本記事は Vim advent calendar 21 日目の記事です。
例年は割と準備してたけど、もっとカジュアルに書いていい気がしたという完全な言い訳をして、自分の vimrc に書いてた設定をブログにコピペ。
その 1
TypeScript で変数とか関数のシグネチャーとかをポップアップで表示する。 組み込みの popup 関係の関数だと表示位置によって微妙にポップアップの位置をずらすとか微調整ができなかったので、自前で描画する場所を計算してやる。
let s:winid = -1 function! s:ts_hint_popup() if s:winid != -1 call popup_close(s:winid) let s:winid = -1 endif let l:content = tsuquyomi#hint() let l:contents = split(l:content, '\n') let l:border_size = 2 " both side of `|` and top and bottom `-` " col position let l:current_col = col('.') let l:max_width = strlen(sort(copy(l:contents), function('s:sort'))[0]) let l:col = l:current_col if l:current_col + l:max_width > &columns " popup is overflowed if l:max_width > &columns let l:col = 0 else " If popup is overflow from buffer window, popup like followings. " " +=========================+ " | +-----------------+| " | |const foo: string|| " | +-----------------+| " | { bar, baz, bazz, foo }| " | ^ | " | cursor is here | | " +=========================+ " let l:col = l:current_col + (&columns - (l:current_col + l:max_width + l:border_size)) + 1 endif endif " line position let l:current_line = winline() let l:popup_height = len(l:contents) + l:border_size " Calc popup overflow size for l:line in l:contents let l:width = strlen(l:line) if l:width + l:border_size >= &columns let l:popup_height += 1 endif endfor let l:lnum = l:current_line < l:popup_height \ ? l:current_line + 1 \ : l:current_line - l:popup_height let s:winid = popup_create(split(l:content, '\n'), { \ 'line': l:lnum, \ 'col': l:col, \ 'border': [1, 1, 1, 1], \ 'moved': 'WORD', \ }) let bufnr = winbufnr(s:winid) call setbufvar(winbufnr(s:winid), '&filetype', &filetype) return s:winid endfunction command! TsHintPopup :call s:ts_hint_popup() noremap <silent> <buffer> <Plug>(TsuHintPopup) :<c-u>TsuHintPopup<CR>
Tsuquyomi には変数とかシグネチャーを取得する関数があるので、それを利用して、Vim のポップアップに流し込んだだけ。
その 2
Angular を書いてて、html でも補完とか、定義ジャンプを使いたい(こっちがメイン)。 Angular は LSP を提供してるので、それを使う。 VSCode で Angular Language Service(angular.ng-template-0.802.3) の拡張を入れる(angular.ng-template-0.900.3 はうまく動いてなかったので要調査)。
Angular + vim-lsp で完全に勝利した。 pic.twitter.com/eF8vyTdGSL
— heavenshell (@heavenshell) October 29, 2019
function! s:is_angular() let current = expand('%:p:h') let path = findfile('angular.json', current . ';') if path == '' return 0 endif return 1 endfunction augroup Angular let s:server = expand('~/.vscode/extensions/angular.ng-template-0.802.3/server/server.js') let g:lsp_async_completion = 1 autocmd User lsp_setup call lsp#register_server({ \ 'name': 'Angular Language Service', \ 'cmd': {server_info -> [&shell, &shellcmdflag, printf('node %s --stdio', s:server)]}, \ 'root_uri':{server_info -> lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_file_directory(lsp#utils#get_buffer_path(), 'angular.json'))}, \ 'whitelist': ['html'], \ }) augroup END autocmd FileType html if s:is_angular() | setlocal omnifunc=lsp#complete | endif
なお Angular の TS なファイルは普通に Tsuquyomi で何の問題もなく動いている。
追記
最新 の angular.ng-template-0.900.3
の場合。
let base = expand(printf('~/.vscode/extensions/%s', 'angular.ng-template-0.900.3')) let node_modules = printf('%s/node_modules/', base) let ng = expand(printf('--ngProbeLocations %s/server', base)) let ts = expand(printf('--tsProbeLocations %s', node_modules)) let s:server = printf('%s/server %s %s', base, ng, ts)
とすればうまくいく。
また angular.ng-template-0.802.3
は適当に GitHub からダウンロードして、
yarn yarn compile
して出来上がった /angular.ng-template-0.802.3/server/out/server.js
を let s:server
に指定すれば OK。