VimプラグインのQFixHowmでTODO管理する際の設定、操作メモ

QFixHowmはEmacsのhowmと同等の機能を、Vim上でプラグインとして提供するものです。
QFixHowmを使うことでローカルにwiki形式で情報を整理したり、予定やTODOを管理できます。
導入方法に関しては過去の記事をご参照ください。
qfixhomwの導入・使い方

これまで一時メモなど簡単な使い方しかしていなかったのですが、この度QFixHowmを使ったTODO管理に本気で取り組んでみました。
その際の設定や操作など主要なTipsをメモしておきます。

まずQFixHowm/QFixGrepの結果表示にはQuickFixウィンドウを使用する設定にしています。

let QFix_UseLocationList = 0

こうしておくと g,q でカレンダー表示しながら g,y や g,t で予定・タスクを一覧表示したときに、以下画像のように良い感じの画面構成になってくれます。
ロケーションリストを使う設定だとカレンダー画面の方に予定一覧が出てしまい、とても使いづらいです。。

sample

また g,y の予定一覧は60日分を表示する設定にしています。
これは経験則的に2ヶ月分の予定が分かれば個人的には十分だからです。

let QFixHowm_ShowSchedule = 60

カテゴリータグも設定しています。
私はページではなく予定やタスク毎にタグを付与しています。

" ※実際はもっと多くのタグを設定しています。
let QFixHowm_UserSwActionLock = ['[ ]', '[:work]', '[:private]']

これでアクションロックが使えるので、[ ] と入力した状態でEnterキーを押すとタグが切り替わります。
さらに以下のようにgotoリンクをどこか適切なページへ書いておいて、タグ毎に予定・タスクを一覧化できるようにもしています。
>>>:<タグ名>
※参考:gotoリンクとは

g,y や g,t による予定・タスク一覧化の際はキャッシュを使いたくないので、キャッシュを無効化しています。
理由はこれらコマンドを使うときは大抵TODO一覧を更新した場合が多いためです。

let QFixHowm_ListReminderCacheTime = 0

TODOを更新した際に最新の状態で予定・タスクを一覧化するとき、デフォルトでは g,ry や g,rt と入力します。
rを入力することに対して少し煩わしさを感じた次第です。。

最後に、g,y や g,t による予定・タスク一覧化で検索する対象ファイルは1ファイルに限定しています。
今後QFixHowm内のページが増えていったときに、検索速度が比例して増加するのを防ぐのが目的です。

"let QFixHowm_ScheduleSearchFile = '<your path to todo file>'

また本設定に伴い、予定・タスクはすべて1ファイルに追記しています。
とは言え行数が増え続けるのは嫌だったので、完了した予定・タスクは別ファイルに移動しています。

ちなみにタスクを追記しているファイルには mW といった形でマークを設定しています。
これで ‘W と入力するだけでタスク一覧ファイルを開け、すぐに予定・タスクを追記できます。

これまでに紹介した設定も含め、QFixHowmに関連する設定は以下のようになっています。

" qfixhome-masterにruntimepathを通す
set runtimepath+=<path to your qfixhowm-master>

" キーマップリーダー
let QFixHowm_Key = 'g'

" howm_dirはファイルを保存したいディレクトリを設定
let howm_dir             = 'C:\howm'
let howm_filename        = '%Y/%m/%Y-%m-%d-%H%M%S.md'
let howm_fileencoding    = 'utf-8'
let howm_fileformat      = 'dos'

" キーコードやマッピングされたキー列が完了するのを待つ時間(ミリ秒)
set timeout timeoutlen=3000 ttimeoutlen=100

" QFixHowmのファイルタイプ
let QFixHowm_FileType = 'markdown'

" タイトル記号を # に変更する
let QFixHowm_Title = '#'

" QuickFixウィンドウでもプレビューや絞り込みを有効化
let QFixWin_EnableMode = 1

" QFixHowm/QFixGrepの結果表示にロケーションリストを使用する/しない
let QFix_UseLocationList = 0

" ファイルパスのバックスラッシュをスラッシュにする
set shellslash

" textwidthの再設定
au Filetype qfix_memo setlocal textwidth=0

" 休日定義ファイル
let QFixHowm_HolidayFile = '<your path to qfixhowm>\qfixhowm-master\misc\holiday\Sche-Hd-0000-00-00-000000.cp932'

