LoginSignup
7
4

More than 5 years have passed since last update.

Vim+TeXでページ追従

Last updated at Posted at 2018-12-23

TL;DR

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

今回紹介するプラグイン

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

プラグイン導入

プラグインマネージャとしてdeinを使っている場合はこれで動くと思います。
pdfビューアはevinceを指定しています。試した限りではevinceが最もよく動きました。
pLaTeXでなくLuaLaTeXを指定しているのは中間ファイルを作らず、直接pdfを出力するからです。
jsarticle/jsreport/jsbookと高い互換性のある文書クラスltjsarticle/ltjsreport/ltjsbookがあるので、表紙テンプレートがpLaTeX版で渡されるなどしても簡単に対応できると思います。

~/.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") as f:
    lines = f.readlines()
for i in 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") as f:
    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 file
    silent exec 'write! ' . b:livepreview_buf_data['tmp_src_file']
    call s:Preprocess(b:livepreview_buf_data['tmp_src_file'])
    call s: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 eですみます。(私は<Leader>にスペースを指定している)
ただし、現状:call EvinceGoTo()ごとにpagedump.txtを読み込みに行っているので、autocmd cursormovedでフックするにはもうすこしpagedump.txtの読み出しタイミングを工夫する必要がありそうです。

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

それでは、Happy Vimming!

7
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4