沒穿方服

封存

顯示╱隱藏內文

把 git-diff 的差異開在 Vim 分頁裡,也可以指定要看的版本,用 Vim 查閱 commit 歷史。
bootleq/vim-gitdiffall - GitHub

gitdiffall 指令

zsh 呼叫 gitdiffall 這個指令(目前是用 ruby 寫的,需要系統能跑 ruby)

gitdiffall --help

參數跟 git diff 大致一樣。

查看某個 commit 改的東西

想知道 1836777 這個 commit 改了些什麼。

log graph

使用 gitdiffall @1836777,會比較 1836777 和它的前一個 commit。
註:前一個 commit 不一定是 1836777^,而是從 git log 取出的前一項,這是為了提供更線性的用法。

指定看一個 commit

就會開在 Vim 裡面。

開了 7 個分頁

這時可以下 :GitDiffInfo logs(同 :GitDiffInfo 不加參數)看 git log。
但是在 diff 進行中,比較常用的可能是 :GitDiff(同 :GitDiffInfo log,注意參數是 log 不是 logs,後面會說明)。

GitDiff 只顯示一個 log

看完請用 :GitDiffOff 來關閉 diff,確保幾件事:
1. 跳回編輯該檔案的目前版本。
2. 還原比較前的 diff 相關 option(Vim 內建的 :diffoff 會設回預設,不一定是原來的值)。

看完 1836777,想看下一個 commit,因為剛才有顯示 Shortcut for this commit is 7,所以只要 gitdiffall 6 就行了。

看下一個 commit

看現在改了什麼

以下圖來說,gitdiffall 會打開兩個紅色的檔案;
gitdiffall --cached 會打開綠色的。

--cached 和不加任何 revision 的情況

以前寫的將複數 git diff 以 vim 分頁一次開啟,現在可以用 gitdiffall 取代了。

在 Vim 裡使用 GitDiff

在 Vim 裡面也可使用 :GitDiff,會比較目前檔案和它的某個版本,這時就不需要 ruby 了。
參數跟 gitdiffall 類似,也稍微支援自動完成。

Vim 裡的指令也能自動完成

Diff 中可以用 :GitDiffInfo 看比較範圍內「全部 commit」的 log,
加上參數 :GitDiffInfo log 可以看「最相關的一個 commit」的 log(跟前述「GitDiff 時再呼叫 :GitDiff」效果一樣)。

GitDiffInfo 會顯示多個 log

GitDiff 另外支援一個用法,就是 revision 的部分使用 +<n> 的型式,有別於 <n> 是找前一個 commit, +<n> 會找「包含目前檔案」的前一個 commit,可以避免 <n> 找不到變更的情況。

例如 :GitDiff +1

快速答案是「一元運算子」。


NOT matter 要寫成 ! matter 還是 !matter 這個問題……
很長一段時間我是用前者,多個空白比較明顯,不會漏看驚歎號。


  1. ruby 文件 not 運算子的範例! mep(! false) 也有空白,我想就是求明顯、清楚。

  2. Kohana framework 的 Conventions and Style 也有類似考量:

    The ! (bang) character must have a space on either side to ensure maximum readability.

    ! 的兩邊都必須有一個空白,以確保最大可讀性。』
    註:這一章是講括弧用法,所以是說 if ( ! $foo)if (!$foo) 的情況。

  3. 不過我發現別人的寫法,絕大部分都是不空白的 !matter 風格。
    我已經沒印象上次看到 ! matter 是何時了。

    我也到 PTT ruby 板問了一下

  4. 沒有明確出處,但找到一些敘述,一般不空白的理由是「Unary operation(一元運算子)後面不加空白」。
    就像 -4 不會寫成 - 4

  5. 更精確地說是「一元運算子和它的運算元之間」不加空白。
    就像這個 NetBeans 選項 Bug 135699 – Use option "space between unary operator and operand"

  6. 最後在 Douglas Crockford 的 JS Code Conventions 看到更具體、可以照做的規範:

    No space should separate a unary operator and its operand except when the operator is a word such as typeof.

    『一元運算子和它的運算元之間,不該有空白,除非該運算子是一個 word,例如 typeof。』


其實我已經改用 !matter 一段時間了。 仍然懷疑 ! matter 沒有錯,但眼前還是解決風格一致的問題先了。

Group 是什麼

cycle.vim 搜尋相關候選字時 (例如目前是 true,應該要找到 false),會在一連串的 group 中查詢; 每個 group 是由 items 和 options 組成,以下便是一個簡單 group:
{ 'items': ['true', 'false'], 'options': {} }
如果想讓 foo 變成 bar,增加一個 items 為 ['foo', 'bar'] 的 group 就可以了。


怎麼設定 group

使用中的 groups 會存在 cycle_groups 這個變數,可以用 :echo string(g:cycle_groups) 查看; 但是這東西比較繁瑣,所以不建議直接修改它的值。

比較好的方式是在 .vimrc 定義 g:cycle_default_groups 這個變數, cycle.vim 啟動時會自動解析它,把需要的 group 都建好。

具體例子如下:

let g:cycle_default_groups = [
      \   [['true', 'false']],
      \   [['yes', 'no']],
      \   [['on', 'off']],
      \   [['+', '-']],
      \   [['>', '<']],
      \   [['"', "'"]],
      \   [['==', '!=']],
      \   [['0', '1']],
      \   [['and', 'or']],
      \   [['in', 'out']],
      \   [['up', 'down']],
      \   [['min', 'max']],
      \   [['get', 'set']],
      \   [['add', 'remove']],
      \   [['to', 'from']],
      \   [['read', 'write']],
      \   [['save', 'load', 'restore']],
      \   [['next', 'previous', 'prev']],
      \   [['only', 'except']],
      \   [['without', 'with']],
      \   [['exclude', 'include']],
      \   [['width', 'height']],
      \   [['asc', 'desc']],
      \   [['是', '否']],
      \   [['上', '下']],
      \   [['男', '女']],
      \   [['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
      \     'Friday', 'Saturday'], ['hard_case', {'name': 'Days'}]],
      \   [['{:}', '[:]', '(:)'], 'sub_pairs'],
      \   [['(:)', '「:」', '『:』'], 'sub_pairs'],
      \ ]

可以只為特定檔案類型設 group 嗎

cycle_groups 可以分成 global 和 buffer 兩個 scope(作用範圍)的版本,分別是 g:cycle_groupsb:cycle_groups 兩個變數。 搜尋的時候會以 buffer 版為優先,你可以讓 "get" 在 html 類型的 buffer 中轉為 "post",在其他類型 buffer 中則轉為 "set"

設定方式是在 .vimrc 定義 g:cycle_default_groups_for_{filetype},其中 {filetype} 表示想生效的檔案類型。
例如 html 專用的設定是:
let g:cycle_default_groups_for_html = [ ...(後略)

註:可以用 :echo string(b:cycle_groups) 檢查設定。


調整 group 行為

Group 的行為可以用 options 微調。目前(version 0.1.0)支援的選項如下:

  • name

    名稱,目前沒什麼用,只有處理衝突時(在多個 group 都有搜尋到目標字時)會顯示一下。

  • match_case

    搜尋候選字時,大小寫預設是不計的,所以 TruetruetrUe 都會被 cycle,只要設定其中一個即可。
    反之若要限制大小寫相符才 cycle,就要設定這個選項。

  • hard_case

    預設情形會保留關鍵字的大小寫位置,也就是 true/false 互換時,True 會變成 FalsetRUe 會變成 fALse
    這個選項可以停用此功能,互換時「若設定中是寫 fAlse,就一律換成 fAlse」。

  • sub_tag

    如果開啟這個選項,cycle.vim 會搜尋成對的 xml 開啟/結束標籤,有的話就一起 cycle 掉。
    例如 <EM>example</EM> 可以變成 <STRONG>example</STRONG>

  • sub_paris

    這個比較特別,它是 sub_pairend_withbegin_with 三個選項的簡易寫法,具體請看 doc。(建議用 sub_pairs 即可)

    [['(:)', '「:」'], 'sub_pairs'] 為例, 各個 item 會由 ":" 拆開, (:) 會拆成 「:」 會拆成
    cycle.vim 處理 "(" 時,會搜尋成對的 ")",若有的話就一起 cycle,
    例如 請保密) 可以變成 請保密」


具體要怎麼設定選項(options)

設定 group 時,每個 group 的第一個參數是 items,之後就都是 options 了。
支援以下各種型式:

  • [['true', 'false']] - 沒有 options
  • [['true', 'false'], {'match_case': 1}] - 以 hash 型式指定 options
  • [['true', 'false'], 'match_case'] - options 可以是字串,cycle.vim 會把它轉成 hash,hash 的預設值依各個 option 而不同,此處 'match_case' 的預設值為 1
  • [['true', 'false'], 'match_case', {'name': 'BOOL', 'sub_tag': 1}, 'hard_case'] - 字串和 hash 混著用也沒關係

你說完了沒

這篇應可滿足一般使用,我自己用到的也差不多這樣了。
在 doc 裡一些比較深入、低階的操作也有介紹,需要的話可以參考看看。