TL;DR
今回紹介するプラグイン
xuhdev/vim-latex-live-preview
VimでTeXのリアルタイムプレビューを可能にするプラグインです。
今回はこれにページ追従を加えます。
プラグイン導入
プラグインマネージャとしてdeinを使っている場合はこれで動くと思います。
オプションの-shell-escapeは内部で追加されているのでここで指定する必要はないです。
[[plugins]]
repo = 'xuhdev/vim-latex-live-preview'
on_ft = 'tex'
hook_add = '''
let g:livepreview_previewer = 'evince'
" let g:livepreview_engine = 'luajittex --fmt=luajitlatex.fmt' "コンパイル速度を上げたい場合はこちら
let g:livepreview_engine = 'lualatex'
set swapfile
set updatetime=1000
'''
追加する関数
自分でプラグインを変更したくない方はこちら
ソースコードの行番号と生成されたpdfのページ番号の対応をダンプする関数
function!s:Preprocess(file)
execute s:py_exe"<< EEOOFF"
with open(vim.eval("a:file"),"r")asf:
lines =f.readlines()foriin range(len(lines)-1):
lines[i]='\write\pagedump{\ \\thepage ,}'+ lines[i]
lines[-1]='\write\pagedump{\ \\thepage ]}'+ lines[-1]
lines.insert(0,'\\newwrite\pagedump\n')
lines.insert(1,'\openout\pagedump=pagedump.txt\n')
lines.insert(2,'\write\pagedump{let pagedump = [}')
lines.append('\closeout\pagedump')
with open(vim.eval("a:file"),"w")asf:f.writelines(lines)
EEOOFF
endfunction
この関数の動きを説明します。以下のようなTeXソースコードがあったとき、
\documentclass{ltjsarticle}\begin{document}
page1
\newpage
page2
\end{document}
次のようにコンパイル前に前処理をします。
\newwrite\pagedump\openout\pagedump=pagedump.txt
\write\pagedump{let pagedump = [}\write\pagedump{\ \thepage ,}\documentclass{ltjsarticle}\write\pagedump{\ \thepage ,}\begin{document}\write\pagedump{\ \thepage ,}page1
\write\pagedump{\ \thepage ,}\newpage\write\pagedump{\ \thepage ,}page2
\write\pagedump{\ \thepage ]}\end{document}\closeout\pagedump
コンパイルすると次のような配列の定義ファイルが$TEXMFOUTPUT/pagedump.txt
に書き出されます。
これをvimからsource pagedump.txt
することでカーソル行とpdfのページ番号の対応を扱うことができます。
let pagedump =[\1,\1,\1,\1,\2,\2]
s:Compile()
の末尾でコンパイル直前にs:Preprocess
を呼ぶように書き換えます
" Write the current buffer in a temporary filesilent exec 'write! '.b:livepreview_buf_data['tmp_src_file']calls:Preprocess(b:livepreview_buf_data['tmp_src_file'])calls:RunInBackground(b:livepreview_buf_data['run_cmd'])lcd-endfunction
evinceにページ番号を指定するキーストロークを投げる関数
私の使っているWSLとXmingの組み合わせでは、WSL内からxdotoolでキーを投げるとXmingが扱っているウィンドウのうち、直近に選択されたウィンドウに投げられる。という挙動になっています。
そのため、Vimの中からフォーカスを外さずに裏のevinceにキーストロークを投げることができます。
当然ながら、他の環境ではこの関数を書き換える必要があります。
function!g:EvinceGoTo()
execute 'source '. \b:livepreview_buf_data['tmp_dir']. \ expand('%:p:h'). \'/pagedump.txt'call system("xdotool key 'ctrl+l'")call system("xdotool key 'ctrl+a'")call system("xdotool key ".g:pagedump[getcurpos()[1]-1])call system("xdotool key KP_Enter")endfunction
操作方法
これで:LLPStartPreview
でevinceを表示したのち、:call EvinceGoTo()
でカーソル行のページが表示されます。
nnoremap <Leader>e:<C-u>call EvinceGoTo()<CR>
としておけばSpace d
ですみます。(私は<Leader>
にスペースを指定している)
ただし、現状:call EvinceGoTo()
ごとにpagedump.txt
を読み込みに行っているので、autocmd cursormoved
でフックするにはもうすこしpagedump.txt
の読み出しタイミングを工夫する必要がありそうです。
〆
明日はクリスマス・イブですね、VimConf2018ではDark Poweredな発表で話題だったΛlisueさんの記事になります。
全く関係ないですが下は大学で最近見かけたポスターです。いったいモデルは何すえさんなのか?…。
そういえばVimConf2018ではVimの父Bramさんからサインを頂いちゃいました。
Vimの父Bram氏からSurfaceにサイン貰った!#vimconfpic.twitter.com/5L52g5v8ed
— ℕ (@mathbbN) 2018年11月24日
それでは、Happy Vimming!