Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 5608

Vim+TeXでページ追従

$
0
0

TL;DR

こんなことができるようになりました。
20181223_222954.gif

今回紹介するプラグイン

xuhdev/vim-latex-live-preview
VimでTeXのリアルタイムプレビューを可能にするプラグインです。
今回はこれにページ追従を加えます。

プラグイン導入

プラグインマネージャとしてdeinを使っている場合はこれで動くと思います。
オプションの-shell-escapeは内部で追加されているのでここで指定する必要はないです。

~/.vim/rc/dein_lazy.toml
[[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のページ番号の対応をダンプする関数

~/dein/repos/github.com/xuhdev/vim-latex-live-preview/plugin/latexlivepreview.vim
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ソースコードがあったとき、

before_preprocess.tex
\documentclass{ltjsarticle}\begin{document}
page1
\newpage
page2
\end{document}

次のようにコンパイル前に前処理をします。

after_preprocess.tex
\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のページ番号の対応を扱うことができます。

pagedump.txt
let pagedump =[\1,\1,\1,\1,\2,\2]

s:Compile()の末尾でコンパイル直前にs:Preprocessを呼ぶように書き換えます

~/dein/repos/github.com/xuhdev/vim-latex-live-preview/plugin/latexlivepreview.vim
" 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にキーストロークを投げることができます。
当然ながら、他の環境ではこの関数を書き換える必要があります。

~/dein/repos/github.com/xuhdev/vim-latex-live-preview/plugin/latexlivepreview.vim
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()でカーソル行のページが表示されます。

~/dein/repos/github.com/xuhdev/vim-latex-live-preview/plugin/latexlivepreview.vim
nnoremap <Leader>e:<C-u>call EvinceGoTo()<CR>

としておけばSpace dですみます。(私は<Leader>にスペースを指定している)
ただし、現状:call EvinceGoTo()ごとにpagedump.txtを読み込みに行っているので、autocmd cursormovedでフックするにはもうすこしpagedump.txtの読み出しタイミングを工夫する必要がありそうです。

明日はクリスマス・イブですね、VimConf2018ではDark Poweredな発表で話題だったΛlisueさんの記事になります。
全く関係ないですが下は大学で最近見かけたポスターです。いったいモデルは何すえさんなのか?…。
image.png
そういえばVimConf2018ではVimの父Bramさんからサインを頂いちゃいました。

それでは、Happy Vimming!


Viewing all articles
Browse latest Browse all 5608

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>