最近の更新

関連


その他いろいろ

MODxでつくる! 最強のCMSサイト カバー
MODxでつくる! 最強のCMSサイト

はやくMODx 2.0でないかなあ

~/.vim/template にあるテンプレートを(複数あればリストアップし)ロードするか否か選択できるプラグイン、qtmplsel.vimに式展開機能を追加し、v1.1.0として公開しました。

式展開

テンプレートファイルに含まれる@{@@}@で囲まれた部分をvimの式として評価し、置換します。

例えば、

// \file @{@expand('%:t')@}@
// \date @{@strftime('%Y-%m-%d')@}@
class @{@expand('%:t:r')@}@ {
};

のようなcpp用テンプレートをtestclass.cppの作成時に適用すると、以下のように展開されます。

// \file testclass.cpp
// \date 2009-09-07
class testclass {
};

入手方法

http://www.vim.org/scripts/script.php?script_id=2761から最新版をダウンロードし、~/.vim/pluginか$VIMRUNTIME/pluginに置いてください。

なお、1.0.0の説明はこちらにあります: vimでファイル作成時にテンプレートを選択 qtmplsel.vim

vimでファイルを新規作成する際、ファイルタイプに応じてテンプレート(orスケルトン)を自動的にロードするためには、.vimrcに以下のような設定を加えることが多いと思います。

autocmd BufNewFile *.py 0r ~/.vim/template/template.py

しかし、決まり切った内容を拡張子ごとに用意するのも芸がなく、
またテンプレートを使いたくない場合や、複数のテンプレートから選びたい場合に対応できません。

そこで、~/.vim/template にあるテンプレートを(複数あればリストアップし)
ロードするか否か選択できるプラグイン、qtmplsel.vimを書いてみました。

インストール

  1. qtmplsel.vim - Quick Template Selector : vim online から最新版をダウンロード
  2. ダウンロードしたスクリプトを $VIMRUNTIME/plugin か ~/.vim/plugin に入れます。

使い方

:e コマンドや vim の起動時に存在しないファイル名を入力して新規作成すると、