"オートリンクでファイルを開く
let QFixHowm_Wiki = 1

" wiki保存場所
let QFixHowm_WikiDir = 'wiki'

let SubWindow_Title = "WikiMenu"

" ,yでの予定表示期間
let QFixHowm_ShowSchedule = 60

" カテゴリタグの定義
let QFixHowm_UserSwActionLock = ['[ ]', '[:work]', '[:private]']

"予定・TODO表示のキャッシュ保持時間(秒)
let QFixHowm_ListReminderCacheTime = 0

"予定・TODOの検索ファイル名指定
"let QFixHowm_ScheduleSearchFile = '<your path to todo file>'

以上です。
久々にVimの設定を見直す良い機会となりました。

Vimコマンドラインモードの操作を爆速にするTips

Vimのコマンドラインモードでの編集は、挿入モードのように
キーマッピングが効かず、もどかしく感じるときがあります。
そんなときはコマンドラインモードで「Ctrl + F」を押しましょう。
するとコマンドラインモードの編集画面が別のバッファで開き、
挿入モードと同じように編集できます。
実行する際はノーマルモードになって「Enter」を押下します。

また過去に実行したコマンド履歴も出てきますので、
履歴からコマンドをコピー/編集して実行することも可能です。
うまく活用すれば、コマンドライン操作をかなり効率化できますよ!

また「/」を押下して検索する際も「Ctrl + F」で同じ操作ができます。
こちらも過去の検索履歴が出てきて非常に便利です。

vim上の表示をそのままhtmlとして保存する”TOhtml”

最近のvimにはvim上の表示をそのままhtmlファイルとして保存できる
“TOhtml”という機能が標準でバンドルされています。
以下のようにvimのシンタックスハイライトを
そのままスライドに貼り付けて使いたいときなどに便利です。
sample
その他私が最近便利だと思ったのは、vimでファイル間のdiffを取得する
“diffsplit”を使った画面をそのままhtml化できる点です。
diff
このようにファイル名と異なる箇所のハイライトがそのままhtml化できるので、
diff結果を誰かと共有するときに使ってます。

こんな感じでvimは日々新しい発見が得られて面白いですね。
皆さまもよきvimライフを!

gvimでフォントサイズを手軽に変える

gvimのフォントサイズを手軽に変えられるようコマンド化してみました。
下記をvimrcに追加すると、例えばexモードで”Big”と実行すれば
フォントサイズが20ポイントになります。

command Small :set guifont=MS_Gothic:h8:cSHIFTJIS guifontwide=MS_Gothic:h8
command Mid :set guifont=MS_Gothic:h12:cSHIFTJIS guifontwide=MS_Gothic:h12
command Big :set guifont=MS_Gothic:h20:cSHIFTJIS guifontwide=MS_Gothic:h20

打ち合わせ中にgvimをプロジェクターに写しつつ議事録をとる際、
瞬時に文字を大きくして誰でも読めるようにできたりしますよ。

Vim statuslineの整え方

普段Vimの statusline は lightline.vim を使用してますが、
勉強がてら自分で作ってみました。

function! SetStatusLine()
  if mode() =~ 'i'
    let c = 1
    let mode_name = 'Insert'
  elseif mode() =~ 'n'
    let c = 2
    let mode_name = 'Normal'
  elseif mode() =~ 'R'
    let c = 3
    let mode_name = 'Replace'
  else
    let c = 4
    let mode_name = 'Visual'
  endif
  return '%' . c . '*[' . mode_name . ']%* %<%F%=%m%r %18([%{toupper(&ft)}][%l/%L]%)'
endfunction

hi User1 gui=bold guibg=red guifg=white
hi User2 gui=bold guibg=blue guifg=white
hi User3 gui=bold guibg=coral guifg=white
hi User4 gui=bold guibg=green guifg=black

set statusline=%!SetStatusLine()

解説

  • 全体概要
    • SetStatusLine関数でモードに応じて動的に色、モード名が変わるように設定
    • return文でstatuslineの設定内容を作成
  • statuslineの内容 (左から順に)
    • %[1-4]*~%*:色の設定
    • %<:長いファイルパスを短縮化
    • %F:開いているファイル名のフルパス
    • %=:左側に記載したものを左寄せ、右側に記載したものを右寄せ
    • %m:修正フラグ
    • %r:読み取り専用フラグ
    • %{toupper…}:指定文字列を大文字化
    • &ft:ファイルタイプ
    • %l:カーソルの現在行
    • %L:ファイルの全行
  • ハイライトの設定
    • hi User[1-4]:各モードに対応したハイライトを定義
    • なお guibg, guifg はGVim用の設定
    • CLIのVimでは ctermbg, ctermfg を使用

上記を設定したstatuslineがこちらです。
Normal
Insert
Visual
Replace

ご自分でstatuslineを作成する際の参考になれば幸いです。

Vimの機能でファイルを暗号化する

余り使う機会はないかもしれませんが、Vimには暗号化機能があります。
以下exコマンドで使えます。

:X

上記コマンドを打つと二回パスワードを入力するよう求められます。
その後保存するとファイルが暗号化されます。
次回ファイルを開くときは
暗号化時に入れたパスワードを入力して復号化します。
パスワードを間違うと暗号化されたデタラメな文字列しか表示されません。

なお暗号化アルゴリズムは下記三種類から選択できます。
※Vimのバージョンが7.4.399以上の場合

  • zip
  • blowfish
  • blowfish2

下にいくほど強固なアルゴリズムになりますので、
blowfish2を使うのがベストです。
デフォルトはzipなので、blowfish2を使う場合は
下記設定をvimrcに追記します。

set cryptmethod=blowfish2

見られると困る秘密のファイルがあれば
この機能で暗号化しておきましょう!

vimのsortコマンドで重複行を削除する

以下vimのsortコマンドでunixの”sort | uniq”と同じことができます。

:sort u

ちなみにsortコマンドは他にも次のようなソートが可能です。

" 文字列として昇順でソート
:sort

" 文字列として降順でソート
:sort!

" 左から探索して最初にマッチする数字でソート
:sort n

" 正規表現にマッチする文字列でソート
:sort /regular expression/ r

Markdown形式に沿ってfoldするためのVimスクリプト

vimのfold機能を使って、Markdown形式のテキストを
見出しごとに折りたたむスクリプトを作ってみました。
Vimスクリプト作成の練習も兼ねてということもあり、
そこまで凝ったものではないため悪しからず。

function! FoldMarkdown(lnum)
  let line = getline(a:lnum)
  let next = getline(a:lnum + 1)

  if line =~ '^#\{1}[^#]\+'
    return 1
  elseif next =~ '^#\{1}[^#]\+'
    return '<1'
  elseif line =~ '^#\{2}[^#]\+'
    return 2
  elseif next =~ '^#\{2}[^#]\+'
    return '<2'
  elseif line =~ '^#\{3}[^#]\+'
    return 3
  elseif next =~ '^#\{3}[^#]\+'
    return '<3'
  endif

  return '='
endfunction

上記スクリプトは見出しレベル3までの折りたたみに対応しています。
必要とあらばレベル4以降の追記も簡単にできると思います。

このスクリプトをvimrcなどに追記し、
以下のようにexコマンドを実行すれば利用できます。

set foldmethod=expr foldexpr=FoldMarkdown(v:lnum)

これで例えば次のように折りたたみが機能します。

foldtest

既にvim-markdownのような素晴らしいプラグインもありますので、
本当にミニマルな機能で良い場合に参考にして頂ければと。

Vimの外部コマンド連携

久々にVimネタで書きます。
今回はVimの外部コマンド連携についてです。
Vimといえばターミナル内で起動してテキスト編集できることが
大きな売りの一つですが、それをVimの特徴たらしめている要素が
「外部コマンド連携」機能だと思っています。

と言いつつも、お恥ずかしいことに最近まで外部コマンド連携については
“!”を使えばシェルのコマンドを実行できる、くらいの認識でした。

しかしそこには標準出力をバッファに取り込む(“r!”)であったり、
バッファを標準入力に書き出す(“w !”)といった使い方もある訳で。
その辺りについて備忘録的に書いていきます。

外部コマンドの起動

まずは標準的な使い方から。
“:!”と入力することでVimから外部コマンドを起動できます。

## &quot;:!&quot;のあとにシェルのコマンドを入力
:!&lt;command name&gt;

