diff options
author | Ian Martins <ianxm@jhu.edu> | 2020-10-25 08:08:39 -0400 |
---|---|---|
committer | Ian Martins <ianxm@jhu.edu> | 2020-10-25 15:24:08 -0400 |
commit | 5a41c62c2671ebfe3e5ea936442819eb66cdb0f9 (patch) | |
tree | f08242bdc3c97f7f35e06899afc155901d3e5ed4 | |
parent | 5b6d774ba10e1c5ee7ae68272ecd19f7784bc3d2 (diff) | |
download | org-mode-5a41c62c2671ebfe3e5ea936442819eb66cdb0f9.tar.gz |
ob-java.el: Use customizable commands, avoid incompatability
* lisp/ob-java.el: Use customizable variables for java compiler and
runtime commands. Move variable declarations to fix byte-compile
warnings. Change Author. Change tabs to spaces.
A recent patch replaced `defcustom' with `defvar' for variables that
point to the java compiler and runtime commands, which would break
functionality for anyone who had customized the variable. This
reverts that change.
ob-java is using features not available on older versions of emacs
which org supports. This replaces them with alternatives.
-rw-r--r-- | lisp/ob-java.el | 176 | ||||
-rw-r--r-- | testing/lisp/test-ob-java.el | 6 |
2 files changed, 99 insertions, 83 deletions
diff --git a/lisp/ob-java.el b/lisp/ob-java.el index eaeb788..05231be 100644 --- a/lisp/ob-java.el +++ b/lisp/ob-java.el @@ -2,7 +2,9 @@ ;; Copyright (C) 2011-2020 Free Software Foundation, Inc. -;; Author: Ian Martins <ianxm@jhu.edu> +;; Authors: Eric Schulte +;; Dan Davison +;; Maintainer: Ian Martins <ianxm@jhu.edu> ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org @@ -31,32 +33,98 @@ (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("java" . "java")) +(defvar org-babel-temporary-directory) ; from ob-core + (defvar org-babel-default-header-args:java '() "Default header args for java source blocks.") (defconst org-babel-header-args:java '((imports . :any)) "Java-specific header arguments.") -(defvar org-babel-java-compiler-command "javac" - "Name of the command to execute the java compiler.") +(defcustom org-babel-java-command "java" + "Name of the java command. +May be either a command in the path, like java or an absolute +path name, like /usr/local/bin/java. Parameters may be used, +like java -verbose." + :group 'org-babel + :package-version '(Org . "9.5") + :type 'string) -(defvar org-babel-java-runtime-command "java" - "Name of the command to run the java runtime.") +(defcustom org-babel-java-compiler "javac" + "Name of the java compiler. +May be either a command in the path, like javac or an absolute +path name, like /usr/local/bin/javac. Parameters may be used, +like javac -verbose." + :group 'org-babel + :package-version '(Org . "9.5") + :type 'string) (defcustom org-babel-java-hline-to "null" "Replace hlines in incoming tables with this when translating to java." :group 'org-babel - :version "25.2" - :package-version '(Org . "9.3") + :package-version '(Org . "9.5") :type 'string) (defcustom org-babel-java-null-to 'hline "Replace `null' in java tables with this before returning." :group 'org-babel - :version "25.2" - :package-version '(Org . "9.3") + :package-version '(Org . "9.5") :type 'symbol) +(defconst org-babel-java--package-re "^[[:space:]]*package[[:space:]]+\\\([[:alnum:]_\.]+\\\);$" + "Regexp for the package statement.") +(defconst org-babel-java--imports-re "^[[:space:]]*import[[:space:]]+\\\([[:alnum:]_\.]+\\\);$" + "Regexp for import statements.") +(defconst org-babel-java--class-re "^[[:space:]]*\\\(?:public[[:space:]]+\\\)?class[[:space:]]+\\\([[:alnum:]_]+\\\)[[:space:]]*\n?[[:space:]]*{" + "Regexp for the class declaration.") +(defconst org-babel-java--main-re "public static void main(String\\\(?:\\[]\\\)?[[:space:]]+[^ ]+\\\(?:\\[]\\\)?).*\n?[[:space:]]*{" + "Regexp for the main method declaration.") +(defconst org-babel-java--any-method-re "public .*(.*).*\n?[[:space:]]*{" + "Regexp for any method.") +(defconst org-babel-java--result-wrapper "\n public static String __toString(Object val) { + if (val instanceof String) { + return \"\\\"\" + val + \"\\\"\"; + } else if (val == null) { + return \"null\"; + } else if (val.getClass().isArray()) { + StringBuffer sb = new StringBuffer(); + Object[] vals = (Object[])val; + sb.append(\"[\"); + for (int ii=0; ii<vals.length; ii++) { + sb.append(__toString(vals[ii])); + if (ii<vals.length-1) + sb.append(\",\"); + } + sb.append(\"]\"); + return sb.toString(); + } else if (val instanceof List) { + StringBuffer sb = new StringBuffer(); + List vals = (List)val; + sb.append(\"[\"); + for (int ii=0; ii<vals.size(); ii++) { + sb.append(__toString(vals.get(ii))); + if (ii<vals.size()-1) + sb.append(\",\"); + } + sb.append(\"]\"); + return sb.toString(); + } else { + return String.valueOf(val); + } + } + + public static void main(String[] args) throws IOException { + BufferedWriter output = new BufferedWriter(new FileWriter(\"%s\")); + output.write(__toString(_main(args))); + output.close(); + }" + "Code to inject into a class so that we can capture the value it returns. +This implementation was inspired by ob-python, although not as +elegant. This modified the source block to write out the value +it wants to return to a temporary file so that ob-java can read +it back. The name of the temporary file to write must be +replaced in this string.") + (defun org-babel-execute:java (body params) "Execute a java source block with BODY code and PARAMS params." (let* (;; if true, run from babel temp directory @@ -67,7 +135,7 @@ ;; just the class name (classname (car (last (split-string fullclassname "\\.")))) ;; just the package name - (packagename (if (seq-contains fullclassname ?.) + (packagename (if (string-match-p "\\." fullclassname) (file-name-base fullclassname))) ;; the base dir that contains the top level package dir (basedir (file-name-as-directory (if run-from-temp @@ -80,19 +148,19 @@ basedir)) ;; the filename of the source file (src-file (concat packagedir classname ".java")) - ;; compiler flags - (cmpflag (or (cdr (assq :cmpflag params)) "")) - ;; runtime flags + ;; compiler flags + (cmpflag (or (cdr (assq :cmpflag params)) "")) + ;; runtime flags (cmdline (or (cdr (assq :cmdline params)) "")) ;; command line args - (cmdargs (or (cdr (assq :cmdargs params)) "")) + (cmdargs (or (cdr (assq :cmdargs params)) "")) ;; the command to compile and run - (cmd (concat org-babel-java-compiler-command " " cmpflag " " + (cmd (concat org-babel-java-compiler " " cmpflag " " (org-babel-process-file-name src-file 'noquote) - " && " org-babel-java-runtime-command + " && " org-babel-java-command " -cp " (org-babel-process-file-name basedir 'noquote) - " " cmdline " " (if run-from-temp classname fullclassname) - " " cmdargs)) + " " cmdline " " (if run-from-temp classname fullclassname) + " " cmdargs)) ;; header args for result processing (result-type (cdr (assq :result-type params))) (result-params (cdr (assq :result-params params))) @@ -107,7 +175,7 @@ ;; write the source file (setq full-body (org-babel-java--expand-for-evaluation - full-body run-from-temp result-type result-file)) + full-body run-from-temp result-type result-file)) (with-temp-file src-file (insert full-body)) ;; compile, run, process result @@ -134,60 +202,6 @@ return class name. If that isn't found either, default to Main." (and package (concat package ".Main")) "Main"))) -(defconst org-babel-java--package-re "^[[:space:]]*package[[:space:]]+\\\([[:alnum:]_\.]+\\\);$" - "Regexp for the package statement.") -(defconst org-babel-java--imports-re "^[[:space:]]*import[[:space:]]+\\\([[:alnum:]_\.]+\\\);$" - "Regexp for import statements.") -(defconst org-babel-java--class-re "^[[:space:]]*\\\(?:public[[:space:]]+\\\)?class[[:space:]]+\\\([[:alnum:]_]+\\\)[[:space:]]*\n?[[:space:]]*{" - "Regexp for the class declaration.") -(defconst org-babel-java--main-re "public static void main(String\\\(?:\\[]\\\)?[[:space:]]+[^ ]+\\\(?:\\[]\\\)?).*\n?[[:space:]]*{" - "Regexp for the main method declaration.") -(defconst org-babel-java--any-method-re "public .*(.*).*\n?[[:space:]]*{" - "Regexp for any method.") -(defconst org-babel-java--result-wrapper "\n public static String __toString(Object val) { - if (val instanceof String) { - return \"\\\"\" + val + \"\\\"\"; - } else if (val == null) { - return \"null\"; - } else if (val.getClass().isArray()) { - StringBuffer sb = new StringBuffer(); - Object[] vals = (Object[])val; - sb.append(\"[\"); - for (int ii=0; ii<vals.length; ii++) { - sb.append(__toString(vals[ii])); - if (ii<vals.length-1) - sb.append(\",\"); - } - sb.append(\"]\"); - return sb.toString(); - } else if (val instanceof List) { - StringBuffer sb = new StringBuffer(); - List vals = (List)val; - sb.append(\"[\"); - for (int ii=0; ii<vals.size(); ii++) { - sb.append(__toString(vals.get(ii))); - if (ii<vals.size()-1) - sb.append(\",\"); - } - sb.append(\"]\"); - return sb.toString(); - } else { - return String.valueOf(val); - } - } - - public static void main(String[] args) throws IOException { - BufferedWriter output = new BufferedWriter(new FileWriter(\"%s\")); - output.write(__toString(_main(args))); - output.close(); - }" - "Code to inject into a class so that we can capture the value it returns. -This implementation was inspired by ob-python, although not as -elegant. This modified the source block to write out the value -it wants to return to a temporary file so that ob-java can read -it back. The name of the temporary file to write must be -replaced in this string.") - (defun org-babel-java--expand-for-evaluation (body suppress-package-p result-type result-file) "Expand source block for evaluation. In order to return a value we have to add a __toString method. @@ -209,7 +223,7 @@ RESULT-FILE is the temp file to write the result." ;; suppress package statement (goto-char (point-min)) (when (and suppress-package-p - (re-search-forward org-babel-java--package-re nil t)) + (re-search-forward org-babel-java--package-re nil t)) (replace-match "")) ;; add a dummy main method if needed @@ -225,7 +239,7 @@ RESULT-FILE is the temp file to write the result." (goto-char (point-min)) (org-babel-java--move-past org-babel-java--class-re) (insert (format org-babel-java--result-wrapper - (org-babel-process-file-name result-file 'noquote))) + (org-babel-process-file-name result-file 'noquote))) (search-forward "public static void main(") ; rename existing main (replace-match "public static Object _main(")) @@ -263,7 +277,7 @@ is simplest to expand the code block from the inside out." (let* ((fullclassname (or (cdr (assq :classname params)) ; class and package (org-babel-java-find-classname body))) (classname (car (last (split-string fullclassname "\\.")))) ; just class name - (packagename (if (seq-contains fullclassname ?.) ; just package name + (packagename (if (string-match-p "\\." fullclassname) ; just package name (file-name-base fullclassname))) (var-lines (org-babel-variable-assignments:java params)) (imports-val (assq :imports params)) @@ -405,17 +419,17 @@ Emacs-lisp table, otherwise return the results as a string." "Evaluate using an external java process. CMD the command to execute. -If RESULT-TYPE equals 'output then return standard output as a -string. If RESULT-TYPE equals 'value then return the value +If RESULT-TYPE equals `output' then return standard output as a +string. If RESULT-TYPE equals `value' then return the value returned by the source block, as elisp. RESULT-PARAMS input params used to format the reponse. RESULT-FILE filename of the tempfile to store the returned value in -for 'value RESULT-TYPE. Not used for 'output RESULT-TYPE." +for `value' RESULT-TYPE. Not used for `output' RESULT-TYPE." (let ((raw (pcase result-type - ('output (org-babel-eval cmd "")) - ('value (org-babel-eval cmd "") + (`output (org-babel-eval cmd "")) + (`value (org-babel-eval cmd "") (org-babel-eval-read-file result-file))))) (org-babel-result-cond result-params raw (org-babel-java-table-or-string raw)))) diff --git a/testing/lisp/test-ob-java.el b/testing/lisp/test-ob-java.el index cb03cad..b8f3425 100644 --- a/testing/lisp/test-ob-java.el +++ b/testing/lisp/test-ob-java.el @@ -1,7 +1,9 @@ ;;; test-ob-java.el --- tests for ob-java.el -;; Copyright (c) 2020 Ian Martins -;; Authors: Ian Martins +;; Copyright (c) 2020 Free Software Foundation, Inc. +;; Authors: Eric Schulte +;; Dan Davison +;; Maintainer: Ian Martins <ianxm@jhu.edu> ;; This file is not part of GNU Emacs. |