Support plantuml as executable in PATH

The plantuml JAR is often packaged alongside a binary that calls the
JAR - both in OS X Homebrew and in Debian.  In particular, in OS X the
plantuml binary sets the environment so that it "just works" - hence
on OS X the wrapper is the recommended way of calling plantuml.

Sample wrapping binaries in packaged plantuml:
* [OS X homebrew](6c8c13b890/Formula/plantuml.rb (L14-L17))
* [debian](https://packages.debian.org/search?searchon=contents&keywords=plantuml&mode=exactfilename&suite=testing&arch=any)

Also convert shell-command to call-process.

References:
* https://www.gnu.org/software/emacs/manual/html_mono/elisp.html
* http://stackoverflow.com/questions/23299314/finding-the-exit-code-of-a-shell-command-in-elisp/23299809#comment35678383_23299809
* http://emacs.stackexchange.com/questions/7712/bind-multiple-values-directly-from-list-without-binding-the-list-itself
This commit is contained in:
Luca Favatella 2016-06-05 18:59:59 +01:00
parent b31063125b
commit e00d256889
1 changed files with 86 additions and 57 deletions

View File

@ -106,47 +106,69 @@
(insert msg) (insert msg)
(insert "\n")))))) (insert "\n"))))))
(defun puml-plantuml-program-and-args ()
"Determines program and args for calling plantuml.
Returns a list of two elements:
- program name
- list of arguments
If unable to determine how to call plantuml, does not return."
(let ((puml-plantuml-command-path (executable-find "plantuml")))
(cond
((file-exists-p puml-plantuml-jar-path)
(list
"java" ;; program
(list "-jar" (shell-quote-argument puml-plantuml-jar-path)))) ;; args
(puml-plantuml-command-path
(list
puml-plantuml-command-path ;; program
())) ;; args
(t
(error "Could not find file plantuml.jar at %s nor command
plantuml in PATH" puml-plantuml-jar-path)))))
(defun puml-init () (defun puml-init ()
"Initialize the keywords or builtins from the cmdline language output." "Initialize the keywords or builtins from the cmdline language output."
(unless (file-exists-p puml-plantuml-jar-path) (let ((plantuml-program-and-args (puml-plantuml-program-and-args)))
(error "Could not find plantuml.jar at %s" puml-plantuml-jar-path)) (let ((plantuml-program (car plantuml-program-and-args))
(with-temp-buffer (plantuml-args (cadr plantuml-program-and-args)))
(shell-command (concat "java -jar " (with-temp-buffer
(shell-quote-argument puml-plantuml-jar-path) (apply 'call-process plantuml-program nil t nil
" -charset UTF-8 -language") (current-buffer)) (append plantuml-args (list
(goto-char (point-min)) "-charset" "UTF-8"
(let ((found (search-forward ";" nil t)) "-language")))
(word "") (goto-char (point-min))
(count 0) (let ((found (search-forward ";" nil t))
(pos 0)) (word "")
(while found (count 0)
(forward-char) (pos 0))
(setq word (current-word)) (while found
(if (string= word "EOF") (setq found nil) (forward-char)
;; else (setq word (current-word))
(forward-line) (if (string= word "EOF") (setq found nil)
(setq count (string-to-number (current-word))) ;; else
(beginning-of-line 2) (forward-line)
(setq pos (point)) (setq count (string-to-number (current-word)))
(forward-line count) (beginning-of-line 2)
(cond ((string= word "type") (setq pos (point))
(setq puml-plantuml-types (forward-line count)
(split-string (cond ((string= word "type")
(buffer-substring-no-properties pos (point))))) (setq puml-plantuml-types
((string= word "keyword") (split-string
(setq puml-plantuml-keywords (buffer-substring-no-properties pos (point)))))
(split-string ((string= word "keyword")
(buffer-substring-no-properties pos (point))))) (setq puml-plantuml-keywords
((string= word "preprocessor") (split-string
(setq puml-plantuml-preprocessors (buffer-substring-no-properties pos (point)))))
(split-string ((string= word "preprocessor")
(buffer-substring-no-properties pos (point))))) (setq puml-plantuml-preprocessors
(t (setq puml-plantuml-builtins (split-string
(append (buffer-substring-no-properties pos (point)))))
puml-plantuml-builtins (t (setq puml-plantuml-builtins
(split-string (append
(buffer-substring-no-properties pos (point))))))) puml-plantuml-builtins
(setq found (search-forward ";" nil nil))))))) (split-string
(buffer-substring-no-properties pos (point)))))))
(setq found (search-forward ";" nil nil)))))))))
(defconst puml-preview-buffer "*PUML Preview*") (defconst puml-preview-buffer "*PUML Preview*")
@ -207,24 +229,31 @@ default output type for new buffers."
(coding-system-for-read (and imagep 'binary)) (coding-system-for-read (and imagep 'binary))
(coding-system-for-write (and imagep 'binary))) (coding-system-for-write (and imagep 'binary)))
(let ((ps (start-process "PUML" buf (let ((plantuml-program-and-args (puml-plantuml-program-and-args)))
"java" "-jar" (shell-quote-argument puml-plantuml-jar-path) (let ((plantuml-program (car plantuml-program-and-args))
(puml-output-type-opt) "-p"))) (plantuml-args (cadr plantuml-program-and-args)))
(process-send-region ps (point-min) (point-max))
(process-send-eof ps) (let ((ps (apply 'start-process "PUML" buf
(set-process-sentinel ps plantuml-program
(lambda (ps event) (append plantuml-args (list
(unless (equal event "finished\n") (puml-output-type-opt)
(error "PUML Preview failed: %s" event)) "-p")))))
(cond
((= prefix 16) (process-send-region ps (point-min) (point-max))
(switch-to-buffer-other-frame puml-preview-buffer)) (process-send-eof ps)
((= prefix 4) (set-process-sentinel ps
(switch-to-buffer-other-window puml-preview-buffer)) (lambda (ps event)
(t (switch-to-buffer puml-preview-buffer))) (unless (equal event "finished\n")
(when imagep (error "PUML Preview failed: %s" event))
(image-mode) (cond
(set-buffer-multibyte t))))))) ((= prefix 16)
(switch-to-buffer-other-frame puml-preview-buffer))
((= prefix 4)
(switch-to-buffer-other-window puml-preview-buffer))
(t (switch-to-buffer puml-preview-buffer)))
(when imagep
(image-mode)
(set-buffer-multibyte t)))))))))
(unless puml-plantuml-kwdList (unless puml-plantuml-kwdList
(puml-init) (puml-init)