布同:vim插件開發實例和講解


  vim是一個強大的編輯器,以命令行操作的快速性著稱。不過,玩着玩着,感覺也不能解決自己工作中的一些特別的問題。所以現在你可以有三種方法來自定義一些命令,完成自己個性化的需求。下面就來一一嘗試。

【宏命令】

  可以用宏命令來批量處理。不過退出之后就消失了,下次不能再使用,所以這個不是一個永久性的方法。短時解決重復工作是非常高效的。

【自定義命令】

  可以自定義命令,這個也是簡短操作的一個好方法。例如:在gvim下將當前文本去掉重復行,就可以使用以下兩個命令:

:sort
:g/^\(.\+\)$\n\1/d

 如果每次都敲入這兩行命令,估計你也嫌麻煩。可以自定義為一個命令,這樣就可以直接用簡短方式執行了。

:command! Td :sort|:g/^\(.\+\)$\n\1/d

  將上面這一個作為一個獨立行放入vim的配置文件中。window下是Vim\_vimrc,linux下是~/.vimrc文件。這樣啟動vim的時候就會自動定義好這個命令,直接就可以使用了。

  關於command自定義冒號命令,我這里羅嗦幾句講一下。

1.以:command開頭,如果是重新定義,command后加!號。沒有定義過也可以加上。如果需要指定可能的參數個數,可以加上-xargs=n配置項。

2.空格之后緊跟新的命令名字,請以大寫字母開頭,后面的是否采用駝峰命名法取決於你自己。

3.然后就是命令操作的集合了。用|分割多個命令,這里跟平常|在編程中的語義不同,請注意。

  對於這樣短一點的命令可以采用這種方式去做,如果操作太多,那么需要在command后面加入很多代碼,這不是vim想看到的。可以將多余的代碼放入函數中,這是今天我想說的主題。

【插件開發】

插件文件放在\ftplugin類似的目錄中,以.vim為后綴。例如:

// art.vim
if exists("b:did_ftplugin")
  finish
endif

run ftplugin/lisp.vim

setl lw-=if
setl lw+=def-art-fun,deffacts,defglobal,defrule,defschema,
      \for,schema,while

 其中一開始判斷是否已經加載了文件,防止重復加載。然后調用了lisp.vim文件,最后進行了一些操作,還可以繼續定義自己的函數。這就是插件的常見基本結構了。

【開發實例】

首先,加入頭部,防止重復加載。

if &cp || exists("g:loaded_filter")
 finish
endif
let g:loaded_filter = "v1"

   這里你還可以自己修改一下loaded_filter,改為其他變量,這樣就能夠區分你自己的插件了。

然后是定義函數:

func Del(part)
    let s:num = line('$')
    while(s:num)
        let s:str = getline(s:num)
        let s:num -= 1
        let s:str = substitute(s:str, a:part, '', '')
        call setline(s:num + 1, s:str)
        unlet s:str
    endwhile
    unlet s:num
    return
endfunc

   函數都是func開頭,名字大寫字母開頭,可以傳遞參數。我簡單說一下這個函數的功能:

  首先獲取全文行數,放到num變量中。然后調用getline函數,取出0至num-1行的內容,將part部分替換為空字符串,也就是刪除。然后調用setline函數,更新該行的內容為替換之后的內容。這個函數很簡單,作用就是從全文中刪掉一個字符串。要在vim中執行這個函數只需要輸入:

:call Del('j')

  回車之后就會執行。如果提示沒有找到Del函數,可以在配置文件中加入對自定義文件的引用:

source $VIMRUNTIME/ftplugin/filter.vim

   然后重啟vim,再次執行就可以了。

  如果我們想自定義刪除兩個符號之間的內容,那么可以將上面函數substitute中的第二個參數修改為正則表達式,進行匹配和替換就行了。

  這里我要講另外一個實例:

func Uc(flag)
    let s:pre = a:flag[0]
    let s:end = a:flag[1]
    let s:num = line('$')
    let s:count = {}
    while(s:num)
        let s:str = getline(s:num)
        let s:num -= 1
        let s:first = stridx(s:str, s:pre)
        if( s:first == -1)
            continue
        endif
        let s:first += 1
        let s:second = stridx(s:str, s:end)
        if( s:second == -1)
            continue
        endif
        let s:str = strpart(s:str, s:first, s:second - s:first)
        if( has_key(s:count, s:str) )
            let s:count[s:str] += 1
        else
            let s:count[s:str] = 1
        endif
        unlet s:str
    endwhile
    
    for key in keys(s:count)
        echo 'key=' key ',value=' s:count[key]
    endfor
    
    unlet s:pre
    unlet s:end
    unlet s:num
    unlet s:count
    return
endfunc

   這個函數的作用是根據參數字符串part的第一個字符和第二個字符去搜索全文每行,按照匹配到的這兩個字符之間的內容進行統計,計算出重復量,顯示到命令輸入欄的上方。這個功能也可以通過linux下的awk來實現,不過經過這樣自己定義之后的函數可以直接調用,一次開發,多次使用,效率更高。

【總結】

  我想講述的就是這些了,如果你還有更多興趣想學習更多,可以參考vim用戶手冊,是一個pdf的電子書,不用緊張,有很好的中文翻譯版本,其中詳細列舉了vim插件開發的語法。

  你還可以通過:function命令查看現在已經定義的函數,然后:function Del查看Del函數的定義內容,這樣來學習更多的插件編程技巧。

  你還可以通過:help substitute來查看substitute函數的相關文檔,這個文檔一般是英文的。計算機英文只要你堅持看,你會發現他們的措辭很類似,單詞也就是那幾個,比較好掌握。

  你還可以去插件目錄下去閱讀其他插件的源代碼,其中不懂的函數就help一下,然后練習練習就會了,更多插件完全就難不倒你了。

  所以現在你就可以去動手開始做自己的插件了,祝你成功。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM