|
@@ -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))))
|