summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Martins <ianxm@jhu.edu>2020-10-25 08:08:39 -0400
committerIan Martins <ianxm@jhu.edu>2020-10-25 15:24:08 -0400
commit5a41c62c2671ebfe3e5ea936442819eb66cdb0f9 (patch)
treef08242bdc3c97f7f35e06899afc155901d3e5ed4
parent5b6d774ba10e1c5ee7ae68272ecd19f7784bc3d2 (diff)
downloadorg-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.el176
-rw-r--r--testing/lisp/test-ob-java.el6
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.