ファイルタイプ
ft=pythonなら サーチパス/python_*
拡張子
*.pyなら サーチパス/*.py
ファイル名
ファイル名=Makefile なら サーチパス/Makefile_*

に該当するテンプレートを ~/.vim/template から列挙し、一つ以上該当するものがあればリストを表示します。

リスト上では k(上) / j(下) で項目を選択し、 Enter で決定、 q でキャンセル(ロードしない)となります。

また、グローバル変数g:qts_templatedirを設定することで、任意の場所をテンプレートファイルのサーチパスに設定することができます。

使用例

qtmplsel.vim screenshot

リスト表示部分などQuickBufを参考にしました。

ExactAudioCopy等でCDをリッピングする際、freedbに曲情報がないとCUEのタイトルなどが空欄になってしまいます。

その後mp3に変換した後で曲名などを設定しても、元のCUEにもそれを反映させるのは結構面倒です。

mp3tocue.py は、「タグ設定済みのmp3」から「対応するタグなし/不完全なCUE」にTITLEとPERFORMER情報をコピーするためのPythonスクリプトです。

mp3tocue-0.1.1.zip をダウンロード

python mp3tocue.py -t -e utf-8 -i CDImage.cue --in-place C:\Music\test\*.mp3

のようにすると、*.mp3のタグを読み出し、トラック番号順に並べ(-tオプション)、UTF-8で(-eオプション)、CDImage.cue を更新します。

-tを指定しなければ入力mp3を指定した順に、-eを指定しなければエンコーディングは元々のCUEのエンコーディングと同じになります。

※トラック長はCUE中のものを流用する必要があり、一からCUEを作り出すことはできません。あくまで曲/奏者情報の書き換えに特化しています。

vimで{モーション}で指定された範囲を、レジスタ(デフォルト”、指定も可能)で置き換えるオペレータ<C-K>を提供するプラグイン、
regreplop.vimの説明を書きました。
ビジュアル選択中で<C-K>とすると選択範囲が置換されます。

前に直接vim scriptとしてポストしたのとだいたい同じ内容ですが、少し綺麗にしてvim.orgに載せました。

使用例

単語の上で<C-K>iw
単語全体をレジスタ(")で置換
"ayyした後、他の行で"a<C-K><C-K>
行全体を、レジスタaにヤンクした行で置換
vWの後にhlで微調整して<C-K>
選択範囲をレジスタ(")で置換

vimのfoldopenにhorが含まれる場合、閉じた折りたたみの上で右移動しようとすると自動的にzo(折りたたみを開く)してくれます。
しかし逆に、開いた折りたたみの上で左移動してもzc(閉じる)してくれません(多分)。

行頭でhすると折りたたみを閉じるようにする設定を.vimrcに加えてみました。

nnoremap <expr> h foldlevel(getpos('.')[1])>0 &&
      \(getpos('.')[2]==1 \|\|
      \getline('.')[: getpos('.')[2]-2] =~ "^[\<TAB> ]*$" )?"zch":"h"

ちょっと便利。

行単位コメントをトグル/挿入/削除するためのコマンド/オペレータを導入するvimスクリプト、commentop.vimv1.1.1をリリースしました。

1.1.0からの変更内容は、

  • range function (:h function-range-example) を用いてスクリプトを簡素化
  • virtcolを利用し、タブ/スペースが混在していても見た目の幅を考慮してコメント挿入されるように

の2点です。

2009 07 24

テンプレート

最近boost::mplに興味を持って、ちょっと色々試しています。

Base::template tmp<0>::get()

なんていう気持ち悪い場所にtemplateが書けるなんてのもここ数日で知りました。

それでテンプレートを使って、TI_0, TI_1, …, TI_n の入力型を処理してTO_0, TO_1, …, TO_m の出力型を吐くような、functionもどきを作ったりしています。

主に画像処理に使う目的(つまりTIとかTOには画像が入る)で書いていますが、
単に画像だけならvector<shared <IplImage> >+仮想関数とかでいいわけです。
ところが時々特徴点集合とか整数値とか、画像じゃないものも受け渡す必要がでてきます。

これらを全部同様に扱えるようにというひねくれた目標を掲げたら途端にテンプレートの世界へ…
だんだん慣れてきて、クソ長いコンパイルエラーもなんとか意図するところがわかるようになってきました。

ちなみにその画像処理ライブラリはテンプレートのコンパイル時inline展開の恩恵に与れているようで、結構面倒な処理を渡しても30fpsカメラで27fpsくらい出ています。

しかしcvShowImageまわりがマルチスレッドで微妙な挙動を示すのには参りました。どうやらcvNamedWindowとcvShowImageは同じスレッドで起動しなくてはならず、cvShowImageはメインスレッド(というかcvWaitKeyスレッド?)でコールしないと画像が表示されない等など。ちょっとソース見たわけではないので怪しい経験則ですが、暇があったらちゃんと読んで調べておこうと思います。
目下の所は全処理スレッドが完了するのを待った後でcvShowImageだけメインスレッドに回しています。若干汚い。

ソースコードを編集しているときにありがちな状況として、一行の先頭や末尾にはそれほど興味がないが、中央付近を編集したいというものがあります。

例えば、今次に示す行の先頭にカーソルがあるとします。

  cord.set_slot(0, boost::shared_ptr<PipelineCallback<Image> >(new PipelineCallback<Image>()));

ここでshared_ptrの中身を書き換えたい場合、ちょっと思いつくだけでも

  1. 検索する /Pi<CR>
  2. カギ括弧へ移動して右 f<l
  3. Pへ移動する fP
  4. 11番目の単語に移動する 11w
  5. カラム指定 37| (エルでもいいけどパイプ)
  6. lllllllllllllllllllllllllllllllllllll

など様々な方法がありますが、2,3,4,5は確実性・直観性に劣り、1はタイプ数に劣り、6はvim使いとして許されざる入力です。この中なら一番まっとうなのは検索でしょうか。
fやtは明らかに次に何処に行くか分かっていれば使い出がありますが、ひとたび変な場所に飛ばされると混乱するのが常です。(vim歴が浅いだけかも知れませんが)

そこで、ここは自分をはじめとする脳の緩いvimユーザのために、最後の6. lllllllllllllllllllllllllllllllllllllに活路を見出そうと思いました。

37回もlをキーリピートするかわりに、最初に行の中央に移動してからlなりhなりで目的の場所へ行こうという方法です。

幸いvimにはvirtualedit/virtcolという、見た目の文字幅を考慮する仕組みが備わっているのでこれをそのまま利用します。

noremap <expr> gm (virtcol('$')/2).'\|'

元々のgmは画面幅に対して中央になるように、カーソルを水平移動するキーですが、あまり使いそうも無いので上書きしてしまいました。

行単位コメントをトグル/挿入/削除するための[count]コマンドとオペレータ{motion}を導入するvimスクリプト、commentop.vimの説明を書きました。

co

で今いる一行のコメントをトグルしたり、

3cO

で3行コメントアウトしたり、

gOa{

で{}ブロックを丸々コメントアウトしたりできます。

ノーマル ビジュアル オペレータ
トグル(ON⇔OFF) co co go{motion}
挿入 cO cO gO{motion}
削除 c<C-O> c<C-O> g<C-O>{motion}

上記の3×3=9種のキーマップが新たに定義されます。

デフォルトでftpluginの設定するcommentstringを使うので、何も設定しなくても多くの言語(vim, python, perl, ruby, haskell, sh, bash, zsh, java, javascript, Makefile, tex, ..etc.) では適したコメントが挿入されます。一部の自動的に決定できないファイルタイプ(c, cpp, csharp, php, matlab)については、スクリプト中で個別に定義していますし、ユーザが.vimrcでオーバーライドすることも可能です。

詳しくはcommentop.vimを参照してください。

先日はじめてのvimスクリプト(vimでモーション(or選択範囲)をレジスタの内容で置き換えるオペレータ)を書いてみましたが、

Re: vimでモーション(or選択範囲)をレジスタの内容で置き換えるオペレータ @ 7bit - while ("im the true Vim master"); - vimグループ
でアドバイスを頂いたので&自分で他のスクリプト書いて少し慣れたので修正しました。マークやレジスタの退避やらなんやらは不要のような気がしたので除外。

機能的に前回と違うのは、レジスタ指定出来る(しない場合はデフォルトレジスタ)になったこと。v:register退避のためだけに呼ぶ関数がダーティな気はします。

" replace selection with register
function! s:ReplaceMotion(type, ...)
  let reg = empty(s:lastreg) ? '"' : s:lastreg
  let op_mode = 'v'      " default: character
  let marks   = '<>'     " default: visual mode

  if !a:0 " normal mode
    let marks = '[]'
    if a:type == 'line'
      let op_mode = 'V'
    endif
  endif

  exe 'normal! `'.marks[1].'$'
  let paste_cmd = getpos("'".marks[1]) == getpos('.') ? 'p' : 'P'
  exe 'normal! `'.marks[0].'"_d'.op_mode.'`'.marks[1].'"'.reg.paste_cmd
endfunction

function! s:SaveReg()
  let s:lastreg = v:register
endfunction

" default mapping
if !hasmapto('<Plug>ReplaceMotion', 'n')
  nmap <silent> <C-K> <Plug>ReplaceMotion
endif
if !hasmapto('<Plug>ReplaceVisual', 'v')
  vmap <silent> <C-K> <Plug>ReplaceVisual
endif

" export the plugin mapping
nnoremap <silent> <Plug>ReplaceMotion :<C-U>call <SID>SaveReg()<CR><ESC>:set opfunc=<SID>ReplaceMotion<CR>g@
vnoremap <silent> <Plug>ReplaceVisual :<C-U>call <SID>SaveReg()<CR><ESC>:call <SID>ReplaceMotion('', 1)<CR>

~/.vim/plugin/ 以下に放り込んでプラグインとして使います。

a:type==の所が’list’というわけのわからん物になっていたのでlineに直しました

« 前のページ次のページ »