yatex

view yatexflt.el @ 519:a6a80e2b6f5a

Nil for YaTeX-on-the-fly-preview-interval should work here.
author HIROSE Yuuji <yuuji@gentei.org>
date Tue, 09 Jan 2018 13:28:03 +0900
parents
children cef987df070f
line source
1 ;;; yatexflt.el --- YaTeX filter command utilizer -*- coding: sjis -*-
2 ;;;
3 ;;; (c)1993-2018 by HIROSE Yuuji.[yuuji@yatex.org]
4 ;;; Last modified Sun Jan 7 11:38:12 2018 on firestorm
5 ;;; $Id$
7 ;;; Commentary:
8 ;;;
9 ;;; This lisp enables passing inline text to some external filter
10 ;;; command to generate files such as graphic files.
11 ;;;
12 ;;; Typical situation is using blockdiag/dot(graphviz) command to
13 ;;; generate png/pdf file.
14 ;;;
15 ;;; Example:
16 ;;;
17 ;;; [[LaTeX Source]]
18 ;;; %#BEGIN FILTER{foo.pdf}{dot -T %t -o o}
19 ;;; \if0
20 ;;; ===
21 ;;; digraph {
22 ;;; A -> B;
23 ;;; B -> C;
24 ;;; }
25 ;;; ===
26 ;;; \fi
27 ;;; %#END
28 ;;; \includegraphics{foo.pdf}
29 ;;;
30 ;;; In this case above, when you type `[prefix] t e' between two
31 ;;; `===' lines, the content in a region are fed to dot command as
32 ;;; follows:
33 ;;;
34 ;;; echo TEXT | dot -T pdf -o foo.pdf
35 ;;;
36 ;;; Then foo.pdf file will be generated and the image (as PNG) will
37 ;;; be displayed in the next window.
39 ;;; Code:
40 (defun YaTeX-filter-filter-set-conversion-flag ()
41 (let ((ovl (get 'YaTeX-filter-filter-sentinel 'overlay)))
42 (if ovl ;; When successful conversion met,
43 (progn ;; (1)Set conversion complete flag
44 (add-hook ;; (2)Add hook of seim-automatic
45 'write-file-hooks ;; update of convert to write-
46 'YaTeX-filter-update-all) ;; file hook.
47 (overlay-put ovl 'converted t)))))
49 (defun YaTeX-filter-filter-unset-conversion-flag
50 (ovl after beg end &optional length)
51 (if after (overlay-put ovl 'converted nil)))
54 (defun YaTeX-filter-pngify-sentinel (proc msg)
55 (save-excursion
56 (let ((b (process-buffer proc)) (selw (selected-window))
57 img)
58 (set-buffer b)
59 (cond
60 ((eq (process-status proc) 'run)
61 (put-text-property (point-min) (point-max) 'invisible t))
62 ((eq (process-status proc) 'exit)
63 (set-buffer b)
64 (YaTeX-popup-image
65 (YaTeX-buffer-substring
66 (get 'YaTeX-filter-pngify-sentinel 'start) (point-max))
67 b)
68 (YaTeX-filter-filter-set-conversion-flag))
69 (t
70 (set-buffer b)
71 (remove-text-properties (point-min) (point-max) '(invisible t))
72 (insert "\nProcess aborted %s\n" msg))))))
74 (defvar YaTeX-filter-pdf2png-stdout
75 (cond
76 ((YaTeX-executable-find "convert") "convert -trim %s PNG:-")
77 (t
78 "gs -dNOPAUSE -sDEVICE=png256 -sOutputFile=- -dBATCH -q -r75 %s"))
79 "Command line syntax to convert PDF file to PNG stream")
81 (defun YaTeX-filter-modified-BEGEND-regions ()
82 "Return the list of overlays which contains un-converted text."
83 (save-excursion
84 (save-restriction
85 (widen)
86 (let (r pl (list (overlays-in (point-min) (point-max))))
87 (while list
88 (if (and (overlay-get (car list) 'filter-input)
89 (setq pl (plist-member (overlay-properties (car list))
90 'converted))
91 (not (plist-get pl 'converted)))
92 (setq r (cons (car list) r)))
93 (setq list (cdr list)))
94 (nconc r)
95 r))))
97 (defun YaTeX-filter-update-all ()
98 "Update all destination files from built-in source text."
99 (interactive)
100 (let ((timeout 4)
101 ans ovl (update-list (YaTeX-filter-modified-BEGEND-regions)))
102 (if update-list
103 (save-excursion
104 (save-window-excursion
105 (catch 'abort
106 (while update-list
107 (goto-char (overlay-start (setq ovl (car update-list))))
108 (or (pos-visible-in-window-p)
109 (set-window-start nil (point)))
110 (unwind-protect
111 (progn
112 (overlay-put ovl 'face 'YaTeX-on-the-fly-activated-face)
113 (message "Non-update source found: Update here: %s "
114 "Y)es N)o A)bort")
115 (setq ans (read-char))
116 (cond
117 ((memq ans '(?Y ?y))
118 (YaTeX-filter-BEGEND)
119 (while (and (> (setq timeout (1- timeout)))
120 (eq (process-status "Filter") 'run))
121 (message "Waiting for conversion process to finish")
122 (sit-for 1)))
123 ((memq ans '(?A ?a)) (throw 'abort t))
124 (t nil)))
125 (overlay-put ovl 'face nil))
126 (setq update-list (cdr update-list)))))))
127 ;; Write file hook should return nil
128 nil))
130 (defun YaTeX-filter-filter-sentinel (proc msg)
131 (put 'YaTeX-filter-pngify-sentinel 'start nil)
132 (let ((b (process-buffer proc))
133 (imagefile (get 'YaTeX-filter-filter-sentinel 'outfile))
134 ovl
135 (selw (selected-window)))
136 (save-excursion
137 (cond
138 ((eq (process-status proc) 'run))
139 ((eq (process-status proc) 'exit)
140 (set-buffer b)
141 (remove-images (point-min) (point-max))
142 (if (and (file-regular-p imagefile)
143 (file-readable-p imagefile))
144 (save-excursion
145 (setq buffer-read-only nil)
146 (cond
147 ((string-match "\\.\\(jpg\\|png\\)" imagefile)
148 (erase-buffer)
149 (YaTeX-popup-image imagefile b)
150 (YaTeX-filter-filter-set-conversion-flag))
151 (t ;Convert again to PNG file
152 (goto-char (point-max))
153 (insert "\nConvert Again to PNG file...\n")
154 (put 'YaTeX-filter-pngify-sentinel 'start (point))
155 (set-process-sentinel
156 (start-process
157 "Filter" b ;Safe to reuse
158 shell-file-name YaTeX-shell-command-option
159 (format YaTeX-filter-pdf2png-stdout imagefile))
160 'YaTeX-filter-pngify-sentinel)
161 (set-buffer-multibyte nil)
162 ))
163 (select-window selw)))
164 (YaTeX-preview-image-mode)
165 )
166 (t ;Other status might be an error
167 (set-buffer b)
168 (goto-char (point-max))
169 (insert (format "%s\n" (process-status proc))))))))
171 (defun YaTeX-filter-pass-to-filter (begend-info)
172 "Pass current BEGIN FILTER environment to external command."
173 (put 'YaTeX-filter-filter-sentinel 'outfile nil)
174 ;; begend-info is from YaTeX-in-BEGEND-p: (BEG END ARGS)
175 (let ((b (car begend-info)) (e (nth 1 begend-info))
176 (args (nth 2 begend-info))
177 (p (point)) openb closeb outfile cmdline point-if0 point-fi)
178 (save-excursion
179 (if (and begend-info
180 (string-match "FILTER" args) ;easy test
181 (goto-char (car begend-info))
182 (re-search-forward
183 "FILTER\\s *{\\([^}]+\\)}" e t)
184 (setq outfile (YaTeX-match-string 1))
185 (goto-char (match-end 0))
186 (prog2 ;Step into the second brace
187 (skip-chars-forward "\t ")
188 (looking-at "{") ;Check if 2nd brace surely exists
189 (skip-chars-forward "{")
190 (skip-chars-forward "\t"))
191 (setq openb (point))
192 (condition-case nil
193 (progn (up-list 1) t)
194 (error nil))
195 (setq closeb (1- (point))
196 cmdline (YaTeX-buffer-substring openb closeb))
197 (re-search-forward "^\\\\if0\\>" p t)
198 (setq point-if0 (point))
199 (re-search-forward "^\\\\fi\\>" e t)
200 (setq point-fi (match-beginning 0)))
201 (let*((case-fold-search t)
202 (type (cond
203 ((string-match "\\.png$" outfile) "png")
204 ((string-match "\\.svg$" outfile) "svg")
205 (t "pdf")))
206 (newcmdline (YaTeX-replace-formats
207 cmdline
208 (list (cons "t" type)
209 (cons "o" outfile))))
210 (delim (progn (goto-char point-if0)
211 (forward-line 1)
212 (and (looking-at "\\(.\\)\\1\\1") ;Triple chars
213 (prog1
214 (YaTeX-match-string 0)
215 (forward-line 1)))))
216 (text-start (point))
217 (text-end (if (and delim
218 (re-search-forward
219 (concat "^" (regexp-quote delim))
220 point-fi t))
221 (match-beginning 0)
222 point-fi))
223 (text (YaTeX-buffer-substring text-start text-end))
224 ;;
225 ;; Now it's time to start filter process
226 ;;
227 (procbuf (YaTeX-system newcmdline "Filter" 'force))
228 (proc (get-buffer-process procbuf))
229 ;(procbuf (get-buffer-create " *Filter*"))
230 (ovl (progn
231 (remove-overlays text-start text-end)
232 (make-overlay text-start text-end)))
233 (ovlmodhook ;hook function to reset conv-success flag
234 'YaTeX-filter-filter-unset-conversion-flag))
235 (if proc
236 (progn
237 (overlay-put ovl 'filter-input outfile)
238 (overlay-put ovl 'converted nil)
239 (overlay-put ovl 'modification-hooks (list ovlmodhook))
240 (set-process-coding-system proc 'undecided 'utf-8)
241 (set-process-sentinel proc 'YaTeX-filter-filter-sentinel)
242 (YaTeX-showup-buffer procbuf)
243 (set-buffer procbuf)
244 (setq buffer-read-only nil)
245 (erase-buffer)
246 (insert (format "Starting process `%s'...\n" newcmdline))
247 (set-marker (process-mark proc) (point-max))
248 (process-send-string proc text)
249 (process-send-string proc "\n")
250 (process-send-eof proc) ;Notify stream chunk end
251 (process-send-eof proc) ;Notify real EOF
252 (put 'YaTeX-filter-filter-sentinel 'outfile outfile)
253 (put 'YaTeX-filter-filter-sentinel 'overlay ovl))))))))
255 (defun YaTeX-insert-filter-special (filter list &optional region-p)
256 (let ((f (YaTeX-read-string-or-skip "Output file: ")))
257 (if region-p
258 (if (< (point) (mark)) (exchange-point-and-mark)))
259 (save-excursion (insert "===\n\\fi\n%#END\n"))
260 (and region-p (exchange-point-and-mark))
261 (insert (format "%%#BEGIN FILTER{%s}{%s}\n\\if0\n===\n"
262 f (or (car list) "")))
263 (save-excursion (insert (or (car (cdr list)) "\n") "\n"))))
265 (provide 'yatexflt)
267 ; Local variables:
268 ; fill-prefix: ";;; "
269 ; paragraph-start: "^$\\| \\|;;;$"
270 ; paragraph-separate: "^$\\| \\|;;;$"
271 ; End: