yatex

annotate yatexflt.el @ 518:dfb71acdec98

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