-
Notifications
You must be signed in to change notification settings - Fork 3
/
tikz.el
253 lines (200 loc) · 8.93 KB
/
tikz.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
;;; tikz.el --- A minor mode to edit TikZ pictures -*- lexical-binding:t -*-
;; Copyright (C) 2020 Emilio Torres-Manzanera <[email protected]>
;; Author: Emilio Torres-Manzanera <[email protected]>
;; Version: 0.14
;; Keywords: tex
;; URL: https://github.com/emiliotorres/tikz
;; Package-Requires: ((emacs "24.1"))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, 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 License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; * ~tikz~ A minor mode to edit TikZ pictures with Emacs
;; ~tikz~ is a minor mode for creating TikZ diagrams with Emacs as an
;; alternative to QtikZ.
;; ** Installation
;; - You should have a running environment of LaTeX.
;; - You should install the [[https://pwmt.org/projects/zathura/][Zathura]]
;; viewer, or change the default configuration.
;; - Copy this file into your =init.el= or load it
;; or use =M-x package-install RET tikz=.
;; ** Using it
;; - Create a Tex file with your favourite preamble.
;; - Once you have fixed the preamble in your document, launch the TikZ mode.
;; #+begin_example
;; M-x tikz-mode
;; #+end_example
;; - Now, when you are in idle time, the pdf will be refreshed
;; automatically with the content of the current buffer.
;; - Every time you modify your preamble, you must turn off/on the TikZ mode.
;; ** Screenshot
;; On the left side, Emacs with a LaTeX buffer with minor mode TikZ. On
;; the right side, Zathura viewing the pdf.
;; [[file:graphics/tikzscreenshot.png]]
;; ** Configuration
;; - You can select another pdf viewer. Modify =tikz-zathura= with your chosen viewer.
;; - You can modify the idle timer to update the pdf. Modify =tikz-resume-timer=.
;; ** How it works
;; - It copies the current TeX buffer into a temp file.
;; - [[https://ctan.org/pkg/mylatexformat][Pre-compile the preamble]].
;; - Pdftex the temp file.
;; - It uses Zathura to view the pdf.
;; - In idle time, copy the current buffer to the temp file and compile
;; it. Zathura automatically refreshes the view.
;; ** Alternatives
;; - QtikZ
;; ** Acknowledgement
;; Partially supported by PGC2018-098623-B-I00.
;;; Code:
(defvar tikz-resume-timer 1
"Timer for refreshing pdf.")
(defvar tikz-viewer "zathura"
"External pdf viewer.")
(defvar tikz-file-temp-tex-prefix "tikz"
"Temporal file to use.")
(defvar tikz-preamble-precompiled "myformat"
"Name of the precompiled preamble.")
(defvar tikz-buffer-compilation "*tikzing output*"
"Output of the pdflatex with current buffer.")
(defvar tikz-resume-timer-internal nil
"Timer for `tikz-run-pdflatex' to reschedule itself, or nil.")
(defvar tikz-preamble-template (concat (file-name-directory load-file-name) "templates/tikz-preamble-template.tex")
"Preamble template.")
(defun tikz-copy-current-buffer-to-temp-tex-file (buf filename preamble)
"Create a file FILENAME with the current buffer BUF and `%&PREAMBLE' string.
Moreover, enclose the buffers content in a latex-document environment.
%&preamble
content of BUF"
(save-excursion
(write-region (concat "%&" preamble "\n") nil filename nil 'quiet)
(write-region "\\begin{document}\n" nil filename t 'quiet)
(set-buffer buf)
(write-region nil nil filename t 'quiet)
(write-region "\\end{document}\n" nil filename t 'quiet)))
(defun tikz-run-pdflatex (input-buffer-tex
file-temp-tex
file-temp-preamble)
"Copy INPUT-BUFFER-TEX to FILE-TEMP-TEX with preamble FILE-TEMP-PREAMBLE.
Run pdflatex in FILE-TEMP-TEX."
(let* ((buffcompilation (get-buffer-create tikz-buffer-compilation))
(dir-temp-tex (file-name-directory file-temp-tex)))
;; (message "%s hola %s" (current-time-string) file-temp-tex)
;; Paso I.. Guardar el actual buffer en un fichero temporal
(tikz-copy-current-buffer-to-temp-tex-file input-buffer-tex
file-temp-tex
file-temp-preamble)
;; Paso II. Compilamos
(with-current-buffer buffcompilation
(erase-buffer))
;; Y lanzamos el proceso asíncrono
(start-process "pdfing" buffcompilation "pdflatex"
"-halt-on-error" "-file-line-error"
(concat "-output-directory=" dir-temp-tex) "-synctex=0" file-temp-tex)))
(defun tikz-run-current-buffer ()
"Pdflatex this tex buffer several times (TikZing).
1. Kill previous process.
2. Create a temporal file.
3. Create a pre-compiled preamble.
4. Launch visor of pdf
5. Launch pdflatex in idle timer."
(when (derived-mode-p 'latex-mode)
(message "TikZing. (Do not modify preamble!) Pre-compiling...")
(let* ((input-buffer-tex (current-buffer))
(buffcompilation (get-buffer-create tikz-buffer-compilation))
(file-temp-tex (concat (make-temp-file tikz-file-temp-tex-prefix) ".tex"))
(file-temp-pdf (concat (file-name-sans-extension file-temp-tex) ".pdf"))
(dir-temp-tex (file-name-directory file-temp-tex))
(file-temp-preamble (concat (file-name-sans-extension file-temp-tex) tikz-preamble-precompiled))
(secs 0))
(when tikz-resume-timer-internal
(tikz-kill)) ; Remove other/previous tikzing
;; Step I. Save the current buffer in a temp file
(set-buffer input-buffer-tex)
(write-region nil nil file-temp-tex nil 'quiet)
;; (message "fichero temp: %s" file-temp-tex)
;; Step II. Pre-compile the preamble in a synchronous way.
;; How to pre-compile preamble: See https://ctan.org/pkg/mylatexformat
;; This pre-compilation is done only one time.
(set-buffer buffcompilation)
(erase-buffer)
(cd (file-name-directory tikz-preamble-template))
(call-process "pdflatex" nil buffcompilation nil
"-ini" (concat "-output-directory=" dir-temp-tex)
(concat "-jobname=" file-temp-preamble )
"\"&pdflatex\""
"mylatexformat.ltx"
(concat "\"" tikz-preamble-template "\""))
(message "TikZing. (Do not modify preamble!) Pre-compiling...done")
;;
;; Activamos zathura, el visor externo de pdf
;; necesita un pdf.
;;
;; Step III. Create a pdf version of the file-temp-tex.
;; We need a pdf file to launch Zathura
(tikz-run-pdflatex input-buffer-tex
file-temp-tex
file-temp-preamble)
;;
;; Step IV. Open asynchronously the pdf with Zathura
;; But first we have to wait to pdftex finishes.
;; Zathura updates it automatically.
;; (message "pdf %s" file-temp-pdf)
;; Wait until the pdf exists.
(while (and (not (file-exists-p file-temp-pdf))
(< secs 20))
(message "TikZing waiting for the first compilation (%s seconds)..." (- 20 secs))
(sit-for 1)
(setq secs (+ 1 secs)))
(sit-for 1)
;; Otherwise, Zathura fails.
(start-process (concat "tikz" tikz-viewer) nil tikz-viewer file-temp-pdf)
(message "TikZing waiting for the first compilation...done")
;;
;; Step V. Pdflatex when in idle time
(setq tikz-resume-timer-internal
(run-with-idle-timer tikz-resume-timer-internal
t
'tikz-run-pdflatex
input-buffer-tex
file-temp-tex
file-temp-preamble)))))
(defun tikz-kill ()
"Kill the process of pdflatexing."
(interactive)
;; Remove run-idle-timer
(unless tikz-resume-timer-internal
(cancel-timer tikz-resume-timer-internal))
(cancel-function-timers 'tikz-run-pdflatex)
;; Kill process
(when (get-process (concat "tikz" tikz-viewer))
(delete-process (get-process (concat "tikz" tikz-viewer))))
(when (get-process tikz-buffer-compilation)
(delete-process (get-process tikz-buffer-compilation))))
;;;###autoload
(define-minor-mode tikz-mode
"Drawing interface for TikZ pictures.
Compile your (short) one page TeX file with TikZ pictures.
Do not modify your preamble. If you change it, turn off this mode
and turn on it again.
Similar to the program QtikZ."
;; The initial value.
nil
;; The indicator for the mode line.
" TikZ"
;; The minor mode bindings. '(([C-backspace] . hungry-electric-delete))
nil
(if tikz-mode
(progn
(setq tikz-resume-timer-internal tikz-resume-timer)
(tikz-run-current-buffer))
(tikz-kill))
:group 'tikz)
(provide 'tikz)
;;; tikz.el ends here