Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 5608

Mercurialのコミットメッセージをvimで編集するためのあれこれ

$
0
0

hg commitを実行すると、コミットメッセージを編集するためのエディタが起動します。
このエディタにvimを使う場合に、いくつかの設定を行うことでプラスアルファの機能を追加しようという話です。

ありていに言うと committiaがすてきな感じなのでMercurialでも同じようなことができないか、という。

コミット対象のファイルを開く

そのまま開く

コミット時には、以下のようなテキストが一時ファイルに出力され、オープンされます。

HG: コミットログを入力してください。'HG:' で始まる行は無視されます。
HG: メッセージが空のままならコミットを中止します。
HG: --
HG: ユーザ: Iwata
HG: ブランチ 'default'
HG: tortoisehg/hgqt/repotreeitem.py を変更
HG: tortoisehg/hgqt/run.py を変更

このように、コミット対象のファイルがテキスト上に最初から表示されているので、そこにカーソルを合わせて <C-w>f<C-w>gfなどとすることで簡単にそのファイルを開くことができます。

が、カレントディレクトリがリポジトリルートになっていないとこれは使えません。

Mercurial自体はリポジトリルートをカレントディレクトリに設定した状態でエディタを起動してくれるのですが、Windows版のvimだと、ファイルパスを引数に与えて起動した場合カレントディレクトリがそのファイルの親ディレクトリに変わってしまうようです。
なので、この挙動を回避するために、vim/gvimを直接起動する代わりにこんな感じのバッチを起動するようにします。

hgcommit.bat
gvim -c ":e %1"

unified diffを開く

以下のようなfunctionを用意して、ファイルパス上での ;dでunified形式のdiffを表示できるようにします。(同じタブ内でウインドウを分割して表示します)

hgcommit.vim
" カーソル下のファイルに対するdiffをunified diff形式で表示
nmap <buffer> ;d :call ShowHgDiffUnified(expand('<cfile>'))<CR>function!s:find_window(pattern)foriin range(1, winnr('$'))if bufname(winbufnr(i))=~a:pattern
      returniendifendforreturn0endfunctionfunction! ShowHgDiffUnified(path) abort
  letwin=s:find_window('^\[hg diff\]')ifwin==0botrightvnewelse
    execute win . 'wincmd w'endifsetlocalfiletype=diffbuftype=nofile modifiablesilent! %delete
  silent! execute 'file [hg diff] ' . fnamemodify(a:path,':t')silent! execute 'r!hg diff ' . a:pathsetlocalnomodifiableendfunction
  • この辺のvimscriptはMercurialのコミットメッセージを編集する時だけ読み込まれればいいので、起動用バッチで gvim -c ":e %1" -S hgcommit.vimみたいに指定するか、 autocmd FileType hgcommitに引っかければいいと思います。

side by side diffを開く

さらに以下の設定で、同じく ;Dで別タブにvimdiffを表示できるようにします。

hgcommit.vim
" カーソル下のファイルに対するvimdiffを新しいタブに表示
nmap <buffer> ;D :call ShowHgDiffSideBySide(expand('<cfile>'))<CR>function! ShowHgDiffSideBySide(path) abort
  execute 'tabedit ' . a:pathletencoding=&encodingvnewsetlocalmodifiablebuftype=nofile
  execute 'setlocal fileencoding=' . encodingsilent! execute 'file ' . fnamemodify(a:path,':t')silent! execute 'r!hg cat ' . a:pathsilent!1delete _
  execute 'doautocmd BufNewFile ' . a:pathsetlocalnomodifiablewindodiffthisendfunction

コミットメッセージの挿入

GUIクライアントだと、最近入力したコミットメッセージを一覧から選択して挿入する機能があったりします。
正直あまり使いませんが、せっかくなのでこれもUnite sourceとして実装しておきましょう。

hgcommit.vim
" 最近のコミットメッセージを表示するUnite sourcelets:unite_last_messages = {
            \ 'name' : 'last-messages',
            \ 'default_action' : { '*' : 'insert' },
            \ }

function!s:unite_last_messages.gather_candidates(args, context) abort
  let log = system('hg log -r "last(all(), 20)" --template "{desc}\n___SEP___\n"')let encoded = iconv(log,'cp932',&encoding)let splitted = split(encoded,'\n___SEP___\n')return map(splitted, '{
            \ "word": split(v:val,"\n")[0],
            \ "source": "last-messages",
            \ "kind": "word",
            \ "action__text": v:val,
            \ }')endfunctioncall unite#define_source(s:unite_last_messages)
unlet s:unite_last_messages

nmap <buffer> ;m :Unite last-messages<CR>

これは単純に最新20コミットを対象にして検索する例ですが、「authorが自分」などの条件を加えてもいいかもしれません。
Windows + win32mbcs環境を前提にしているので文字コード変換(iconv)をかけていますが、Linux環境でvimのencodingもutf8ならこれは不要です。

TODO

commit --amendへの対応

diffの機能がcommit --amend時には無力なので、そこを何とかする。
と言ってもエディタ側からは通常のコミットなのかamendなのかは分からないので、両方のモードを用意して手動でスイッチする感じ?


Viewing all articles
Browse latest Browse all 5608

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>