vim 稍微高级一些的设置

最近需要在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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,780评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,424评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,397评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,576评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,997评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,945评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,107评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,850评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,625评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,804评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,285评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,613评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,291评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,164评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,963评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,096评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,886评论 2 278

推荐阅读更多精彩内容