From e00d25688959bafba682f923dfd1ec5147840f01 Mon Sep 17 00:00:00 2001 From: Luca Favatella Date: Sun, 5 Jun 2016 18:59:59 +0100 Subject: [PATCH] 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](https://github.com/Homebrew/homebrew-core/blob/6c8c13b890dd3271d4fa05a08f5fc67ebf6055df/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 --- puml-mode.el | 143 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 57 deletions(-) diff --git a/puml-mode.el b/puml-mode.el index 1aa2341..5e94c88 100644 --- a/puml-mode.el +++ b/puml-mode.el @@ -106,47 +106,69 @@ (insert msg) (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 () "Initialize the keywords or builtins from the cmdline language output." - (unless (file-exists-p puml-plantuml-jar-path) - (error "Could not find plantuml.jar at %s" puml-plantuml-jar-path)) - (with-temp-buffer - (shell-command (concat "java -jar " - (shell-quote-argument puml-plantuml-jar-path) - " -charset UTF-8 -language") (current-buffer)) - (goto-char (point-min)) - (let ((found (search-forward ";" nil t)) - (word "") - (count 0) - (pos 0)) - (while found - (forward-char) - (setq word (current-word)) - (if (string= word "EOF") (setq found nil) - ;; else - (forward-line) - (setq count (string-to-number (current-word))) - (beginning-of-line 2) - (setq pos (point)) - (forward-line count) - (cond ((string= word "type") - (setq puml-plantuml-types - (split-string - (buffer-substring-no-properties pos (point))))) - ((string= word "keyword") - (setq puml-plantuml-keywords - (split-string - (buffer-substring-no-properties pos (point))))) - ((string= word "preprocessor") - (setq puml-plantuml-preprocessors - (split-string - (buffer-substring-no-properties pos (point))))) - (t (setq puml-plantuml-builtins - (append - puml-plantuml-builtins - (split-string - (buffer-substring-no-properties pos (point))))))) - (setq found (search-forward ";" nil nil))))))) + (let ((plantuml-program-and-args (puml-plantuml-program-and-args))) + (let ((plantuml-program (car plantuml-program-and-args)) + (plantuml-args (cadr plantuml-program-and-args))) + (with-temp-buffer + (apply 'call-process plantuml-program nil t nil + (append plantuml-args (list + "-charset" "UTF-8" + "-language"))) + (goto-char (point-min)) + (let ((found (search-forward ";" nil t)) + (word "") + (count 0) + (pos 0)) + (while found + (forward-char) + (setq word (current-word)) + (if (string= word "EOF") (setq found nil) + ;; else + (forward-line) + (setq count (string-to-number (current-word))) + (beginning-of-line 2) + (setq pos (point)) + (forward-line count) + (cond ((string= word "type") + (setq puml-plantuml-types + (split-string + (buffer-substring-no-properties pos (point))))) + ((string= word "keyword") + (setq puml-plantuml-keywords + (split-string + (buffer-substring-no-properties pos (point))))) + ((string= word "preprocessor") + (setq puml-plantuml-preprocessors + (split-string + (buffer-substring-no-properties pos (point))))) + (t (setq puml-plantuml-builtins + (append + puml-plantuml-builtins + (split-string + (buffer-substring-no-properties pos (point))))))) + (setq found (search-forward ";" nil nil))))))))) (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-write (and imagep 'binary))) - (let ((ps (start-process "PUML" buf - "java" "-jar" (shell-quote-argument puml-plantuml-jar-path) - (puml-output-type-opt) "-p"))) - (process-send-region ps (point-min) (point-max)) - (process-send-eof ps) - (set-process-sentinel ps - (lambda (ps event) - (unless (equal event "finished\n") - (error "PUML Preview failed: %s" event)) - (cond - ((= 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))))))) + (let ((plantuml-program-and-args (puml-plantuml-program-and-args))) + (let ((plantuml-program (car plantuml-program-and-args)) + (plantuml-args (cadr plantuml-program-and-args))) + + (let ((ps (apply 'start-process "PUML" buf + plantuml-program + (append plantuml-args (list + (puml-output-type-opt) + "-p"))))) + + (process-send-region ps (point-min) (point-max)) + (process-send-eof ps) + (set-process-sentinel ps + (lambda (ps event) + (unless (equal event "finished\n") + (error "PUML Preview failed: %s" event)) + (cond + ((= 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 (puml-init)