沒穿方服

索引

顯示╱隱藏內文
左邊會顯示 mark 位置

在沒有規則的位置間移動

雖然 ``ga 等跳轉指令有不少,但是要跳到沒特殊意義的位置——例如「剛剛有看到,不過具體看到什麼完全沒印象」——這種情形除了 mark 應該也沒有更好的解了。

於是用 mamb、……放了幾個 mark,結果更難用:

  1. 視覺上看不見哪兒有 mark,所以不知道某 mark 的位置,比方 `b 會跳到哪裡去。
    事實上按了 ` 之後,就會卡在不知道要按哪個字母。
  2. 不知道哪些 mark 已經用過,例如下 md 的時候要擔心會不會蓋掉舊的。
    事實上按了 m 之後,就會卡在不知道要按哪個字母。

ShowMarks plugin

ShowMarks 會利用 sign column(在行號左邊的一欄,預設不會有)顯示 mark 的位置。雖然是很老的 plugin,不過先進替代品從缺,功能也冇問題,就用吧。

唯一不滿是用了 CursorHold autocmd 在閒置時自動開啟(如果開啟檔案後,突然畫面左邊冒出一條 bar,就是這功能),所以 fork 一份 bootleq/ShowMarks,加上 let g:showmarks_auto_toggle=0 即關閉它。

wokmarks.vim plugin

wokmarks.vim 提供不必記憶 mark 名稱(例:a-z)的操作。指令會變成 Prev、Next、Set、Toggle、Kill 這樣的感覺;另外設置 mark、在 mark 間移動時也會在狀態列顯示訊息。

具體設定

gist: 738007 - [vimrc] ShowMarks and wokmarks.vim- GitHub

完成後,看到有感覺的行就按 mm 放標記(sign column 會自動開啟),覺得這行沒用就按 mm 取消標記,想瀏覽標過的地方就按 mjmk 前後移動。若新開的檔案沒有顯示任何標記,就按 momt 顯示。

限制

因為使用 Vim 本身的 mark,所以 mark 總數有限(a-zA-Z,其中大寫的又不適合單一檔案使用)。

如果真的需要 26 個以上,也有一些 plugin 會另行記錄標記資訊,不過「不用 Vim 的 mark」是否比較好,就要考慮一下了。

煩惱許久的需求—— git difftool, open all diff files immediately, not in serial - Stack Overflow。具體狀況是:用 git-difftool 呼叫 vimdiff 看變更,會重複「2 files to edit ~ 自動進入 Vim 比較一個檔案 ~ 手動離開 Vim」這個流程,有 10 個(變更的)檔案就會重複 10 次,而且中間不知道怎麼停下來……

原文的解法我沒試成功,而是靠之前寫的 function,加上在 .zshrc 裡設定:

alias gitdiffall='vim -p `git diff --name-only` -c "tabdo GitDiff" -c "tabfirst"'

之後只要輸入指令 gitdiffall 即可。

檔案改到一半發現自己失憶,忘記改了哪些東西,只好跟上次 git push 的狀態比較看看了。

正統作法是在 shell 下指令 git diff,或下 git difftool 用 vimdiff 分割視窗顯示,如下圖,前者在檔案多時容易快速概觀,但單一檔案時還是 vimdiff 方便。

狀況單純的話也很好用 缺點是一次只 diff 一個檔案

目前看到兩個插件 hypergitvcscommand 都可以在 Vim 裡直接顯示 diff 結果,前者是 git-diff 型式,後者是 vimdiff 型式(取出舊版內容,再切割視窗作 vimdiff)。我的需求比較接近後者,但又不想裝整支 vcscommand,於是擅自取出原始碼,改寫進 vimrc。

用到的 git 指令

  • git rev-parse --show-prefix
    若指令來自 git 的子目錄,輸出該目錄對 .git 的相對路徑。
  • git log -1 --format=format:%s\ %n%h' -- '%an' -- '%ai\ '('%ar') HEAD
    顯示 HEAD 所在的一條 log,輸出格式為 [主題] \n[hash 縮寫] -- [作者] -- [日期] ([相對日期]),
    例如 fefe3c8 -- bootleq -- 2010-08-30 18:14:37 +0800 (13 hours ago)
  • git show HEAD:some_path/some_file
    顯示 HEAD 中 some_file 的檔案內容。

原始碼

gist: 558647 - [.vimrc] git diff.

