ALIGN

2012年10月22日

vimを本格的に使い始めたが、Emacsがうらやましいところがひとつある。org-modeがあることだ。
org-modeは、Emacsをアウトラインプロセッサとして使うための機能を付与する非常に強力なスクリプトである。 vimにもorg-modeプラグインが開発されているが導入が難しい。また、Emacsで使うからこそ強力で便利であるのであり、そのままの操作感をvimに持ち込んでも無理があるというもの。

そこで簡易なプラグインの導入で、アウトラインプロセッサとして実用になる手段を考えた。
え、ニーズ?   なにそれ、おいしいの?

1.求める機能

org-modeで特に便利だと思っている機能のうち、以下の2つについてvimに持ち込む。

(1)表作成機能

テキストで表を作るとき、スペースの数を合わせるのが最も時間がかかる。 表の内容だけをスペース区切りで羅列し、ワンタッチで表形式に整える機能。 整形ルールは、1つのスペースに区切った項を、|(縦棒)を補って表形式にする。

(2)視覚的な文書構造の入れ替え機能

大項目、中項目、小項目といった各文章単位を、インデントを使い記述していき、ブロック単位で前後関係を入れ替えたり、レベルを上げ下げする。その際、視覚的にスライドして移動する機能。

2.実装に必要なプラグイン

(1)表作成機能

表を簡易に作成する機能はvim標準では存在しないので、以下のプラグインを導入し、任意のセパレータ文字で表形式に整える機能を付与する。

(2)文書構造の編集ー領域の選択の拡張

文書の階層構造におけるレベルの移動は、インデントの量により決まる。vimでは、ビジュアルモードで選択した行を、"<"と">"でインデント量を増減させられる。そこで、ビジュアルモードでインデントを基準とした選択をできるようにする。そのために以下のプラグインを導入する。

(3)文章構造の編集ー上下移動

vimには、複数行をひと塊として扱い、1行に畳み込んでみせるfold機能がある。 畳み込みにはレベルがあり、第一レベルの畳み込みに、複数の第二レベルの畳み込みを組み入れられる。 その機能を使い、章や段落を1行に見せかけて編集することで、文書構造を行の移動として入れ替えられる。標準のままでは、畳み込んだときの表示がわかりにくいので、以下のプラグインを導入する。

3.表の作成機能の設定と操作方法

(1)Alignの設定

上記のAlign.vimをインストールしたら、以下の設定を入れる。 マルチバイトを使うので、3を設定しておく。

let g:Align_xstrlen = 3

(2)以下のキーマップを設定

どのキーに割り当てるかは任意。ここれは、,tに割り当てている。

vmap <silent> ,t :s!\ !\|!g<CR>gv:s!.*!\|&\|!g<CR>gv<Plug>AM_t\|

(3)操作方法

[基本]スペース区切りで書いた表から、スペースを補完して整形する。
これは(1)のalign.vimの操作。 ビジュアルモードで整形したい表を選択し、<Leader>tsp

[縦棒で区切る] これは、(2)の独自キーマップの操作。
ビジュアルモードで整形したい表を選択し、,t

その他の操作については、以下ページを参照。

4.文書構造の入れ替え

ここでは、まず選択を容易にするために、textobj-indentを使えるようにする。
そのあと、インデント幅を調整する左右の移動を容易にする。
文書の前後関係を調整するための、上下の移動については、スライドする方式と折りたたみ機能を使った方式を考える。

(1)領域の選択

vimの基本機能で、空行で挟まれた行は、段落として認識されるので、vipかvapで一気に選択できる。 vipはカーソル位置がそのまま、vapで選んだ場合は選択領域の最終行にカーソルが移動する。

インデント量が同じ領域を一気に選択するには、textobj-indentを使う。 textobj-indentには設定は特にない。操作方法は、以下のとおり。(最後の文字は、i(アイ)の大文字か小文字である)

vii カレントの行のインデントレベルと、それ以下のレベルの行を選択する。空行があればそこで止まる。
viI カレントの行のインデントレベルと同じレベルの行を選択する。空行があればそこで止まる。
vai カレントの行のインデントレベルと、それ以下のレベルの行を選択する。空行があっても止まらず、上位のレベルの行で止まる。
vaI カレントの行のインデントレベルと同じレベルの行を選択する。空行があっても止まらず、上位もしくは下位のレベルの行で止まる。

(2)左右の移動

こうして選択したした領域の、インデントの幅を変更するには、標準でも< >のキーを使うと、その領域のインデント量をshiftwidthの分だけ増減してくれる。しかし、変更が一回終わると、領域選択が解除されてしまい、連続的に移動することができない。そこで、以下のキーマップを.vimrcに追記することで、領域選択がキャンセルさなくなり、連続して移動させられる。

" continuous indent block in visualmode
vnoremap < <gv
vnoremap > >gv

なお、tab幅については、下記参考ページのはてな技術勉強会のページに詳しい。
ぼくは、以下のように設定してある。

set expandtab
set tabstop=2
set softtabstop=2
set shiftwidth=2

(3)上下の移動 スライド方式

