Hacking Vim 7.2 讀後心得。
以及一些簡單的筆記、和心得記錄。
Task list: 😄
Hacking Vim 7.2
Ready-to-use hacks with solutions for common situations encountered by users of the Vim editor
這本書大概是講一些比較進階的Vim設定使用的內容。
Table of Contents:
原文 | 中文 |
---|---|
Ch1: GETTING STARTED WITH VIM | #簡介 |
Ch2: PERSONALIZING VIM | #Vim個人化 |
Ch3: BETTER NAVIGATION | #移動 |
Ch4: PRODUCTION BOOSTERS | #增強生產力 |
Ch5: ADVANCED FORMATTING | #進階格式化 |
Ch6: BASIC VIM SCRIPTING | #基本 Vim Scripting |
Ch7: EXTENDED VIM SCRIPTING | #進階 Vim Scripting |
簡介了 Vim 的歷史,從 ex,vi,STEVIE,Elvis,nvi,Vim,Vile。
不過沒提到較新的 neovim。
另外一些比較有趣的編輯器:
在Vim下輸入指令,直接顯示目前的設定檔位置:
:echo $HOME
:echo $MYVIMRC
:echo $MYGVIMRC
gvimrc 主要是輸入一些在GUI特有的設定,最好是能把跟 vimrc的設定分開。
在GUI下輸入,可以打開字型視窗。
:set guifont=*
不同的的作業系統下設定字型的方式有點差異。
" Linux
:set guifont=Courier\ New\ 14
" MSWin
:set guifont=Courier\ New:14
:help guifont "更多的資料
See Also: Setting the font in the GUI
配色在 console,和GUI下,同一colorscheme會有不同的效果, 所以選擇 colorscheme應該要注意。
pass
狀態列可以設定滿多東西的,文件名,格式,文件長度…
:set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYP[HEX=\%02.2B]\ [POS=%04l,%04v]\ [%p%%]\ [LEN=%L]
但這設定完後,不會馬上出現,要設定 statusline的位置在最後兩行,才會出現。
:set laststatus=2 #狀態列在最後第二行
:set laststatus=0 #狀態列關閉
在GUI下,可以設定功能到選單、工具列上。
增加選單
:menu menupath command
menu
的指令就是像 map
把選單映射到一個指令
例如
:menu Tabs.Next <ESC>:tabnext<cr>
從 Vim 7.0開始支援 頁籤 Tabs,每個 Tabs有個別的屬性。
:set tabline tabline-layout " Tabs的狀態列
:set guitablabel " gvim的Tab狀態列
:set cursorline " 顯示cursor line
:highlight CursorLine guibg=lightblue ctermbg=lightgray
" 設定 cursorline 顏色
:set cursorcolumn " 顯示縱向的指標行
:highlight CursorColumn guibg=blue ctermbg=gray
" 設定 cursorcolumn 顏色
:set nocursorcolumn " 關閉cursorcolumn
" 打開行號
:set number
:set nu
:set nonumber
:set nonu
" 預設的行號佔 4個space, 下面指令可以修改預設值
:set numberwidth=`widch`
Vim 7.0 以後有內建的 spell check
:set spell " 打開拼寫檢查
:set spelllang=en_us " 設定拼寫語言
錯字的配色
移動、更正
z=
,可以更正錯誤的拼字。]s
and [s
可以移動到上一個、下一個錯誤拼字使用縮寫來減少重複輸入
:iabbrev myAddr 32 Lincoln Road, Birmingham B27 6PA, United Kingdom
可以在 輸入模式中,輸入 myAddr後,變成之前設定的地址。
:map <C-s> <esc>:w<cr>
把按鍵和指令重新指定。
Keys | Notation |
---|---|
<BS> |
Backspace |
<Tab> |
Tab |
<CR> |
Enter |
<Enter> |
Enter |
<Return> |
Enter |
<Esc> |
Escape |
<Space> |
Space |
<Up> |
Up arrow |
<Down> |
Down arrow |
<Left> |
Left arrow |
<Right> |
Right arrow |
<F1> - <F12> |
Function keys 1 to 12 |
#1, #2..#9,#0 | Function keys F1 to F9, F1 |
<Insert> |
Insert |
<Del> |
Delete |
<Home> |
Home |
<End> |
End |
<PageUp> |
Page up |
<PageDown> |
Page down |
這章說明了各種設定修改的方式。
本章說明在各文件快速移動的方式。遊標移動、在多文件中移動、使用說明文件、搜索、標記。
文件結構的不同,可分為兩種情形:
h
,j
,k
,l
#左、下、上、右{
,}
#段落首、尾g,
g;
#最近修改過的地方,向前,向後(
,)
#句首、句尾w
#下一個單詞首字母b
#前一個單詞首字母e
#移動到單詞末尾單詞(Word)的定義:
由字母、數字、dash(-)、underline(_)組成 以非空白字母組成
Vim無法辨識所有程式的結構,不過C語言預設是可以的。
函數
[[
and ][
: Move backwards / forward to the next section beginning (for
example, start of a function)[]
and ]]
: Move backwards / forward to the next section end (for example,
end of a function)區塊
[{
: Move to the beginning of the block]}
: Move to the end of the block註解
[/
: Move to the beginning of the comment block]/
: Move to the end of the comment blockgd
: 跳到變數定義區段
gD
: 跳到全域變數定義區段
一行的內容過長,超過VIM視窗範圍的話,程式會自動把超出視窗寬的在下一行顯示。
gk
,gj
:會以視覺上的行為主而移動。
Vim的說明文件可以:
:help <keyword>
移動
*
文章內還有一些比較進階的設定。
打開的文件,是存在緩衝區(Buffer)中。
:buffers
: buffer list:buffer N
: jump to buffer N:bnext(bn)
: Next buffer:bprevious(bp)
: Previous buffer像是在 C語言中的 #include
#include "example.h"
在 example.h
上按 gf
,Vim就會把檔案讀入緩衝區
分三種:
找單詞
?example
,命令模式下 /example
可以找單詞n
,N
:在找到的結果向上,向上移動。//
,??
: 上一次搜索的輸入#
,*
: 搜索在遊標上的單詞,向上移動, 向下移動搜索的指令,在Unix系統下有 grep
,MSWin下有 find
,findstr
,
而在 Vim下,有:
:vimgrep /pattern/[j][g] file file2... fileN
j
: 把結果輸入到 quickfix
列表g
: 如果在同一行內有三個符合的結果,則會都顯示quickfix
:clist
:顯示 quickfix
結果cnext(cn)
,cprevious(cp)
:在 quickfix
列表中移動:helpgrep pattern [@LANG]
" @LANG,可以指定說明文件的語言,例子:
:helpgrep completion@en
如果是新增加的文件,可以用下面的指令生成文件tags
:helptags /path/to/doc
有時文件太長,要在個各處移動,標記(Marks)可以在某行前 作記號。例:
通常是會在行號前面,用來標記某一行的符號。
:sign define name arguments
定義標記列顏色
:highlight SignColumn guibg=darkgrey
pass
另一種標記方式,基本上看不到,除非打開標記列表
:marks
: 打開標記列表
ma
: 標記 a
\
a: 移動到
a
:deletemarks markid1 markid2 markid3:刪除標記
:delmarks a f-i 1-4
:刪除 makrs
:delmarks !
:刪除目前buffer所有marks
標號 | 用法 |
---|---|
0-9 | 保留內部使用,通常是最近開啟文件 |
a-z | 本文件使用 |
A-Z | 可以跟文件使用,如果有.viminfo 存檔,下次打開Vim時,還可以使用 |
這一節描述了cursor的移動,搜索、或是在各文件中移動的方式。
這一章會簡介一些能增加效率的工具。
建立模版 Template ,減少重複性的工作。
應該可以分為兩種行為
#include
),檔尾方法:
$VIMHOME
/templates/下加入新的 file-type.tpl
,像是 html.tpl
autocmd
在開啟新檔時,自動讀入模版。前面有提為的功能 縮寫可以用來快速輸入一些結構,像是迴圈、或是snippets
更完整的功能,有人編寫了完整的 plugins。
https://vimawesome.com/plugin/snipmate https://www.vim.org/scripts/script.php?script_id=2540 https://github.com/garbas/vim-snipmate
比較 http://vim-wiki.mawercer.de/wiki/topic/text-snippets-skeletons-templates.html
除了 snipMate以外,還有其他plugins有snippets的功能
UltiSnipsby HOLGER RAPP36216612 UltiSnips - The ultimate snippet solution for Vim. Send pull requests to SirVer/ultisnips!
neosnippet-snippetsby SHOUGO1972908 The standard snippets repository for neosnippet
vim-snippets * by HONZA POKORNY25449499 * vim-snipmate default snippets (Previously snipmate-snippets) * 這個是 snippets程式片段檔的集合
產生程式中的所有關鍵字、函數名、…
Tag List的產生要用外部的程式,常見的有:
用法,可以快速跳到函數定義的地方。
### 4.2.1 Tag List 的其他用法
除了用來找函數、和變數外,還有其他用法。
:help tags
分三種
4.3.1 已知單詞的自動補全
C-p
C-n
在打完的前兩個字母後按,
會出現auto complete的選項,向前、或向後
利用已有的字典作 autocomplete
設定字典檔
:set dictionary+=/path/to/dictionary/file/with/words
C-x C-k
x是進入autocomplete模式, k是從字典中找相近的單字。
其他模式:
C-x C-o
進入 Omnicompletion 模式
pass
把前面多種autocomplete模式整合
這個指令可以找到,CleverTab()
help ins-complete
可以用 Tab
來選取需要的選項。
用來錄製指令
Vim保存了許多資訊,分成幾種:
保存目前視圖、會話
:mkview file
:mksession file
:set viewdir=$HOME/.vim/views " 設定視圖存放的目錄
" 載入視圖方式
$vim -S Session.vim
:source Session.vim
:loadview View.vim
pass
pass
把段落、或是區塊 多行折疉成一行
打開遠端的文件
:Nread ftp://user@server/path/to/file
:Nwrite server user passwd path/to/file
將文件重新排版的過程。
例:將長行自動斷行
gpap
向左、 置中、向右對齊
在 Markdown、reST中,H1、H2的語法可以寫成:
Level1
======
Level2
------
### Level3
這邊利用接鍵組合,可以快速在文字下加上相同長度的 =
,或-
像在 New Heading
上按 yypVr=o
用函式快速加入 lists的格式
排版良好的程式碼,對方便閱讀很有幫助。
前面幾小節 介紹了縮排的幾個方式。
:set ai
: 會依前一行的設定,縮排之後的文件:set si
: smarter than autoindent要貼程式碼時,可以用下面的指令,讓貼上的程式碼排版不會跑掉。
:set paste
:set nopaste
:set pastetoggle
使用 其他程式來排版,像是 Indent,Berkeley Par,Tidy
" 設定 indent
:set equalprg=program
Tidy 是用來排版 XML,HTML 文件的工具。
" XML 文件
au FileType xml exe ":silent 1,$!tidy --input-xml true --indent yes -q"
" HTML 文件
au FileType html,htm exe ":silent 1,$!tidy --indent yes -q"
本章介紹了一些排版的方式
Vim可以透過 VimScript使用許多功能,且容易分享, 而且還可以支援外部語言,如python,ruby,perl,lua…
syntax-color scheme會將程式中的 關鍵字以不同的顏色表示,
不僅使程式易讀、而且可以容易發現打錯的字。
語法上色,先要找出關鍵字,然後設置對應的顏色,以下是例子:
:syntax match myComments "/\*.*\*/"
:syntax keyword myVars x y
:syntax match mySymbols "[{}();=]"
:syntax keyword myKeywords if return
:highlight myVars ctermfg=red guifg=red
:highlight mySymbols ctermfg=blue guifg=blue
:highlight myKeywords ctermfg=green guifg=green
:highlight myComments ctermfg=yellow guifg=yellow
像是注釋之類的,一整個區塊要上色的,例子如下:
:syntax region myComments start=/\/\*/ end=/\*\//
pass
除了個別指定顏色外,也可以用配色方案中定義的顏色, 這樣的話,可以隨著 color scheme改變語法顏色。
除了自已開發功能外,也可以在網路上找別人寫好的plugin回來安裝
依腳本的功能,有:
安裝 VimScript 的方式,最基本的就是把 .vim
丟到 $HOME/.vim/
的目錄下,
不過,有些 plugins 檔案太多,於是目前就有一些比較方便的安裝管理方式:
.vim
,或是壓縮檔:直接(解壓)放到 $HOME/.vim/
目錄下$vim something.vba
:so %
安裝:PluginInstall
安裝移除的方式就直接和安裝方式相關,
通常是把 .vim
下的檔案移除,再把 vimrc內的設定去掉。
寫自己想要的功能。
在開發腳本時,可能要注意各個Vim的版本,在各平台上可用的功具、函數可能也不用, 在寫腳本時,要注意,另外一些功能最好也保留可以讓用戶修改的功能,保留彈性。
VIM下只有字串、和數值
數值包括:
例:
:echo 10 + 0x10 + 010
字串
" " , ' '
\n
是換行(new line),\r
是 Return ,\t
是Tab, \<CR>是 Return
其他的符號 參照下面連結定義變數,都是用 :let
來賦值的
:let myvar=somevalue
:let myvalue=100 "數值
:let mystring="this is a test" " 字串
型值會自動轉換
:let myvar='123'
echo myvar-23 " 會顯示100
字串經過數值運算會轉成數字。另有,型值強制轉換函數 string()
:let myunber=mystring+0
:let mystring=string(mynumber)
List
list是一群變數的集合。 list[0]是第一個元素。
:let mylistvar1 = [1, 2.7, 0x04, "six", myvar, [1,2,3]]
字典 Dictionary
字典是 key-value pairs,鍵和鍵值的互相參照的序列。
:let mydictvar2 = {1: "one",2: "two","tens":{0: "ten",1: "eleven"}}
key不一定是數值,也不需要照順序。
函式
:let Myfunrefvar= function("Myfunction")
:echo Myfunrefvar()
刪除函數
delfunction function-name
函數中使用的變數的 變數可視範圍 Scope 變數前的字母,代表變數的作用區域。
Vim中的注釋是以引號開始 \”
let g:sum=0
function SumNumbers(num1,num2)
let l:sum = a:num1+a:num2
"check if previous sum was lower than this
if g:sum < l:sum
let g:sum=l:sum
endif
return l:sum
endfunction
" test code, this will print 7 (value of l:sum)
echo SumNumbers(3,4)
" this should also print 7 (value of g:sum)
echo g:sum
See Also:
If條件式
if condition1
code-to-execute-if-condition1-is-true
else
if condition2
code-to-execute-if-condition2-is-true
endif
endif
See Also:
:help if
向下翻,還有 while, for, try , catch, throw,final
List, Dic 的 CRUD
[CRUD」分別為 Create, Read, Update, Delete
Create
:let mylist = [1,2,3,"cat", myvar1]
:let mydicfruit = {'banana':'yellow','apple':'green','orange':'orange'}
Read
:echo mylist[0],mylist[-1] " 1 , cat (-1是最後的一個值)
:echo mydicfruit['banana'] " yellow
" 如果 key是[0-9][a-zA-Z][_]的話
:echo mydicfruit.banana " yellow
Update
:let mylist[0]=99 "
:let mydicfruit['banana']='green' "
Delete
"用 unlet
:unlet mylist[0]
:unlet mydicfruit['banana']
" remove()
:call remove(mylist,2)
其他操作
:let mylist3 = mylist1 + mylist
:let mylist4 += [5,6,7,8]
" extend() 會把兩個 list 相加
:call extend(mylist3,mylist4)
:echo myilst3 " mylist3會變成 mylist3 + mylist4, mylist4 不變
" add() list4 加進 list3,變成 list3 的一個元素
:call add(mylist3,mylist4)
See Also:
:help Dictionary, List
:help get(), has_key(), items(), keys(), values()
:help add(), extend(), remove()
For Loops
for item in mylist
call remove(mylist, 0)
endfor
While Loops
:let lnum = 1
:while lnum <= line("$")
:call FixLine(lnum)
:let lnum = lnum + 1
:endwhile
See Also:
:help break
: 離開 loop:help continue
: 開始下一個loopfunction Name (arg1, arg2, ... argN) keyword code-to-excute-when-func-call endfunction
keyword
a:000
代表所有 argX的集合Scope
通常函數是local的,可以在函數前加 g:
以代表全域函數。
這邊參照
a:0
: 參數個數a:1
: 第一個參數名字,其他以此類推 a:2, a:3…See Also:
* :help function-argument
* :help local-variables
* :help function-lsit
VimScript 的安裝、移除,管理。
基本的資料型態、結構、操作。
本章會介紹 Script的結構,技巧、如何除錯、使用其他外部語言。
腳本前最好加上一個檔頭,說明腳本的一些基本資料。 例:作者、日期、版本,以及 著作權授權聲明。
像是:
" myscript.vim : Example script to show how a script is structured.
" Version : 1.0.5
" Maintainer : Who Who <who@what.com>
" Last modified : 01/01/2007
" License : This script is released under the Vim License.
腳本在執行前,最好先檢查腳本是否正常載入,以免發生問題。
ex: 如果腳本載入不成功,會先把函數先缷載, 把loaded_myscript(是不是要載入腳本)設成true,
if exists("loaded_myscript")
delfunction MyglobalfunctionB
delfunction MyglobalfunctionC
endif
let loaded_myscript=1
腳本的開頭可以放設定,如:顏色,路徑… 或是一些設定使用者已有原本的設定, 可以檢查是否已有原本的設定值,再決定要不要取代原本的設定。
修改按鍵設定,尋找是否有舊的設定,決定取代、或建立新的設定。
這邊有些新的代碼:
hasmapto()
: 檢查是否有maping 對映到你的程式<unique>
: 檢查 mapping是否唯一<Leader>
: 前導符號,用來開始一些功能的快速鍵。<Leader>
會被 全域的 Leader 覆蓋<Plug>
: 建立一個全域、唯一的Mapping。 這樣就不會和全域變數中的其他函數衝突See Also:
:help <SID>
: Script ID ?:help <Plug>
:help
script-local`s:MyfunctionA
: 前綴的 s
把函數的範圍限定在 script 內。
設定函數的正確的Scope,才不會發現意料之外的問題。
完整腳本的例子:
pass
See Also:
:help 'write-filetype-plugin'
:help 'write-compiler-plugin'
:help 'write-library-script'
Gvim 和 vim有不少不同的地方,如何知道目前執行的是哪一個版本?
if has("gui_running")
"execute gui-only command here"
endif
See Also:
:help 'feature-list
作業系統間的不同:路徑、檔案存取權限、…
if has("win16") || has("win32") || has("win64")|| has("win95")
" do windows things here
elseif has("unix")
" do linux/unix things here
說明文件內的例子:
See Also:
:help 'feature-list
主版號.副版號.補丁編號
if v:version >= 702 || v:version == 701 && has("patch123")
" code here is only done for version 7.1 with patch 123
" and version 7.2 and above
endif
:if has("patch-7.4.123")
視窗的寬度不少可能超出 80,如果內容太長, 需要函數偵測、防止出錯。
-D
: 例如, Vim -D something.txt
,可以印出除錯訊息
:debug
用來除錯的命令。
基本上就是,設立中錯點、印出數值,除錯。
依之前的安裝多樣的方式,發布腳本的方向也很多樣。
要確定有安裝 VimBall
制作Vimball 的命令是:
:[range]MkVimball filename.vba
中間填入需要檔案的路徑、其他設定後。
:MkVimball myscript.vba
打包
Vim說明文件的寫法。
腳本寫好了以後,好的說明文件也是很重要的一部分。
Vim的說明文件,基本上是普通的 text,加上一些記號
First Line
*myscript.txt* Documentation for example script myscript.vim
文件的第一行,開頭字符號一定要是 \*
,兩個\*
中間是文件檔名, 後面是文件簡述
這邊用書上的例子:
*myscript.txt* Documentation for example script myscript.vim
Script : myscript.vim - Example script for vim developers
Author : Kim Schulz
Email : <kim@schulz.dk>
Changed : 01/01/2007
=============================================================
*myscript-intro*
1. Overview
This document gives a short introduction to the example
script myscript.vim.
This script is made as an example for vim users on how to
structure a simple vim plugin script such that it is easy
to read and figure out.
The following is covered in this document:
1. Overview |myscript-intro|
2. Mappings |myscript-mappings|
3. Functions |myscript-functions|
4. Todo |myscript-todo|
=============================================================
\*
myscript-intro\*
是連結目標,可以用 :help 'myscript-intro'
跳到這\|
myscript-intro\|
建立類似超連結功能,能快速跳到連結目標\>
Code here\<
中間的是Code寫好文件後,執行:
:helptags docdir
" docdir 是指向你的文件 `PLUGIN/doc`
See Also:
:help 'help-translated'
輸入 :version
和以看到目這的Vim技援的外部功能
像是這些,+lua,+perl,+python,+python3,+ruby,-tcl
或是輸入指令,是是否有支援。
:echo has("perl")
pass
這邊只看一下比較熟的python。
單行
:python3 print("This is Python3")
多行
:python3 << *endpattern*
some statement here
and here
*endpattern*
" endpattern : 像是 EOF
Vim 的的 vim
模組,可以讀取vim的資訊
import vim
window = vim.current.window
window.height = 200
window.width = 10
window.cursor = (1,1)
See Also:
下面的命令可以用來獲取所有的可用函数列表:
* :help 'python-vim'
pass
pass
Vim game,發 mail,twitter,IRC…
或是 設定成 IDE
:help compiler
:help quickfix
參考 http://vim.wikia.com/wiki/Use_Vim_like_an_IDE
Vimrc是 Vim 所有設定存放的檔案,隨著時間 Vimrc可能會變的越來越大,而以維護。
:set nocompatible
: 把vim設成不相容模式,能開啟比較多的功能。"
開頭的注釋,可以讓區段的功能容易了解修改source
讀進程式Vim Setup system : Vim Setup system - persistent setup directly in vim
這個plugin讓vim的設定,有選單的可以直接設定,設定完了,再存回 .vimrc
有GUI來設定,的確是方便了一些。
把vim的設定放在網路上,可以方便在多台機器間轉移。
這邊是用 netrw
來讀寫網路上的設定檔。
參考書藉