功能說明

  • GitDiff 指令

    輸入 :GitDiff 即可切割視窗顯示目前檔案的 HEAD 版本,可加一個參數指定更早的 HEAD,例如 :GitDiff 99 取得 HEAD~99 版本。顯示後會進入 diff 模式。另外可用 echo t:git_diff_info 顯示該 commit 的簡易資訊。
    GitDiff t:git_diff_info 顯示
    註:指令取的 HEAD~ 並無限制「有變更當前檔案」所以可能往前跳好幾個 HEAD 也看不出變化。
  • MyDiffOff 指令

    因為預設的 :diffoff 指令可能會把本來的 foldmethod 等 diff 相關選項蓋掉,所以改用 :MyDiffOff 來關閉 diff。
    不過也只是設回我的預設值,沒有真的建立暫存/重設機制。
  • GitDiffOff 指令

    進入 :GitDiff 後,用 :GitDiffOff 快速恢復到原始狀態。(目前只支援從兩視窗的狀態復原)

Vim 簡短入門提示

艱難學習至今,提出三項。


<Esc> 難按

切換 normal mode 是最硬的基本技,<Esc> 不快你立馬被打爆。
可以用 <C-[> 取代,或配合 <Leader>(預設是 \,Enter 鍵是一字或 L 型會影響其手感)或 <LocalLeader> 鍵。
例:按兩下 , 即進入 normal mode

let maplocalleader = ","
noremap  <LocalLeader>, <C-\><C-N>
noremap! <LocalLeader>, <C-\><C-N>

早裝早輕鬆的插件

GSession 配合 git branch(不過 Windows 下比較難使用 git)是管理 session 的快樂方案。參考 Vim-Taiwan 上的討論串
因為多檔編輯需求大,但 session 操作繁瑣,所以認定首要插件就此一支。


學會查 help

大量招式(睇 :help quickref)不是單純常用就能學會的,已知指令也值得翻文複習。畢竟軟體演變下來,誰比較懂得善用靠的還是知識。

  • 更新 help

    如果 Vim 版本很舊,可考慮更新整個 $VIMRUNTIME(包含 help 以外的各種檔案,所以會花點時間)。
    以下為系統有 aap 支援的情形:
    :!cd $VIMRUNTIME
    :!aap -f ftp://ftp.vim.org/pub/vim/runtime/main.aap fetch
    另外安裝插件等操作動到 doc 檔案時,也需要重建一下 tag(讀 help 時用來 jump 的、類似超連結的東西)
    :helptags ~/.vim/doc
    (其中 ~/.vim/doc 可能是其他位置,即放說明文件的地方)
  • 益於求助的 map

    預設 <F1> 等同於 :help 其實不易利用,可改為:

    • 於 normal mode 查詢游標所在單字的說明。
    • 於 visual mode 查詢選取文字的說明,對付 'sb' 這般有引號的項目較方便。
    • 以上若先按 <LocalLeader> 則將說明開在新分頁。
    map  <F1> :help <C-R>=expand('<cword>')<CR><CR>
    map  <LocalLeader><F1> :tab help <C-R>=expand('<cword>')<CR><CR>
    xmap <F1> :<C-U>call RegStash(1)<CR>gvy:let b:tempReg=@"<CR>:call RegStash()<CR>:help <C-R>=b:tempReg<CR><CR>
    xmap <LocalLeader><F1> :<C-U>call RegStash(1)<CR>gvy:let b:tempReg=@"<CR>:call RegStash()<CR>:help <C-R>=b:tempReg<CR><CR>
    (其中 RegStash 來自暫存與還原 register 的 function,也可移掉)

    在 help 文件中,預設可用 <C-]> 跳到游標所在單字的說明(類似超連結),按 <C-O><C-I> 則是在次次跳轉的位置來回(類似上一頁、下一頁),這裡也可稍微 map:

    • 若檔案唯讀(help 文件皆唯讀),就讓 Enter 也可跳進 tag、BS 也可回上一頁。
    • Alt-LeftAlt-Right 當成上一頁、下一頁使用。
    nnoremap <expr> <CR> &modifiable ? "i<CR><C-\><C-N>" : "<C-]>"
    nnoremap <expr> <BS> &modifiable ? "i<C-W><C-\><C-N>" : "<C-O>"
    nnoremap <M-Left> <C-O>
    nnoremap <M-Right> <C-I>

註:以上只是讓動作變簡單,要真正愛用 help,還是要親身體會、自求多福~

部分操作會將相關資訊暫存備用,例如 d 掉的文字會被放進 register 變數,以便之後貼上。

執行 vim script(例如自訂的 map)時若做了這類操作,便可能把本來的 register 等資料蓋掉。以下幾個 function 先將暫存資訊另存,以供 script 結束後還原。

原始碼

gist: 555806 - [.vimrc] simple functions to save/restore position, register or mark.

使用例

:call PosStash(1)   " 暫存目前游標位置
:call PosStash()    " 還原游標位置
:call RegStash(1)   " 暫存目前 register
:call RegStash()    " 還原 register
:call MarkStash(1)  " 暫存目前 mark
:call MarkStash()   " 還原 mark