yatex

changeset 518:dfb71acdec98 dev

add yatexflt.el
author HIROSE Yuuji <yuuji@gentei.org>
date Tue, 09 Jan 2018 13:14:28 +0900
parents 668632d9392e
children a6a80e2b6f5a
files yatexflt.el
diffstat 1 files changed, 271 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/yatexflt.el	Tue Jan 09 13:14:28 2018 +0900
     1.3 @@ -0,0 +1,271 @@
     1.4 +;;; yatexflt.el --- YaTeX filter command utilizer -*- coding: sjis -*-
     1.5 +;;; 
     1.6 +;;; (c)1993-2018 by HIROSE Yuuji.[yuuji@yatex.org]
     1.7 +;;; Last modified Sun Jan  7 11:38:12 2018 on firestorm
     1.8 +;;; $Id$
     1.9 +
    1.10 +;;; Commentary:
    1.11 +;;;
    1.12 +;;;	This lisp enables passing inline text to some external filter
    1.13 +;;;	command to generate files such as graphic files.
    1.14 +;;; 
    1.15 +;;;	Typical situation is using blockdiag/dot(graphviz) command to
    1.16 +;;;	generate png/pdf file.
    1.17 +;;;
    1.18 +;;; Example:
    1.19 +;;;
    1.20 +;;;	[[LaTeX Source]]
    1.21 +;;;	%#BEGIN FILTER{foo.pdf}{dot -T %t -o o}
    1.22 +;;;	\if0
    1.23 +;;;	===
    1.24 +;;;	digraph {
    1.25 +;;;	  A -> B;
    1.26 +;;;	  B -> C;
    1.27 +;;;	}
    1.28 +;;;	===
    1.29 +;;;	\fi
    1.30 +;;;	%#END
    1.31 +;;;	\includegraphics{foo.pdf}
    1.32 +;;;
    1.33 +;;;	In this  case above, when  you type  `[prefix] t e'  between two
    1.34 +;;;	`===' lines, the  content in a region are fed  to dot command as
    1.35 +;;;	follows:
    1.36 +;;;	
    1.37 +;;;	    echo TEXT | dot -T pdf -o foo.pdf 
    1.38 +;;;
    1.39 +;;;	Then foo.pdf file will be generated and the image (as PNG) will
    1.40 +;;;	be displayed in the next window.
    1.41 +
    1.42 +;;; Code:
    1.43 +(defun YaTeX-filter-filter-set-conversion-flag ()
    1.44 +  (let ((ovl (get 'YaTeX-filter-filter-sentinel 'overlay)))
    1.45 +    (if ovl				;; When successful conversion met,
    1.46 +	(progn				;; (1)Set conversion complete flag
    1.47 +	  (add-hook			;; (2)Add hook of seim-automatic
    1.48 +	   'write-file-hooks		;;    update of convert to write-
    1.49 +	   'YaTeX-filter-update-all)	;;    file hook.
    1.50 +	  (overlay-put ovl 'converted t)))))
    1.51 +
    1.52 +(defun YaTeX-filter-filter-unset-conversion-flag
    1.53 +    (ovl after beg end &optional length) 
    1.54 +  (if after (overlay-put ovl 'converted nil)))
    1.55 +
    1.56 +
    1.57 +(defun YaTeX-filter-pngify-sentinel (proc msg)
    1.58 +  (save-excursion
    1.59 +    (let ((b (process-buffer proc)) (selw (selected-window))
    1.60 +	  img)
    1.61 +      (set-buffer b)
    1.62 +      (cond
    1.63 +       ((eq (process-status proc) 'run)
    1.64 +	(put-text-property (point-min) (point-max) 'invisible t))
    1.65 +       ((eq (process-status proc) 'exit)
    1.66 +	(set-buffer b)
    1.67 +	(YaTeX-popup-image
    1.68 +	 (YaTeX-buffer-substring
    1.69 +	  (get 'YaTeX-filter-pngify-sentinel 'start) (point-max))
    1.70 +	 b)
    1.71 +	(YaTeX-filter-filter-set-conversion-flag))
    1.72 +       (t
    1.73 +	(set-buffer b)
    1.74 +	(remove-text-properties (point-min) (point-max) '(invisible t))
    1.75 +	(insert "\nProcess aborted %s\n" msg))))))
    1.76 +
    1.77 +(defvar YaTeX-filter-pdf2png-stdout
    1.78 +  (cond
    1.79 +   ((YaTeX-executable-find "convert")	"convert -trim %s PNG:-")
    1.80 +   (t
    1.81 +    "gs -dNOPAUSE -sDEVICE=png256 -sOutputFile=- -dBATCH -q -r75 %s"))
    1.82 +  "Command line syntax to convert PDF file to PNG stream")
    1.83 +
    1.84 +(defun YaTeX-filter-modified-BEGEND-regions ()
    1.85 +  "Return the list of overlays which contains un-converted text."
    1.86 +  (save-excursion
    1.87 +    (save-restriction
    1.88 +      (widen)
    1.89 +      (let (r pl (list (overlays-in (point-min) (point-max))))
    1.90 +	(while list
    1.91 +	  (if (and (overlay-get (car list) 'filter-input)
    1.92 +		   (setq pl (plist-member (overlay-properties (car list))
    1.93 +					  'converted))
    1.94 +		   (not (plist-get pl 'converted)))
    1.95 +	      (setq r (cons (car list) r)))
    1.96 +	  (setq list (cdr list)))
    1.97 +	(nconc r)
    1.98 +	r))))
    1.99 +
   1.100 +(defun YaTeX-filter-update-all ()
   1.101 +  "Update all destination files from built-in source text."
   1.102 +  (interactive)
   1.103 +  (let ((timeout 4)
   1.104 +	ans ovl (update-list (YaTeX-filter-modified-BEGEND-regions)))
   1.105 +    (if update-list
   1.106 +	(save-excursion
   1.107 +	  (save-window-excursion
   1.108 +	    (catch 'abort
   1.109 +	      (while update-list
   1.110 +		(goto-char (overlay-start (setq ovl (car update-list))))
   1.111 +		(or (pos-visible-in-window-p)
   1.112 +		    (set-window-start nil (point)))
   1.113 +		(unwind-protect
   1.114 +		    (progn
   1.115 +		      (overlay-put ovl 'face 'YaTeX-on-the-fly-activated-face)
   1.116 +		      (message "Non-update source found: Update here: %s "
   1.117 +			       "Y)es N)o A)bort")
   1.118 +		      (setq ans (read-char))
   1.119 +		      (cond
   1.120 +		       ((memq ans '(?Y ?y))
   1.121 +			(YaTeX-filter-BEGEND)
   1.122 +			(while (and (> (setq timeout (1- timeout)))
   1.123 +				    (eq (process-status "Filter") 'run))
   1.124 +			  (message "Waiting for conversion process to finish")
   1.125 +			  (sit-for 1)))
   1.126 +		       ((memq ans '(?A ?a)) (throw 'abort t))
   1.127 +		       (t nil)))
   1.128 +		  (overlay-put ovl 'face nil))
   1.129 +		(setq update-list (cdr update-list)))))))
   1.130 +    ;; Write file hook should return nil
   1.131 +    nil))
   1.132 +
   1.133 +(defun YaTeX-filter-filter-sentinel (proc msg)
   1.134 +  (put 'YaTeX-filter-pngify-sentinel 'start nil)
   1.135 +  (let ((b (process-buffer proc))
   1.136 +	(imagefile (get 'YaTeX-filter-filter-sentinel 'outfile))
   1.137 +	ovl
   1.138 +	(selw (selected-window)))
   1.139 +    (save-excursion
   1.140 +      (cond
   1.141 +       ((eq (process-status proc) 'run))
   1.142 +       ((eq (process-status proc) 'exit)
   1.143 +	(set-buffer b)
   1.144 +	(remove-images (point-min) (point-max))
   1.145 +	(if (and (file-regular-p imagefile)
   1.146 +		 (file-readable-p imagefile))
   1.147 +	    (save-excursion
   1.148 +	      (setq buffer-read-only nil)
   1.149 +	      (cond
   1.150 +	       ((string-match "\\.\\(jpg\\|png\\)" imagefile)
   1.151 +		(erase-buffer)
   1.152 +		(YaTeX-popup-image imagefile b)
   1.153 +		(YaTeX-filter-filter-set-conversion-flag))
   1.154 +	       (t 			;Convert again to PNG file
   1.155 +		(goto-char (point-max))
   1.156 +		(insert "\nConvert Again to PNG file...\n")
   1.157 +		(put 'YaTeX-filter-pngify-sentinel 'start (point))
   1.158 +		(set-process-sentinel
   1.159 +		 (start-process
   1.160 +		  "Filter" b		;Safe to reuse
   1.161 +		  shell-file-name YaTeX-shell-command-option
   1.162 +		  (format YaTeX-filter-pdf2png-stdout imagefile))
   1.163 +		 'YaTeX-filter-pngify-sentinel)
   1.164 +		(set-buffer-multibyte nil)
   1.165 +		))
   1.166 +	      (select-window selw)))
   1.167 +	(YaTeX-preview-image-mode)
   1.168 +	)
   1.169 +       (t					;Other status might be an error
   1.170 +	(set-buffer b)
   1.171 +	(goto-char (point-max))
   1.172 +	(insert (format "%s\n" (process-status proc))))))))
   1.173 +
   1.174 +(defun YaTeX-filter-pass-to-filter (begend-info)
   1.175 +  "Pass current BEGIN FILTER environment to external command."
   1.176 +  (put 'YaTeX-filter-filter-sentinel 'outfile nil)
   1.177 +  ;; begend-info is from YaTeX-in-BEGEND-p: (BEG END ARGS)
   1.178 +  (let ((b (car begend-info)) (e (nth 1 begend-info))
   1.179 +	(args (nth 2 begend-info))
   1.180 +	(p (point)) openb closeb outfile cmdline point-if0 point-fi)
   1.181 +    (save-excursion
   1.182 +      (if (and begend-info
   1.183 +	       (string-match "FILTER" args) ;easy test
   1.184 +	       (goto-char (car begend-info))
   1.185 +	       (re-search-forward
   1.186 +		"FILTER\\s *{\\([^}]+\\)}" e t)
   1.187 +	       (setq outfile (YaTeX-match-string 1))
   1.188 +	       (goto-char (match-end 0))
   1.189 +	       (prog2			;Step into the second brace
   1.190 +		   (skip-chars-forward "\t ")
   1.191 +		   (looking-at "{")	;Check if 2nd brace surely exists
   1.192 +		 (skip-chars-forward "{")
   1.193 +		 (skip-chars-forward "\t"))
   1.194 +	       (setq openb (point))
   1.195 +	       (condition-case nil
   1.196 +		   (progn (up-list 1) t)
   1.197 +		 (error nil))
   1.198 +	       (setq closeb (1- (point))
   1.199 +		     cmdline (YaTeX-buffer-substring openb closeb))
   1.200 +	       (re-search-forward "^\\\\if0\\>" p t)
   1.201 +	       (setq point-if0 (point))
   1.202 +	       (re-search-forward "^\\\\fi\\>" e t)
   1.203 +	       (setq point-fi (match-beginning 0)))
   1.204 +	  (let*((case-fold-search t)
   1.205 +		(type (cond
   1.206 +		       ((string-match "\\.png$" outfile) "png")
   1.207 +		       ((string-match "\\.svg$" outfile) "svg")
   1.208 +		       (t				 "pdf")))
   1.209 +		(newcmdline (YaTeX-replace-formats
   1.210 +			     cmdline
   1.211 +			     (list (cons "t" type)
   1.212 +				   (cons "o" outfile))))
   1.213 +		(delim (progn (goto-char point-if0)
   1.214 +			      (forward-line 1)
   1.215 +			      (and (looking-at "\\(.\\)\\1\\1") ;Triple chars
   1.216 +				   (prog1
   1.217 +				       (YaTeX-match-string 0)
   1.218 +				     (forward-line 1)))))
   1.219 +		(text-start (point))
   1.220 +		(text-end (if (and delim
   1.221 +				   (re-search-forward
   1.222 +				    (concat "^" (regexp-quote delim))
   1.223 +				    point-fi t))
   1.224 +			      (match-beginning 0)
   1.225 +			    point-fi))
   1.226 +		(text (YaTeX-buffer-substring text-start text-end))
   1.227 +		;;
   1.228 +		;; Now it's time to start filter process
   1.229 +		;;
   1.230 +		(procbuf (YaTeX-system newcmdline "Filter" 'force))
   1.231 +		(proc (get-buffer-process procbuf))
   1.232 +		;(procbuf (get-buffer-create " *Filter*"))
   1.233 +		(ovl (progn
   1.234 +		       (remove-overlays text-start text-end)
   1.235 +		       (make-overlay text-start text-end)))
   1.236 +		(ovlmodhook	;hook function to reset conv-success flag
   1.237 +		 'YaTeX-filter-filter-unset-conversion-flag))
   1.238 +	    (if proc
   1.239 +		(progn
   1.240 +		  (overlay-put ovl 'filter-input outfile)
   1.241 +		  (overlay-put ovl 'converted nil)
   1.242 +		  (overlay-put ovl 'modification-hooks (list ovlmodhook))
   1.243 +		  (set-process-coding-system proc 'undecided 'utf-8)
   1.244 +		  (set-process-sentinel proc 'YaTeX-filter-filter-sentinel)
   1.245 +		  (YaTeX-showup-buffer procbuf)
   1.246 +		  (set-buffer procbuf)
   1.247 +		  (setq buffer-read-only nil)
   1.248 +		  (erase-buffer)
   1.249 +		  (insert (format "Starting process `%s'...\n" newcmdline))
   1.250 +		  (set-marker (process-mark proc) (point-max))
   1.251 +		  (process-send-string proc text)
   1.252 +		  (process-send-string proc "\n")
   1.253 +		  (process-send-eof proc) ;Notify stream chunk end
   1.254 +		  (process-send-eof proc) ;Notify real EOF
   1.255 +		  (put 'YaTeX-filter-filter-sentinel 'outfile outfile)
   1.256 +		  (put 'YaTeX-filter-filter-sentinel 'overlay ovl))))))))
   1.257 +
   1.258 +(defun YaTeX-insert-filter-special (filter list &optional region-p)
   1.259 +  (let ((f (YaTeX-read-string-or-skip "Output file: ")))
   1.260 +    (if region-p
   1.261 +	(if (< (point) (mark)) (exchange-point-and-mark)))
   1.262 +    (save-excursion (insert "===\n\\fi\n%#END\n"))
   1.263 +    (and region-p (exchange-point-and-mark))
   1.264 +    (insert (format "%%#BEGIN FILTER{%s}{%s}\n\\if0\n===\n"
   1.265 +		    f (or (car list) "")))
   1.266 +    (save-excursion (insert (or (car (cdr list)) "\n") "\n"))))
   1.267 +
   1.268 +(provide 'yatexflt)
   1.269 +
   1.270 +; Local variables:
   1.271 +; fill-prefix: ";;;	"
   1.272 +; paragraph-start: "^$\\|\\|;;;$"
   1.273 +; paragraph-separate: "^$\\|\\|;;;$"
   1.274 +; End: