美文网首页Vim程序员上古神器Vim
vim 稍微高级一些的设置

vim 稍微高级一些的设置

作者: 粗衣大布裹天涯 | 来源:发表于2017-11-23 17:02 被阅读161次

    最近需要在linux系统下编辑fortran的代码,但是系统自带的编辑器vim本身对fortran的支持不够强大,但是好在vim本身是一个扩展性极强的编辑器,在CSDN上查找到一篇搬运的教程,但是本身没有写全,原链接又时效了,于是倒腾了一上午,结果如下:

    实现了vim对fortran语法高亮的优化

    image.png

    自动识别自由格式,自动折叠特定模块

    image.png

    编辑模式下,按F7自动补全语法结束语句。

    image.png 敲F7 image.png

    PS:本人额外添加了许多类似的模块结束语句补全功能。

    实现方法:

    1.打开vim对Python的支持

    这一步最新版vim已经不需要执行了,因为大家都跨入py3的时代了,并且这个教程内使用到的py2脚本我也已经优化成py3格式了~~~

    这里说的python是指python2+,所以需要用apt从新安装
    输入sudo apt-get install vim-nox-py2 可以安装vim的特定Python支持版本,之后需要切换版本则可以使用sudo update-alternatives --config vim来切换。
    这时输入vim --version | grep python 应该可以看见:

    image.png

    2.打开~/.vimrc文件

    添加如下内容

    "这是建立的vim配置文件,需要移植请拷贝致~.vimrc处。
    " 这行定义了文字编码规则序列
    set encoding=utf-8
    set fileencodings=ucs-bom,utf-8,utf-16,gbk,big5,gb18030,shift-jis,euc-jp,euc-kr,latin1
    set fileencoding=utf-8
    "fortran code improve set
    let s:extfname=expand("%:e")
    if s:extfname==?"f90"
            let fortran_free_source=1
            unlet! fortran_fixed_source
    else
            let fortran_fixed_source=1
            unlet! fortran_free_source
    endif
    let fortran_more_precise=1
    let fortran_do_enddo=1
    "去掉固定格式每行开头的红色区域
    let fortran_have_tabs=1
    "允许折叠
    let fortran_fold=1
    let fortran_fold_conditionals=1
    "折叠方式
    set foldmethod=syntax
    "加载第三方插件
    filetype plugin on
    

    3.在~/.vim/after/indent文件夹内添加如下文件

    文件命名为fortran.vim
    内容为:

    " Vim indent file
    " Language:     Fortran 95, Fortran 90 (free source form)
    " Description:  Indentation rules for continued statements and preprocessor
    "               instructions
    "               Indentation rules for subroutine, function and forall
    "               statements
    " Installation: Place this script in the $HOME/.vim/after/indent/ directory
    "               and use it with Vim 7.1 and Ajit J. Thakkar's Vim scripts
    "               for Fortran (http://www.unb.ca/chem/ajit/)
    " Maintainer:   S閎astien Burton <sebastien.burton@gmail.com>
    " License:      Public domain
    " Version:      0.4
    " Last Change:  2011 May 25
    
    " Modified indentation rules are used if the Fortran source code is free
    " source form, else nothing is done
    if (b:fortran_fixed_source != 1)
        setlocal indentexpr=SebuFortranGetFreeIndent()
        setlocal indentkeys+==~subroutine,=~function,=~forall
        setlocal indentkeys+==~endsubroutine,=~endfunction,=~endforall
        " Only define the functions once
        if exists("*SebuFortranGetFreeIndent")
            finish
        endif
    else
        finish
    endif
    
    
    " SebuFortranGetFreeIndent() is modified FortranGetFreeIndent():
    " Returns the indentation of the current line
    function SebuFortranGetFreeIndent()
        " No indentation for preprocessor instructions
        if getline(v:lnum) =~ '^\s*#'
            return 0
        endif
        " Previous non-blank non-preprocessor line
        let lnum = SebuPrevNonBlankNonCPP(v:lnum-1)
        " No indentation at the top of the file
        if lnum == 0
            return 0
        endif
        " Original indentation rules
        let ind = FortranGetIndent(lnum)
        " Continued statement indentation rule
        " Truth table (kind of)
        " Symbol '&'            |   Result
        " No            0   0   |   0   No change
        " Appearing     0   1   |   1   Indent
        " Disappering   1   0   |   -1  Unindent
        " Continued     1   1   |   0   No change
        let result = -SebuIsFortranContStat(lnum-1)+SebuIsFortranContStat(lnum)
        " One shiftwidth indentation for continued statements
        let ind += result*&sw
        " One shiftwidth indentation for subroutine, function and forall's bodies
        let line = getline(lnum)
        if line =~? '^\s*\(\(recursive\s*\)\=pure\|elemental\)\=\s*subroutine\|program\|module'
                    \ || line =~? '^\s*\(\(recursive\s*\)\=pure\|elemental\)\=\s*'
                    \ . '\(\(integer\|real\|complex\|logical\|character\|type\)'
                    \ . '\((\S\+)\)\=\)\=\s*function'
                    \ || line =~? '^\s*\(forall\)'
            let ind += &sw
        endif
        if getline(v:lnum) =~? '^\s*end\s*\(subroutine\|function\|forall\|program\|module\)'
            let ind -= &sw
        endif
        " You shouldn't use variable names begining with 'puresubroutine',
        " 'function', 'endforall', etc. as these would make the indentation
        " collapse: it's easier to pay attention than to implement the exceptions
        return ind
    endfunction
    
    " SebuPrevNonBlankNonCPP(lnum) is modified prevnonblank(lnum):
    " Returns the line number of the first line at or above 'lnum' that is
    " neither blank nor preprocessor instruction.
    function SebuPrevNonBlankNonCPP(lnum)
        let lnum = prevnonblank(a:lnum)
        while getline(lnum) =~ '^#'
            let lnum = prevnonblank(lnum-1)
        endwhile
        return lnum
    endfunction
    
    " SebuIsFortranContStat(lnum):
    " Returns 1 if the 'lnum' statement ends with the Fortran continue mark '&'
    " and 0 else.
    function SebuIsFortranContStat(lnum)
        let line = getline(a:lnum)
        return substitute(line,'!.*$','','') =~ '&\s*$'
    endfunction
    
    

    4.在~/.vim/ftplugin文件夹下新建

    文件名问:fortran_codecomplete.vim
    (文件本身原本使用的python2语法,我已经优化成py3语法了,并且添加了对program和module块的补完操作)
    内容为:

    " File: fortran_codecomplete.vim
    " Author: Michael Goerz (goerz AT physik DOT fu MINUS berlin DOT de)
    " Version: 0.9
    " Copyright: Copyright (C) 2008 Michael Goerz
    "    This program is free software: you can redistribute it and/or modify
    "    it under the terms of the GNU General Public License as published by
    "    the Free Software Foundation, either version 3 of the License, or
    "    (at your option) any later version.
    "
    "    This program is distributed in the hope that it will be useful,
    "    but WITHOUT ANY WARRANTY; without even the implied warranty of
    "    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    "    GNU General Public License for more details.
    "
    " Description: 
    "    This maps the <F7> key to complete Fortran 90 constructs"
    
    " Installation:
    "    Copy this file into your ftplugin directory. 
    
    
    python3 << EOF
    import re
    import vim
    
    class SyntaxElement:
        def __init__(self, pattern, closingline):
            self.pattern = pattern
            self.closingline = closingline
        def match(self, line): 
            """ Return (indent, closingline) or (None, None)"""
            match = self.pattern.search(line)
            if match:
                indentpattern = re.compile(r'^\s*')
                variablepattern = re.compile(r'\$\{(?P<varname>[a-zA-Z0-9_]*)\}')
                indent = indentpattern.search(line).group(0)
                closingline = self.closingline
                # expand variables in closingline
                while True:
                    variable_match = variablepattern.search(closingline)
                    if variable_match:
                        try:
                            replacement = match.group(variable_match.group('varname'))
                        except:
                            print("Group %s is not defined in pattern" % variable_match.group('varname'))
                            replacement = variable_match.group('varname')
                        try:
                            closingline = closingline.replace(variable_match.group(0), replacement)
                        except TypeError:
                            if replacement is None:
                                replacement = ""
                            closingline = closingline.replace(variable_match.group(0), str(replacement))
                    else:
                        break
            else:
                return (None, None)
            closingline = closingline.rstrip()
            return (indent, closingline)
                
            
    def fortran_complete():
    
        syntax_elements = [
            SyntaxElement(re.compile(r'^\s*program\s+(?P<name>[a-zA-Z0-9_]+)'),
                          'end program ${name}' ),
            SyntaxElement(re.compile(r'^\s*type\s+(?P<name>[a-zA-Z0-9_]+)'),
                          'end type ${name}' ),
            SyntaxElement(re.compile(r'^\s*interface\s+'),
                          'end interface' ),
            SyntaxElement(re.compile(r'^\s*module\s+(?P<name>[a-zA-Z0-9_]+)'),
                          'end module ${name}' ),
            SyntaxElement(re.compile(r'^\s*subroutine\s+(?P<name>[a-zA-Z0-9_]+)'),
                          'end subroutine ${name}' ),
            SyntaxElement(re.compile(r'^\s*\w*\s*function\s+(?P<name>[a-zA-Z0-9_]+)'),
                          'end function ${name}' ),
            SyntaxElement(re.compile(r'^\s*((?P<name>([a-zA-Z0-9_]+))\s*:)?\s*if \s*\(.*\) \s*then'),
                          'end if ${name}' ),
            SyntaxElement(re.compile(r'^\s*((?P<name>([a-zA-Z0-9_]+))\s*:)?\s*do'),
                          'end do ${name}' ),
            SyntaxElement(re.compile(r'^\s*select case '),
                          'end select' )
        ]
    
        cb = vim.current.buffer
        line = vim.current.window.cursor[0] - 1
        cline = cb[line]
    
        for syntax_element in syntax_elements:
            (indent, closingline) = syntax_element.match(cline)
            if closingline is not None:
                vim.command('s/$/\x0D\x0D/') # insert two lines
                shiftwidth = int(vim.eval("&shiftwidth"))
                cb[line+1] = indent + (" " * shiftwidth)
                cb[line+2] = indent + closingline 
                vim.current.window.cursor = (line+2, 1)
    EOF
    
    nmap <F7> :python3 fortran_complete()<cr>A
    imap <F7> ^[:python3 fortran_complete()<cr>A
    
    

    相关文章

      网友评论

        本文标题:vim 稍微高级一些的设置

        本文链接:https://www.haomeiwen.com/subject/pljzvxtx.html