多用するのでプラグイン作ってみた。
class
って書いたりpackage ... {
って括弧書いたり面倒だよね。
超適当配布なので VimScript 1ファイル製。
仕様
変換ルール
記法 | 変換 | 備考 |
---|---|---|
. foo | package foo | html の class 属性のイメージで . にした |
# foo | namespace foo | html の id 属性のイメージで # にした |
+ Foo | class Foo | |
- Foo | enum Foo | |
* Foo | interface Foo | |
空行 | 捨てられる | 実装辛くてどーでも良くなってしまった |
それ以外 | そのまま | 線とかコメントとか |
HTML のリスト記法のイメージなので、
. foo
+ FooId
# FooType
が
package foo {
class FooId
enum FooType
}
になるってこと。
ソース
command! PlantVim call PlantVim()
function! PlantVim()
call s:init(getline(1, '$'))
let node = s:subs(0)
execute 'normal ggdG'
call s:put('@startuml')
call s:put('')
call s:indentingSetLine(node, '')
call s:put('')
call s:put('@enduml')
execute 'normal Gddgg0'
endfunction
function! s:init(input)
let g:n = 0
let g:input = filter(a:input, 'v:val != ""')
let g:max = len(g:input) - 1
endfunction
function! s:subs(depth)
let xs = []
while g:n <= g:max && s:depth(g:input[g:n]) >= a:depth
let g:n = g:n + 1
if s:depth(g:input[g:n - 1]) == a:depth
if s:needParse(g:input[g:n - 1]) == 'true'
let parsed = s:parse(g:input[g:n - 1])
let parsed['subs'] = s:subs(a:depth + 1)
let xs = xs + [parsed]
else
let xs = xs + [{'line': g:input[g:n - 1], 'output': 'raw', 'subs': []}]
endif
endif
endwhile
return xs
endfunction
function! s:depth(line)
let x = 0
for c in split(a:line, '\zs')
if c == ' '
let x = x + 1
else
break
endif
endfor
return x / 2
endfunction
function! s:parse(line)
let type = {'.': 'package', '#': 'namespace', '+': 'class', '-': 'enum', '*': 'interface'}[split(a:line, '^ ')[0][0]]
let containable = get({'package': 'containable', 'namespace': 'containable'}, type, 'no_contains')
let content = split(a:line, ' ')[1]
return {'line': type . ' ' . content, 'output': containable}
endfunction
function! s:needParse(line)
return (a:line =~ '\.\|#\|+\|- \|\*') == 1 ? 'true' : 'false'
endfunction
function! s:indentingSetLine(node, pad)
for elm in a:node
if elm['output'] == 'containable'
call s:put(a:pad . elm['line'] . ' {')
call s:indentingSetLine(elm['subs'], a:pad . ' ')
call s:put(a:pad . '}')
elseif elm['output'] == 'no_contains'
call s:put(a:pad . elm['line'])
else
call s:put(elm['line'])
endif
endfor
endfunction
function! s:put(line)
call append(line('$') - 1, a:line)
endfunction
導入
上のファイルをplant.vim
という名前で保存して、vi を起動して:so ~/Downloads/plant.vim
をする。(パスは読み替えて)
インデント略記が書き終わったら:PlantVim
とすると変換される。
デモ
おしまい
while
とかグローバル変数と添字アクセスとか数年ぶりに書いた。ちょー辛い、もう二度とやりたくない。
本当は改行を保ちたいとか不可逆だしファイルを書き換えちゃうのでやり直しが効かないとか対応したかったけど、これ以上を VimScript 1ファイルでやるのはもう無理。
気に入って、かつ機能追加したくなったらメインロジックは全部 haskell か何かに移して VimScript はすっかすかにする。
ノシ