## 例えばVimを起動したままCのコンパイルをしたり
:!make

## gitリポジトリにcommitしたりできます
:!git commit -a -m &quot;test&quot;

## 編集中のファイルのバックアップも気軽に作れます
## ちなみに&quot;%&quot;は編集中のファイル名を表します
:!cp % %.bak

私は最近まで上記くらいの使い方しか知らなかったです…

外部コマンドの標準出力をバッファへ取り込む

“:r!”を使うと外部コマンドの標準出力を
バッファに取り込むことが出来ます。

## 例えばテキスト中に日付を入れてみたり
## (%記号を使う場合はエスケープ文字&quot;\&quot;が必要っぽいです)
:r!date +&quot;\%Y/\%M/\%d \%H:\%m:\%S&quot;

## ワークディレクトリまでの絶対パスを挿入したいときにも
:r!pwd

## 特定ディレクトリ内のファイル一覧を作成したり出来ます
:r!ls -1

外部コマンドの標準入力にバッファの内容を渡す

“:w !”を使うと外部コマンドにバッファの内容を
標準入力として渡すことができます。
※”w”と”!”の間には必ず一スペース必要です

## バッファ内から条件に合うものだけを取り出してみたり
:w !egrep &quot;^2017-08-20&quot; | less

## バッファ内の計算式から計算結果を出してみたり
:w !bc -l

うーん、あまり良い例を思いつかなかったです。

編集中バッファを外部コマンドにより整形

“%!”コマンドは編集中バッファの内容を外部コマンドの
標準入力として渡し、その実行結果をバッファとして取り込みます。

## csvファイルをVimで編集中(あるかな?)にawkでフィルタ
:%!awk -F, '$2==&quot;test&quot;{print $0}'

## 編集中バッファの特定範囲だけを数値でソート
'&lt;,'&gt;%!sort -n

またソートについてはVimの機能として強力なものがあるので、
別の機会に是非ご紹介したいです。

おわりに

久々のVim関連のポストでしたが、
Vimの世界は奥深く広いものですね。
知らないことが未だたくさんありそうです。
他にも目からウロコな発見があれば記事にしていく所存です。

Vimのoldfilesを使う

Vimを使っていて過去に開いたファイルをまた開きたい場合、
プラグインを使われている方はneomru.vimなどを利用されていることと思います。
こうしたプラグインは非常に便利ですが、やや動作がもっさりしてくるのが難点です。

そこで今回はVimに標準で入っている機能(しかも動作が軽い)を使って
過去のファイルを探索してみたいと思います。

それにはVimのoldfilesという機能を使います。
以下がoldfilesのhelpです。

:ol[dfiles] viminfo ファイルにマークが記録されているファイルのリス
トを表示する。起動時にこのリストが読み込まれ、
:rviminfo! を行った後でのみ変更される。|v:oldfiles|
も参照。このリストで表示される番号は |c_# ができる。
出力は |:filter| でフィルタリングできる。例: >
filter /.vim/ oldfiles
{Vi にはない。|+eval| 機能付きでコンパイルされたときの
み有効}

“:oldfiles” とコマンドを実行すると、
過去に開いたファイルの一覧を確認できます。
この状態から各ファイルに対応する番号を指定することで、
所望のファイルを開くことが出来ます。
例えば3番のファイルを開きたい場合は “:e #<3" とします。
しかしこれだとコマンドをやや覚えづらく、
また一覧表示されるファイル数が多いと開きたいファイルを探すのが
面倒になってきます。

そこで今回は "browse" と "filter" を組み合わせて使い、
より効率よく過去のファイルを開きたいと思います。
使い方は下記の通りです。

:browse ol
もしくは
:browse filter {pattern} ol

前者はviminfoに記載されている過去に開いたファイル全てを
一覧で表示します。
後者は{pattern}で指定した文字列を含むファイルのみを表示します。

上記コマンドを実行すると、最後に開きたいファイルに対応する番号を
入力するように促されるので、該当する番号を入力してEnterを押します。
これで過去に編集したファイルを開けます。

こういったプラグインに頼らない方法も知っておくと、
制限のある環境で構築作業をするときなどにとても役立ちます。
あと、標準機能縛りでVimを使い倒すというのもゲーム感覚で割りと楽しめます。