選択した領域をddで消して、任意の場所にpで貼り付けてもよいのだが、その方法は、はっきりと、ここをここに移したい、と決まっている場合。
構成を考えながら、あっちにおいてみたり、こっちにおいてみたりしてみたい。org-modeでは、選択範囲を一行ずつスライドしていくことができたので、vimでも、それを実現した。
以下のvimスクリプトを.vimrcに組み込む。(下記、参考ページにあるtacahiroyさん作成)
下記のキーマップでは、ビジュアル選択状態でCTRL+pで一行上に、CTRL+nで一行下に、選択ブロックが移動する。

" continuous move block in visualmode
function! s:move_block(d) range
  let cnt = a:lastline - a:firstline

  if a:d ==# 'u'
    let sign = '-'
    let cnt = 2
  else
    let sign = '+'
    let cnt += 1
  endif

  execute printf('%d,%dmove%s%d', a:firstline, a:lastline, sign, cnt)
endfunction

vnoremap <C-n> :call <SID>move_block('d')<Cr>==gv
vnoremap <C-p> :call <SID>move_block('u')<Cr>==gv

(4)畳込み(fold)の活用

vimには、あるルールで行を畳み込み、表題だけみせる機能がある。それを使い、文書構造全体を見回せるように表示する。
畳み込みルールは、中括弧3つを入力し、それで領域を認識させる方法(marker)と、インデント幅で認識させる方法(indent)がある。ぼくは自由に指定できるmarkerを使っている。
次に、左端に畳み込みレベルのマークを表示する。ここでは第5レベルまで表示とした。

set foldmethod=marker
set foldcolumn=5

使い方は以下。

za 畳み込みのopenとcloseをトグルで切り替える。
zo/zO 畳み込みを開く。大文字だと再起的に開く。
zc/zC 畳み込みを閉じる。
zr/zR 全ての畳み込みを開く。
zm/zM 全ての畳み込みを閉じる。
zf 畳み込み印を付与する。
zd 対応する折り畳み印を削除する。

(5)FoldCCの設定

foldCCの設定。畳み込みしたときの表示テキストを、FoldCCのものにする。(するとレベルや行数が表示されるようになる)

set foldtext=FoldCCtext()

(6)上下の移動 畳込み方式

畳み込むと複数行が1行に見る。そこにカーソルを持ってきて、ddで削除し、任意の位置でpで貼り付けてやると、畳み込んだ領域が全て移動することができる。
ちなみに、畳み込みをしているときに、(3)のスライド方式を使うと、畳込みの階層が崩れて逆に見にくい。

5.参考ページ

ここでは紹介しなかったが、foldで畳み込んだ表題をリスト表示し、選んだ表題にすばやくカーソル移動できるuniteのプラグインがある。(これで、表題の移動ができれば最高なのだが・・・)



sylphide_ffr31mr at 23:42コメント(0)トラックバック(0) 

2012年10月19日

テキストファイルで、スペースで区切った表を作ることがあるが、これをちゃんとした表に見えるように空白を補うのは結構面倒だ。
align.vimは、それを自動で整形してくれるが、スペースを|(縦棒)に変換してくれたり、ましてや<td>タグでくくってくれたりはしない。

例えば、以下の様なスペース区切りの表を書く。

あっくん みかん 梨 りんご
いぶきちゃん 大根 ブロッコリー トマト
うみうし 後鰓類 軟体動物門腹足綱 無楯類

それをビジュアルモードで選択し、

<Leader>tsp

とすると、こうなる。

あっくん     みかん 梨               りんご
いぶきちゃん 大根   ブロッコリー     トマト
うみうし     後鰓類 軟体動物門腹足綱 無楯類

これはこれで便利であるが、以下の様な表にしたい。

|あっくん    |みかん|梨              |りんご|
|いぶきちゃん|大根  |ブロッコリー    |トマト|
|うみうし    |後鰓類|軟体動物門腹足綱|無楯類|

そのためにはキーマップで、以下のように定義する。

vmap <silent> ,t :s!\ !\|!g<CR>gv:s!.*!\|&\|!g<CR>gv<Plug>AM_t\|

スペースひとつを、ひとつの区切りとしているので、連続したスペースをいれると項がずれるが、実用にはなる。縦棒を:(コロン)とか、好みのものに変えるのも簡単。

同じく、スペース区切りの表から、tableタグ用に<TD>と<TR>のタグを自動変換するキーマップは以下。

vmap <silent> ,T :s!\ !\</td\>\<td\>!g<CR>gv:s!.*!\<tr\>\<td\>&\</td\>\</tr\>!g<CR>gv<Plug>AM_Htd

すると、こうなる。

<tr><td> あっくん     </td><td> みかん </td><td> 梨               </td><td> りんご </td></tr>
<tr><td> いぶきちゃん </td><td> 大根   </td><td> ブロッコリー     </td><td> トマト </td></tr>
<tr><td> うみうし     </td><td> 後鰓類 </td><td> 軟体動物門腹足綱 </td><td> 無楯類 </td></tr>

align.vimが入っていない場合は、最後の<CR>から後ろを取れば良い。

vmap <silent> ,t :s!\ !\|!g<CR>gv:s!.*!\|&\|!g<CR>
vmap <silent> ,T :s!\ !\</td\>\<td\>!g<CR>gv:s!.*!\<tr\>\<td\>&\</td\>\</tr\>!g<CR>

参考にしたのは、以下のページ
Big Sky



sylphide_ffr31mr at 22:27コメント(0)トラックバック(0) 
記事検索
最新コメント
livedoor プロフィール
月別アーカイブ
  • ライブドアブログ