vim-markdown で行っているVim上のMarkdownの畳み込みで ちょっと気になる所があったのでいじってみました。
vim-markdownで行ってる畳み込み
vim-markdown ではafter/ftplugin/markdown.vim の中で畳み込みの設定してますが、 これはもともと Original版(plasticboy/vim-markdown) にあったものを取ってきたままのものでした。
これは、基本的に#
で指定したり---
の下線を引くことで作る
各セクション毎に畳み込む設定です。
ただ、先日のアップデート
でYAMLブロックのハイライトを出来る様になって、
ファイルの先頭にあるYAMLブロックをハイライトしてくれる様にはなりましたが、
畳み込みのところでは考慮されておらず、
YAMLブロックの最後の---
で閉める所に、上に空白を一行入れないと
セクションタイトルとみなされてそれ以下を閉じてしまいます。
特にこれを直したかったのと、 コード部分が長くなる事が多いのでコード部分をたたみ込めたら 便利だな、ということでやってみました。
畳み込みの設定
Vimでの畳込みは
setl foldmethod=expr
とすることでfoldexpr
で指定される方法で畳み込みを行う様になります。
(該当ファイルに対してだけ設定したいのでset
でなくsetl
(setlocal
)で。)
このfoldexpr
に与えられた評価式は各行毎に評価され、
畳み込みの深さを指定します。
そのため、foldexpr
で与えられた式の中では、行番号として
v:lnum
という値を使うことが出来ます。
1
|
|
とすれば、getline(v:lnum)[0]==\"\\t\"
の結果は
行の要素の先頭がタブなら1
(Vimでは評価が真だと1)、そうでなければ0
なので、
タブの行だけ畳み込みの深さが1になってその部分が畳み込まれます。
(0が何も畳み込まれない所、数が大きいほど深い畳み込みの中に入ります。)
また、
1 2 3 4 5 6 7 8 9 |
|
の様に関数を使っても同じことが出来ます。
畳み込みの深さを指定する返り値には数値以外にも使える物があります。
値 | 意味 |
---|---|
0 |
畳み込み無し |
1 , 2 , … |
数値の畳み込みの深さを指定 |
-1 |
前後の行の浅い方と同じ深さ |
"=" |
前の行と同じ深さ |
"a1" , "a2" |
数の分だけ前の行より深く設定 |
"s1" , "s2" |
次の行の初期状態を数の分だけ前の行より浅く設定 |
"<1" , "<2" |
数の深さの畳込みをここで終了 |
">1" , ">2" |
数の深さでで畳み込みをここから開始 |
"s1"
について、ヘルプ
1
を見ると
"s1", "s2", .. subtract one, two, .. from the fold level of the previous line
となってるんですが、実際には現在の行まで畳み込みを同じレベルで行って 次の行で数だけ浅くなる、という動作をします。 (単に書き間違えだと思いますが。。。)
つまり"="
なら浅くなった所、"a1"
とかなら浅くなったところから開始して
1つ深い所、に設定されます。
"<1"
/">1"
に関しては、通常は単に1
とするのと変わりありませんが、
前後に-1
や"="
があった場合、
それらは1
とは評価されず0
と評価される様になります。
また、"<1"
や"a1"
等を使うと同じ深さの物を並べても別々の畳込みに入れられます。
>1 ---
=
<1 ^^^
>1 ---
=
<1 ^^^
a1 ---
=
s1 ^^^
a1 ---
=
s1 ^^^
各行が上の最初の文字列の様な深さに設定されてるとすると、
右側の---
から^^^
までの部分でそれぞれ畳み込みが作られます。
vim-markdownでの畳み込みのアップデート
新しい畳み込み用の関数はこんな感じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
|
ここでは、各行の情報として、getline
で行の要素を取ってくるのに加えて、
synIDattr(synID(a:lnum,1,1), 'name')
として各業の一文字目の
ハイライトの名前を使っています。
また、このためにYAMLブロックの区切り文字をyamlDelimiter
に変更しました。
この関数内ではSyntaxの中の設定と違って行ごとに行うので、 この区切りからこの区切り、みたいなSyntaxファイルで行ってることと 同じことは出来ません。 (一行評価する毎に全行(もしくは必要な前後の複数行)読み込んで評価する、ということをすれば出来ないことも無いですが。。。)
従って、ここでは区切りを見つけて、その前の行や後ろの行を見ることで どうするべきか決めていたりもします。
yamlDelimiter
の場合には必ず1行目に最初が来て、
後は閉じるだけなので1行目なら開始、それ以外なら終了、といった感じ。
コードブロックでは区切りがmkDelimiter
、liquidTag
(Octopressのcodeblock
文)
の場合があり、これらでは次の行がコードブロック内なら開始行、
前の行がコードブロック内なら終了行、と言った感じ。
こちらは色の設定の関係でcodeDelimiter
みたいなのを作成したいとしても
それぞれ用にしなくちゃいけない上、そのまま使っても特に問題ないので
他と共通な上のハイライト名で行っています。
また、markdownCodeDelimiter
は
先日のアップデート
でjoker1007/vim-markdown-quote-syntax
に戻したコードブロック内を各言語でハイライトする場合に使う物で、
この場合、ブロック内はmkdCode
ではなく、
各コードのハイライトになるのでそれで指定するのは難しいので
前後の行が空白の場合、で行っています。
{% codeblock %}
前後に空白が無いときちんとビルド出来ないことが
あるので空白が必要なのでこれで良いかと。
スペース字下げによるコードも畳み込めるようにしてありますが、 1行だけの場合にはしないようにしています。 意味が無いのと、もしやろうとすると、開始と終了の行が同じになるので こんな感じではできず、コードの次の空白行まで含めて、 空白行で一つ前がコードでその前が空白、みたいな事をチェックして、 とか必要になって面倒しかないのでやめています。
後はコメント行も畳み込める様にしてあります。
セクションタイトルのとこもシンタックスハイライトの名前を使って分かりやすく。
これでOctopressでブログを書くのが大分やりやすくなりました。
追記: 2014/11/19
見た目はかなり良くなったんですが
Syntaxをチェックする際に結構負荷があるらしく、
すべての行で行うため、大きめのファイルを開くと結構時間がかかるのと、
編集したりする際にも負荷がかかってダメだったので、
この設定はオプションにしました。
デフォルトでは上の機能はなしで各セクション毎
(---
や#
を見るだけ)の畳込みだけで、
上記の機能を使いたい場合は
let g:vim_markdown_better_folding=1
と.vimrcの中で設定すると有効になります。
追記ここまで