YaTeX はカスタマイズ性に優れ,かゆいところに手が届くどころか YaTeX の機能を使いたいが為にかゆいところを探すほどである.
他の統合環境とは違い,設定さえできればどのようなマクロに対しても自由自在に入力支援が得られる.
特にマクロを自作する人やオプション引数に keyval が多用されているマクロやパッケージをよく利用する人は YaTeX 一択と言い切れる程である.
さらに,lisp に慣れていない人のために自作の入力支援関数を作成するためのパッケージも付属している.
詳しくは yatex/docs/yatexadd.doc
や yatex/yatexadd.el
および
yatex/docs/yatexgen.doc
や yatex/yatexgen.el
を参照のこと.
YaTeX の入力支援関数の作成支援を体験してみたい人は TeX のソースファイルで M-x YaTeX-generate や
M-x YaTeX-generate-simple してみるといいかもかも.
もちろん YaTeX がパーフェクトであるというつもりはない.ちょっとした愚痴もある.
以下は YaTeX のヘルプなどから抜き出し,私の変更点を加えただけのものである.
なお,emacs で YaTeX のヘルプを見ようとしても文字化けして見れないという人は,
騙されたと思って C-x [ENTER] r sjis-dos [ENTER] としてみてください.
理由はわからないが Melpa で配布されている YaTeX パッケージは2019年2月1日現在 docs
,help
の2つのディレクトリが含まれていない.
すなわち,help/YATEXHLP.(jp|eng)
の2つのファイルが含まれていないため Emacs からヘルプを見ることができない.
Melpa のよいところがまったく活かせないので早くどうにかしてもらいたい.
YaTeX のメッセージを英語/日本語の選択をする(default : nil [英語])
t [日本語]
この変数の値によっていくつかの変数のデフォルトが変化する. tex-command は,YaTeX-use-LaTeX2e が t のとき platex が設定され, YaTeX-use-LaTeX2e が nil のときかつ YaTeX-japan が t のとき jlatex が設定され, いずれも nil ならば latex が設定される. 以下,YaTeX-japan の値に関して, bibtex-command は,t のとき jbibtex,nil のとき bibtexが設定される. YaTeX-default-document-style および YaTeX-default-documentclass は,t のとき jsarticle,nil のとき articleが設定される. mode-name は,t のとき やてふ,nil のとき YaTeX が設定される. help-file は,t のとき YATEXHLP.jp,nil のとき YATEXHLP.eng が設定される. ちなみに,YaTeX モードのとき C-c C-x I とすると YaTeX のヘルプファイルが表示される. (1.81.2 より YaTeX-default-document-style と YaTeX-default-documentclass の挙動が同じになる. 以前は YaTeX-japan が t のとき YaTeX-default-documentclass は jarticle であった.)
YaTeX-use-LaTeX2e | bibtex-command | YaTeX-default-document-style | YaTeX-default-documentclass | mode-name | help-file | |||
---|---|---|---|---|---|---|---|---|
t | nil | |||||||
YaTeX-japan | t | platex | jlatex | jbibtex | jsarticle | やてふ | YATEXHLP.jp | |
nil | latex | bibtex | article | YaTeX | YATEXHLP.eng |
これらの値が気に入らないときは,yatex.el
を読み込んだ後に (setq tex-command "/usr/local/bin/ptex2pdf -l -u")
などと変更すればよい.
文書を作成する時の漢字コード(default : nil = 既存のコードのまま)
pLaTeX を使っているのであればデフォルトの nil でいいが,LuaLaTeX を使っているため 4 に設定し強制的にソースファイルの文字コードを UTF-8 にしている. ソースを utf-8 で記述しなければならない uplatex,XeLaTeX を使う人も 4 に設定しておいた方がいいだろう.
0=no-conversion
,1=Shift JIS
,2=JIS
,3=EUC
,4=UTF-8
4
LaTeX タイプセッタコマンド名(default : platex)
基本的にタイプセットに関する設定はメインのソースファイルの冒頭に %#!lualatex -synctex=1
と設定しているので,
この設定はほとんど使われることはない.
filename
ptex2pdf -l -u -ot '-synctex=1'
プレヴューアコマンド名(default : xdvi -geo +0+0 -s 4)
/usr/bin/evince
makeindex コマンド(default : makeindex)
mendex -g -s mystyle.ist
dvi を PDF に変換するコマンド(default : dvipdfmx)
\item
の桁揃えの時に用いる,\item
の正規表現(default : (concat (regexp-quote "\\") "\\(sub\\|bib\\)*item"))
edaenumerate
環境および hlist
環境を使用することにしたので \edaitem
と \hitem
も含める.
(eval-after-load 'yatex (setq YaTeX-item-regexp (concat (regexp-quote "\\") "\\(sub\\|bib\\|eda\\|h\\)*item")))
C-c C-b ?? のショートカットを使わず,C-c C-b だけで補完入力に入る(default : nil)
t
\include
などで C-c C-g した時に,
ジャンプ先が存在しないファイルであってもオープンする(default : nil)
個人的には t にしておいた方が自分でファイルを作成する手間が省けて嬉しい.
\include
の引数を間違えておかしなファイル名のバッファができたとしてもすぐに C-x k すればバッファから消え去るから問題ない.
t
AMS-LaTeX を使用する場合は t に設定する(default : nil)
align
環境など amsmath パッケージで定義されている環境を利用するのであれば t に設定する.
nil では align
環境等で数式モードで動作しない.
t
Emacs 24.4 で導入された改行時の,自動インデントをどうするか. この値がそのまま electric-indent-local-mode に渡される. -1 で off.
Emacs 24.4 以降のヴァージョン場合,デフォルトのままでは enumerate
環境などで改行をした場合勝手に桁揃えをしてくれない.
Emacs 24.4 以前のヴァージョンの動作が好みの場合は t にしておく.
t
ヘルプでは「環境タイプセット」「on-the-fly プレビュー」「環境即時プレビュー」「即時プレビュー」などブレがあるが C-c C-t e として動作する機能があり, それは一般的にはポイントが含まれる最も内側の環境や数式環境内の場合はポイントが含まれる数式環境全体を自動で領域タイプセットしプレビューする機能であり, これが動作するとその環境内で文字等の修正が行われる度に自動で新たにタイプセット及びプレビューが行われるのだが, その際のキー入力から動作するまでの無動作時間を設定する変数である. ただし,nil を指定した場合は「環境タイプセット」は動作しない. この「環境タイプセット」は一度動作をすると YaTeX ではその動作を解除する手法が与えられておらず, 他のバッファに一度移動するなどをすることで解除できるが, 勝手に何度も入力者の意志に反してタイプセットが行われるのは甚だ鬱陶しいのでこの機能を動作しないように nil にしている.
ヘルプには nil で動作しないようなことが書いてあるのだが,2018年1月7日時点では nil でも「環境タイプセット」が動作してしまう.
nil
\ref{}
のラベル名自動生成のときに使う関数のシンボル.
デフォルトは標準の YaTeX::ref-generate-label 関数が割り当ててある.
引数を2つ取る関数を定義して,この変数にセットするとその関数を呼んだ結果をデフォルトのラベル名候補とする.
この2つの引数は C-c C-s ref で \ref
コマンドを利用したときにそのラベルを自動生成し,
さらに対応する \label
コマンドの位置を指定するが,
そのときに選択したアイテムに合わせて,第1引数にはそのコマンドや環境名,第2引数には第1引数が \section
系の場合その引数が設定される.
例えば \label
位置の選択で align
環境内の行を選択すると第1引数には align,第2引数は空文字列 ,
\setction{hoge}
を選択したすると第1引数には section,第2引数には hoge が代入される.
このことを利用するとデフォルトでは \ref
を設定するとそのラベルは時刻を用いた文字列が自動で生成されるが,
好みの任意のラベルをつけることができるようになる.
以下はこの変数の設定例を参考にした私の設定である(ほとんど設定例のままであるが…).
(eval-after-load 'yatexadd `(progn (setq YaTeX::ref-mathenv-regexp (concat YaTeX::ref-mathenv-regexp "\\|\\(sub\\)?numcases") YaTeX-ref-generate-label-function 'my-yatex-generate-label) (defun my-yatex-generate-label (command value) (and (string= command "caption") (re-search-backward "\\\\begin{\\(figure\\|table\\)}" nil t) (setq command (match-string 1))) (let ((alist '(("chapter" . "chap") ("section" . "sec") ("subsection" . "subsec") ("figure" . "fig") ("table" . "tbl") ("align" . "eq") ("gather" . "eq") ("numcases" . "eq") ("subnumcases" . "eq") ("equation" . "eq") ("eqnarray" . "eq") ("item" . "enu"))) (labelname (replace-regexp-in-string "\\(:\\|-\\)" ":" (concat (if (> (length YaTeX-parent-file) 0) (concat (file-name-sans-extension (file-name-nondirectory YaTeX-parent-file)) ":")) (file-name-sans-extension (file-name-nondirectory (buffer-name))))))) (if (setq command (cdr (assoc command alist))) (concat command ":" (read-string "ユニークなラベルになるような文字列・番号などを入力してください: " (concat labelname ":" value))) (YaTeX::ref-generate-label nil nil)))) ))
YaTeX::ref-mathenv-regexp は C-c C-s ref で検索する \label
を付けられる数式環境の一覧であり,
その一覧に \\|\\(sub)?numcases を追加している.
例えば,親ファイルが main.tex
,子ファイルが child.tex
で
C-c C-s ref で \label
をつける場所を align
環境に設定し,
pythagorean-theorem
という文字列を入力した場合,\ref
および \label
の引数は,
eq:main:child:pythagorean-theorem
という文字列が設定される.
ちなみに YaTeX::ref-generate-label は,デフォルトの \ref
および \label
の引数を作成する関数であり,時間を元に引数が作成される.
また,YaTeX-parent-file は,メインファイルのディレクトリを含めた文字列が代入されているようである.
恥ずかしながら最近まで C-c C-s label
で \label
を設定し C-y で \ref
を貼り付けていた.しかし,これは間違った使い方である.
\ref
を設定し,それに応じて \label
が設定されるべきというポリシーのもとに YaTeX が設計されている.
他の統合環境などと比較して YaTeX の素晴らしい点として,強力な入力支援とそのカスタマイズ性が挙げられる.
例えば,enumitem パッケージの enumerate
環境のオプションとして resume というのがあるが,
C-c C-b enumerate したときにオプション resume を利用するかどうか聞くようにしたいときは次のようにする.
(defun YaTeX:enumerate () ((let (op (if y-or-n-p "resume オプションを使いますか? ") "resume")) (if (> (length op) 0) (concat "[" op "]"))))
これは非常に簡単な例であるが,工夫次第で様々なオプションに対応した入力支援が得られる. 以下は,その工夫時に利用できる予め YaTeX で定義されている関数である.
YaTeX:read-position
(引数:[]
の中に入れてもよい文字を羅列した文字列)
[htb]
などのような location 指定を作成します.
何も入力せずリターンを押すと,[]
自体も省略されます.
[]
の中に来るべき文字が htbp
に限られているなら,(YaTeX:read-position htbp)
と呼び出します.
YaTeX:read-coordinates
(基本プロンプト,X座標プロンプト,Y座標プロンプト(全て省略可))
「基本プロンプト X座標プロンプト:」というプロンプトを出して,X座標を読み込み,
「基本プロンプト Y座標プロンプト:」を出して,Y座標を読み込み,(X座標,Y座標) の様な形式を作成します.
何も入力せずリターンを押しても,(,)
が返されます.
各プロンプトのデフォルトはそれぞれ,Dimension, X, Y です.
YaTeX-intelligent-newline-foo
YaTeX では enumerate
環境や tabular
環境で M-[ENTER] や ESC [ENTER] とすると「おまかせ改行」機能が働くが,
enumitem
パッケージなどで \newlist{centerenum}{enumerate}{1}
などとして新たな enumerate
環境を定義した場合,
これらの環境でも「おまかせ改行」をして欲しくなる.
このとき使うのが YaTeX-intelligent-newline-foo
である.
foo
の部分は対応させる環境により決まる.
今回の例の場合は ~/.emacs.d/init.el
において
(fset 'YaTeX-intelligent-newline-centerenum 'YaTeX-intelligent-newline-itemize)
としておくと,
新たに定義した centerenum
環境でも itemize
環境と同様に「おまかせ改行」が利用できるようになる.
また,hlist パッケージの hlist
環境は \linewidth
を等間隔に分割して enumerate
環境のように番号付けを行う環境(emath の edaenumerate
環境に相当する)であるが,
\item
ではなく \hitem
で項目を指定する.
この場合は YaTeX-intelligent-newline-itemize
の定義を模倣して次のようにする.
(YaTeX-intelligent-newline-hlist ()
"Insert '\\hitem' ."
(insert "\\hitem ")
(YaTeX-indent-line))
自作した入力支援用関数などは yatexhks.el
に記述するように指示されているが,もしものことを考え,
my-func.el
などというユニークなファイルを作成してそれに記述し,
yatexhks.el
内に (require 'my-func)
とだけ記述するほうが YaTeX 一式を新調したときも自作の関数は上書きされず安全である.
lisp 初心者でヘルプなどを見様見真似で作ったものである.
emath という接頭語がついているが,これらは元々が emath の pszahyou
環境のオプションを覚えきれなかったため,
足りない頭の代わりに YaTeX に頑張ってもらおうとして関数を作成したという経緯のためである.
emath を my などに置換すればいいのだろうが,
如何せん置換した後に問題なく動くという自信がないので置換していない.
この接頭語は無視してください.
emath-select-key-value
(emath-select-key-value "hoge" "[option]" `(("ふが" "fuga") ("あわわ" "awawa")))
とすると,``[option] 0:設定しない 1:ふが 2:あわわ: '' という選択肢を表示し,
入力した数字によって 1 --> hoge=fuga 2 -->hoge=awawa という文字列を返す.
"hoge"を""としたときは 1--> fuga 2-->awawa という文字列を返す.
下請けの関数で直接使うことはまずない.
定義は次の通りである.
(defun emath-select-key-value (key title lists) (let* ((guidelist (mapcar 'car lists));;lists内の各々のリストに対してcarを実行して新たなリストを作成 (valuelist (mapcar '(lambda (x) (nth 1 x)) lists));;mapcarの第1引数が引数をとる関数のときの処理 ;; この無名関数はリストの引数を1つとりその2番目の要素を返す ;; すなわち valuelist は lists の要素である各々のリストに対して2番目の要素を次々と取り出して並べたリスト (emnum (emath-get-number-from-list title guidelist))) (if (or (< emnum 1)(> emnum (length guidelist))) "" (emath-option-combine "=" `(,key ,(nth (- emnum 1) valuelist))))))
emath-get-number-from-list
emath-select-key-value
の下請け関数.
(emath-get-number-from-list "[option]" `("ほげ" "ふが" "あわわ") "attention")
で,
"[option] 1:ほげ 2:ふが 3:あわわ attention" と表示し数字の入力を促し,入力された数値を返す.
単独で (cond ((= num 1)(...))((= num 2)(...))(()()))
などの num の設定にも使える.
定義は次の通りである.
(defun emath-get-number-from-list (title guides &optional addguide) (message (format "%s%s%s: " (if (> (length title) 0)(concat title " ")"") (emath-make-guide 1 guides) (if (> (length addguide) 0) addguide ""))) (let* ((string (read-char))) (string-to-number (char-to-string string))))
emath-make-guide
emath-get-number-from-list
の下請け関数.
(emath-make-guide 0 `("ほげ" "ふが" "あわわ"))
で,
第2引数の list から中身を順に取り出し 0:ほげ 1:ふが 2:あわわ のように番号付けをした文字列を作り出す.
第1引数が 1 なら 1:ほげ 2:ふが 3:あわわ となる.
定義は次の通りである.
(defun emath-make-guide (num guides) (let* ((emnum num) (emlist (mapcar '(lambda (x) (prog1 (format "%s:%s " emnum x) (setq emnum (+ emnum 1)))) guides))) (mapconcat 'concat emlist "")))
emath-option-combine
emath-select-key-value
の下請け関数.
(emath-option-combine separator optionlist)
で,
optionlist の中身を separator で繋げる.
そのときリスト内の文字列の前後のどちらか空文字列 "" であれば separator はつかない.
リスト内に変数 var1,var2,var3 がある場合は `(,var1 ,var2 ,var3)
と指定する.
具体的には,separator が "," で optionlist が
("a" "" "b" "" "c" "d" "" "" "" "e" "f" "" "")
の場合,
"a,b,c,d,e,f"
という文字列を作り出す.
定義は次の通りである.
(defun emath-option-combine (separator oplist) (let* ((emlist (split-string (mapconcat 'concat oplist separator) (concat separator "+") t))) (mapconcat 'concat emlist separator)))
emath-setoption
ここからが本命.
(emath-setoption options str guide leftbrace rightbrace default)
で,
変数 options に追加する文字列を guide を表示し文字列の入力を促し,
(concat options ",str=leftbrace入力文字列rightbrace")
という文字列を返す.
ただし,入力文字列が空文字列 "" の場合は options をそのまま返す.
leftbrace 以降はオプショナルであり,デフォルトは空文字列 "" である.
options は空文字列 "" でも構わない.
具体的な使用例は,次のようなコードを yatexhks.el
などに記述し
C-c C-s hoge などと YaTeX の入力支援を実行すると,
順に「左マージンの指定: 」「右マージンの指定: 」「背景色の指定: 」と聞いてくるので,
例えば順に「10pt」「」(Enterキーを押すだけ)「red」と入力すると,
変数 op に leftmargin=10pt,background-color=red という文字列が代入される.
するとソースファイルに \hoge[leftmargin=10pt,background-color=red]{}
という文字列が追加される.
このように keyval 系の複数のオプションの付加を容易にするための関数である.
(defun YaTeX:hoge () (let* ((op (emath-setoption "" "leftmargin" "左マージンの指定")) (op (emath-setoption op "rightmargin" "左マージンの指定")) (op (emath-setoption op "background-color" "背景色の指定"))) (if (> (length op) 0) (concat "[" op "]"))))
例えば,オプションが coord={(1,2)}
のように「,
」が含まれる場合はオプションの指定に使う文字列を「{}
」でくくらなければならない.
そのようなときは
(emath-setoption op "coord" "座標の指定" "{" "}")とする. また,オプションの指定文字列としてよく使う文字をデフォルトで入力済みにするときは
(emath-setoption op "color" "色の指定" "" "" "black")などとする.この場合は「色の指定: black」のように最初から文字列「
black
」が「色の指定:」と同時に出力される.
これにより出力される文字列「black
」はミニバッファで編集可能である.
定義は次の通りである.
(defun emath-setoption (options key guide &optional leftbrace rightbrace default) (let* ((temp (read-string (format "[option] %s: " guide) default)) (emleft (if leftbrace leftbrace "")) (emright (if rightbrace rightbrace "")) (emoption (concat options "," (if (> (length temp) 0) (format "%s=%s%s%s" key emleft temp emright) ""))) (emlist (split-string emoption "," t))) (mapconcat 'concat emlist ",")))
emath-tenretu-loop
(emath-tenretu-loop separator guide seq)
で,
guide を表示して入力を促し,入力されたものを separator で区切って繋げていく.
Enterキーのみを押すと終了する.
具体的な使用例は,次のコードを yatexhks.el
などに記述し
C-c C-m draw などと YaTeX の入力支援を実行すると,「折れ線が通る点を順に入力:」と聞いてくるので,
順に「(A)」「(B)」「(C)」「」と入力すると,
ソースファイルに \draw(A)--(B)--(C);
という文字列が代入される.
seq はこの関数が再帰的に使用される際に用いるもので通常は指定する必要はない.
(defun YaTeX:draw () (concat (emath-tenretu-loop "--" "折れ線が通る点を順に入力") ";"))
定義は次の通りである.
(defun emath-tenretu-loop (separator guide &optional seq) (let* ((empoint (read-string (format "%s: " guide)))) (if (> (length empoint) 0) (let* ((empoint (emath-option-combine separator `(,seq ,empoint)))) (emath-tenretu-loop separator guide empoint)) (concat seq))))
連携を行うための下準備として,~/bin
に次のコードからなる fwdevince
というファイルを作成して,
chmod +x fwdevince として実行権限を与える.
ただし,python のバージョンは3以上でなければ動作しないので python -V としてバージョンを確かめ,
#!/usr/bin/python
は環境によって #!/usr/bin/python3
などと変更する必要がある.
fwdevince 本体 (7.6KB)
また,TeX をコンパイルする際はオプションに -synctex=1 を付加する.
TeX のソースの冒頭に %#!uplatex -synctex=1
source file name
や
%#!ptex2pdf -l -u -ot "-synctex=1"
source file name
などと記述するか,
~/.emacs.d/init.el
(Spacemacs の場合は .spacemacs
の dotspacemacs/user-config) に (setq tex-command "lualatex -synctex=1")
などと記述しておけばよい.
#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright (C) 2010 Jose Aliste # 2011 Benjamin Kellermann # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public Licence as published by the Free Software # Foundation; either version 2 of the Licence, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public Licence for more # details. # # You should have received a copy of the GNU General Public Licence along with # this program; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA import dbus import argparse import os.path import traceback import sys import urllib.parse class EvinceForwardSearch: def parse_args(self): parser = argparse.ArgumentParser(description='Forward search with Evince') parser.add_argument('pdf', nargs=1, help='PDF file') parser.add_argument('line', nargs=1, type=int, help='Line') parser.add_argument('tex', nargs=1, help='TeX file') return parser.parse_args() def run(self): args = self.parse_args() pdf = os.path.abspath(args.pdf[0]).replace(" ", "%20") line = int(args.line[0]) tex = os.path.join(os.path.dirname(os.path.abspath(args.tex[0])), './', os.path.basename(os.path.abspath(args.tex[0]))) try: import time bus = dbus.SessionBus() daemon = bus.get_object('org.gnome.evince.Daemon', '/org/gnome/evince/Daemon') dbus_name = daemon.FindDocument('file://' + urllib.parse.quote(pdf, safe="%/:=&?~#+!$,;'@()*[]"), True, dbus_interface='org.gnome.evince.Daemon') window = bus.get_object(dbus_name, '/org/gnome/evince/Window/0') time.sleep(0.2) window.SyncView(tex, (line, 1), 0, dbus_interface='org.gnome.evince.Window') except dbus.DBusException: traceback.print_exc() class EvinceInverseSearch: def parse_args(self): parser = argparse.ArgumentParser(description='Inverse search with Evince') parser.add_argument('pdf', nargs=1, help='PDF file') parser.add_argument('editor', nargs=1, help='Editor command') return parser.parse_args() def run(self): import dbus.mainloop.glib from gi.repository import GObject args = self.parse_args() pdf = os.path.abspath(args.pdf[0]) editor = args.editor[0] dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) a = EvinceWindowProxy('file://' + pdf, editor, True) loop = GObject.MainLoop() loop.run() class EvinceWindowProxy: """A Dbus proxy for an Evince Window.""" daemon = None bus = None RUNNING = range(2) CLOSED = range(2) EV_DAEMON_PATH = '/org/gnome/evince/Daemon' EV_DAEMON_NAME = 'org.gnome.evince.Daemon' EV_DAEMON_IFACE = 'org.gnome.evince.Daemon' EVINCE_PATH = '/org/gnome/evince/Evince' EVINCE_IFACE = 'org.gnome.evince.Application' EV_WINDOW_IFACE = 'org.gnome.evince.Window' def __init__(self, uri, editor, apawn=False, logger=None): self._log = logger self.uri = uri.replace(" ", "%20") self.editor = editor self.status = self.CLOSED self.source_handler = None self.dbus_name = '' self._handler = None try: if EvinceWindowProxy.bus is None: EvinceWindowProxy.bus = dbus.SessionBus() if EvinceWindowProxy.daemon is None: EvinceWindowProxy.daemon = EvinceWindowProxy.bus.get_object(self.EV_DAEMON_NAME, self.EV_DAEMON_PATH, follow_name_owner_changes=True) EvinceWindowProxy.bus.add_signal_receiver(self._on_doc_loaded, signal_name='DocumentLoaded', dbus_interface=self.EV_WINDOW_IFACE, sender_keyword='sender') self._get_dbus_name(False) except dbus.DBusException: traceback.print_exc() if self._log: self._log.debug('Could not connect to the Evince Daemon') def _on_doc_loaded(self, uri, **keyargs): if uri == self.uri and self._handler is None: self.handle_find_document_reply(keyargs['sender']) def _get_dbus_name(self, spawn): EvinceWindowProxy.daemon.FindDocument(self.uri, spawn, reply_handler=self.handle_find_document_reply, error_handler=self.handle_find_document_error, dbus_interface = self.EV_DAEMON_IFACE) def handle_find_document_error(self, error): if self._log: self._log.debug('FindDocument DBus call has failed') def handle_find_document_reply(self, evince_name): if self._handler is not None: handler = self._handler else: handler = self.handle_get_window_list_reply if evince_name != '': self.dbus_name = evince_name self.status = self.RUNNING self.evince = EvinceWindowProxy.bus.get_object(self.dbus_name, self.EVINCE_PATH) self.evince.GetWindowList(dbus_interface = self.EVINCE_IFACE, reply_handler = handler, error_handler = self.handle_get_window_list_error) def handle_get_window_list_error (self, e): if self._log: self._log.debug("GetWindowList DBus call has failed") def handle_get_window_list_reply (self, window_list): if len(window_list) > 0: window_obj = EvinceWindowProxy.bus.get_object(self.dbus_name, window_list[0]) self.window = dbus.Interface(window_obj,self.EV_WINDOW_IFACE) self.window.connect_to_signal("SyncSource", self.on_sync_source) else: #That should never happen. if self._log: self._log.debug("GetWindowList returned empty list") def on_sync_source(self, input_file, source_link, timestamp): import subprocess import re print(input_file + ':' + str(source_link[0])) # This is probably useless input_file = input_file.replace("%20", " ") # This is to deal with source files with non-ascii names # We get url-quoted UTF-8 from dbus; convert to url-quoted ascii # and then unquote. If you don't first convert ot ascii, it fails. # It's a bit magical, but it seems to work #input_file = urllib.parse.unquote(input_file.encode('ascii')) input_file = urllib.parse.unquote(input_file) print(type(input_file), input_file) #cmd = re.sub("%f", input_file, self.editor) cmd = re.sub("%f", input_file.replace('file://', ''), self.editor) cmd = re.sub("%l", str(source_link[0]), cmd) print(cmd) subprocess.call(cmd, shell=True) if self.source_handler is not None: self.source_handler(input_file, source_link, timestamp) if __name__ == '__main__': cmd = os.path.basename(sys.argv[0]) if cmd == 'fwdevince' or cmd == 'evince_forward_search': EvinceForwardSearch().run() elif cmd == 'invevince' or cmd == 'bwdevince' or cmd == 'evince_inverse_search' or cmd == 'evince_backward_search': EvinceInverseSearch().run() else: sys.stderr.write("rename 'fwdevince' or 'invevince'\n") sys.exit(1)
YaTeX から evince への連携は,以下を ~/.emacs.d/init.el
(Spacemacs の場合は .spacemacs
の dotspacemacs/user-config) に次のコードを記述すると平文で
C-c C-g でカーソル位置に対応する PDF ファイルの箇所に飛ぶことができる.
(setq YaTeX-inhibit-prefix-letter t) (setq YaTeX-dvi2-command-ext-alist '((Preview\\|evince\\|okular\\|zathura\\|qpdfview\\|pdfopen\\|xdg-open\\|open\\|start" . ".pdf"))) (setq dvi2-command "evince") (setq tex-pdfview-command "evince")
evince から YaTeX への連携は,以下を ~/.emacs.d/init.el
(Spacemacs の場合は .spacemacs
の dotspacemacs/user-config) に記述すると evince で ctrl + 右クリック でクリックした場所に該当する TeX のソースに飛ぶ.
(require 'dbus) (defun un-urlify (fname-or-url) "A trivial function that replaces a prefix of file:/// with just /." (if (string= (substring fname-or-url 0 8) "file:///") (substring fname-or-url 7) fname-or-url)) (defun evince-inverse-search (file linecol &rest ignored) (let* ((fname (decode-coding-string (url-unhex-string (un-urlify file)) 'utf-8)) (buf (find-file fname)) (line (car linecol)) (col (cadr linecol))) (if (null buf) (message "[Synctex]: %s is not opened..." fname) (switch-to-buffer buf) (goto-line (car linecol)) (unless (= col -1) (move-to-column col))))) (dbus-register-signal :session nil "/org/gnome/evince/Window/0" "org.gnome.evince.Window" "SyncSource" 'evince-inverse-search)
私は Spacemacs を用いているのだが helm と YaTeX の相性がいいようには見えない.
そのため,Emacs YaTeX/yahtml の入力支援では helm を無効にする
を参考にして YaTeX が動作中には helm が使えないようにしている.具体的には,~/.spacemacs
の dotspacemacs/user-config に次の1011行を追加している.
(ad-to-list 'helm-completiong-read-handlers-alist '(YaTeX-change-environment . nil))
を追加する.
(with-eval-after-load "helm-mode" (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-accent . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-begin-end . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-fontsize . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-section . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-singlecmd . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-begin-end-region . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-fontsize-region . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-make-section-region . nil)) (add-to-list 'helm-completing-read-handlers-alist '(YaTeX-change-environment . nil)) )
\ref
コマンドを入力時に \label
を挿入する候補がズラッと並べられるが,enumerate
環境を多用していると
\item
ばかりが並んでどれを選択していいのかわからなくなる.
特に enumerate
環境を入れ子にしているときは最悪である.
と思っているのかもしれないが,
\item
だけを絞り込めるから大丈夫だろう\item
が7個も8個も並ぶとそこから \label
の正しい挿入位置を選択するのは大変である.
これに関しては作者に入れ子の状態に応じてインデントなどで違いがわかるようにしてもらえないか
と相談したのだが,現在の
と言われた.
本当にこれに関してはどうにか改善してもらいたい…
現状では,\label
を挿入する場所を抽出するロジックでは無理だ\ref
コマンドを入力時に一つの関数で \label
が挿入可能なすべての場所を抽出しそれらを表示するという手法で,必要ならば使用者が「数式環境」
「enumerate
環境」などを絞り込むという方法である.
そして,\label
を挿入する場所をたった一つの関数によって抽出する手法に拘るがためにこのような状況になっている.
それを,\ref
コマンドを入力時に「数式環境」「\chapter
などの見出し用コマンド」「enumerate
環境」「定理環境」などと最初に絞りこませて,
それから各々に応じた \label
を挿入する場所を抽出する関数を呼びだせば済むと思う(現時点では enumerate
環境に対する \label
の挿入位置に関して問題があるので enumerate
環境に関する \label
挿入位置を抽出する関数だけ新規で作成することになると思うが…).
\ref
コマンド入力時に YaTeX 使用者はどこに \label
を挿入したいかわかっているので,\label
挿入位置をすべて抽出した後でどこに挿入するか絞りこませるのではなく,
使用者に \lable
挿入位置を絞りこませてからそこを対象に \label
挿入位置を抽出するという順序でも全く問題がないと思うのだが…
また,enumerate
環境下の \label
コマンドの挿入位置にも不満がある.
と意見したことがあるが,
\item
直後に \label
を挿入しなければ,次の \item
までの間に改ページが起こりそれ以降に \label
が挿入されてしまうと,
\pageref
などをしたときに参照したいページと異なる場合がある
などとトンチンカンな回答をされ無視されている.
何か勘違いをしているのだと思うが,これもどうにかして欲しい案件である.
\ref
が参照する番号はページに依存しないenumerate
環境下で \label
が挿入される度に \item
直後へと移動させているのがとても面倒である.
「C-c C-t e」で起動される「環境タイプセット」が厄介である.
一度設定されるとその環境内で何かしら変更がある度にタイプセットが行われるのだがこれが非常に鬱陶しい.
何故こんなものが作られたのか理解に苦しむ.さらに,一度設定されると解除する方法は YaTeX では準備されていない(少なくともマニュアルには書かれていない).
大抵は \include
された子ファイルでの作業中にミスタイプで「環境タイプセット」が実行されてしまう.
そのときは「C-c ^」で親ファイルに移動してから戻ってくると解除されるようなのでそのようにしている.
「環境タイプセット」をなくせとは言わないが,少なくとも「C-c C-t」としたときに「環境タイプセット」を実行するための「e」だけではなく,
「環境タイプセット」を終了させるためのキーバインドも用意してもらいたい.
個人的には「領域タイプセット」というものがすでに存在しているのだから「環境タイプセット」は不要だと思っている.
マシンパワーが貧弱な YaTeX 利用者にとっては不要なだけでなく迷惑な存在だろう.
2018年1月7日時点では,YaTeX-on-the-fly-preview-interval を nil にしても「環境タイプセット」が動作してしまう.