branch: elpa/geiser-kawa commit 79dec5450e57495f9e38b1006bd104b3bed746eb Author: spellcard199 <spellcard...@protonmail.com> Commit: spellcard199 <spellcard...@protonmail.com>
Add support for viewing Expression tree --- elisp/geiser-kawa-etree.el | 85 +++++++++++++ elisp/geiser-kawa-exprtree.el | 85 +++++++++++++ elisp/geiser-kawa.el | 1 + pom.xml | 2 +- .../java/kawageiser/java/GeiserCompleteJava.java | 133 ++++++++++++++++----- 5 files changed, 278 insertions(+), 28 deletions(-) diff --git a/elisp/geiser-kawa-etree.el b/elisp/geiser-kawa-etree.el new file mode 100644 index 0000000..9941068 --- /dev/null +++ b/elisp/geiser-kawa-etree.el @@ -0,0 +1,85 @@ +;; Copyright (C) 2020 spellcard199 <spellcard...@protonmail.com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the Modified BSD License. You should +;; have received a copy of the license along with this program. If +;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>. + +(require 'geiser-kawa-complete-java) + +(defvar geiser-kawa-exprtree-buffer "*kawa exprtree*" + "Buffer where Expression tree is showed") + +(defun geiser-kawa-eval--to-res (sexp) + (let* ((question + (format "(geiser:eval (interaction-environment) %S)" + (format "%S" sexp))) + (answer (geiser-eval--send/wait question))) + + (if (assoc 'error answer) + (signal 'peculiar-error + (list (string-trim + (car (split-string (geiser-eval--retort-output + answer) + "\t"))))) + ;; from: ((result "expr-tree") (output . ...)) + ;; to: "expr-tree" + (cadr (car answer))))) + +(defun geiser-kawa-exprtree--view (expr-tree) + (with-current-buffer (get-buffer-create + geiser-kawa-exprtree-buffer) + (View-quit) + (delete-region (point-min) (point-max)) + (insert expr-tree) + (goto-char (point-min))) + + (view-buffer-other-window + geiser-kawa-exprtree-buffer)) + +(defun geiser-kawa-exprtree--for-expression (code-str) + (geiser-kawa-eval--to-res + ;; Kawa sexp here + `(invoke + (kawadevutil.ast.AstElemWrapper + (kawadevutil.compile.Compile:compileStr + ,code-str)) + 'formatElem java.lang.Boolean:TRUE))) + +(defun geiser-kawa-exprtree-for-expression () + (interactive) + "If region is active send region, otherwise send last expression." + (let* ((code-str + (if (region-active-p) + (buffer-substring-no-properties reg-beg reg-end) + (save-excursion + (let ((sexp-beg (progn (backward-sexp) (point))) + (sexp-end (progn (forward-sexp) (point)))) + (buffer-substring-no-properties sexp-beg sexp-end))))) + (expr-tree (geiser-kawa-exprtree--for-expression + code-str))) + (geiser-kawa-exprtree--view expr-tree))) + +(defun geiser-kawa-exprtree--for-fmp-completion(code-str cursor-index) + (geiser-kawa-eval--to-res + ;; Kawa sexp here + `(kawageiser.java.GeiserCompleteJava:getExprTreeAndFormat + ,code-str + ,cursor-index))) + +(defun geiser-kawa-exprtree-for-fmp-completion () + (interactive) + (let* ((code-and-point-data + (geiser-kawa-complete-java--code-point-from-toplevel)) + (code-str (cdr (assoc "code-str" + code-and-point-data))) + (cursor-index (cdr (assoc "cursor-index" + code-and-point-data))) + (expr-tree (geiser-kawa-exprtree--for-fmp-completion + code-str cursor-index))) + (geiser-kawa-exprtree--view expr-tree))) + +(provide 'geiser-kawa-exprtree) + +;;; geiser-kawa-exprtree.el ends here + diff --git a/elisp/geiser-kawa-exprtree.el b/elisp/geiser-kawa-exprtree.el new file mode 100644 index 0000000..9941068 --- /dev/null +++ b/elisp/geiser-kawa-exprtree.el @@ -0,0 +1,85 @@ +;; Copyright (C) 2020 spellcard199 <spellcard...@protonmail.com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the Modified BSD License. You should +;; have received a copy of the license along with this program. If +;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>. + +(require 'geiser-kawa-complete-java) + +(defvar geiser-kawa-exprtree-buffer "*kawa exprtree*" + "Buffer where Expression tree is showed") + +(defun geiser-kawa-eval--to-res (sexp) + (let* ((question + (format "(geiser:eval (interaction-environment) %S)" + (format "%S" sexp))) + (answer (geiser-eval--send/wait question))) + + (if (assoc 'error answer) + (signal 'peculiar-error + (list (string-trim + (car (split-string (geiser-eval--retort-output + answer) + "\t"))))) + ;; from: ((result "expr-tree") (output . ...)) + ;; to: "expr-tree" + (cadr (car answer))))) + +(defun geiser-kawa-exprtree--view (expr-tree) + (with-current-buffer (get-buffer-create + geiser-kawa-exprtree-buffer) + (View-quit) + (delete-region (point-min) (point-max)) + (insert expr-tree) + (goto-char (point-min))) + + (view-buffer-other-window + geiser-kawa-exprtree-buffer)) + +(defun geiser-kawa-exprtree--for-expression (code-str) + (geiser-kawa-eval--to-res + ;; Kawa sexp here + `(invoke + (kawadevutil.ast.AstElemWrapper + (kawadevutil.compile.Compile:compileStr + ,code-str)) + 'formatElem java.lang.Boolean:TRUE))) + +(defun geiser-kawa-exprtree-for-expression () + (interactive) + "If region is active send region, otherwise send last expression." + (let* ((code-str + (if (region-active-p) + (buffer-substring-no-properties reg-beg reg-end) + (save-excursion + (let ((sexp-beg (progn (backward-sexp) (point))) + (sexp-end (progn (forward-sexp) (point)))) + (buffer-substring-no-properties sexp-beg sexp-end))))) + (expr-tree (geiser-kawa-exprtree--for-expression + code-str))) + (geiser-kawa-exprtree--view expr-tree))) + +(defun geiser-kawa-exprtree--for-fmp-completion(code-str cursor-index) + (geiser-kawa-eval--to-res + ;; Kawa sexp here + `(kawageiser.java.GeiserCompleteJava:getExprTreeAndFormat + ,code-str + ,cursor-index))) + +(defun geiser-kawa-exprtree-for-fmp-completion () + (interactive) + (let* ((code-and-point-data + (geiser-kawa-complete-java--code-point-from-toplevel)) + (code-str (cdr (assoc "code-str" + code-and-point-data))) + (cursor-index (cdr (assoc "cursor-index" + code-and-point-data))) + (expr-tree (geiser-kawa-exprtree--for-fmp-completion + code-str cursor-index))) + (geiser-kawa-exprtree--view expr-tree))) + +(provide 'geiser-kawa-exprtree) + +;;; geiser-kawa-exprtree.el ends here + diff --git a/elisp/geiser-kawa.el b/elisp/geiser-kawa.el index ff9011c..c9207a2 100644 --- a/elisp/geiser-kawa.el +++ b/elisp/geiser-kawa.el @@ -37,6 +37,7 @@ (require 'cl) (require 'geiser-kawa-complete-java) +(require 'geiser-kawa-exprtree) ;;; Code: diff --git a/pom.xml b/pom.xml index 935aa0d..ae97614 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ <dependency> <groupId>com.gitlab.spellcard199</groupId> <artifactId>kawa-devutil</artifactId> - <version>5aa298138d09904a0370d93f8a4bcb46e253e71c</version> + <version>28c5ea885835974a52ff51682d176267596c5a82</version> </dependency> <!-- https://mvnrepository.com/artifact/org.testng/testng --> diff --git a/src/main/java/kawageiser/java/GeiserCompleteJava.java b/src/main/java/kawageiser/java/GeiserCompleteJava.java index f1d2e4b..dd21220 100644 --- a/src/main/java/kawageiser/java/GeiserCompleteJava.java +++ b/src/main/java/kawageiser/java/GeiserCompleteJava.java @@ -6,12 +6,15 @@ package kawageiser.java; import gnu.expr.Language; +import gnu.kawa.functions.Format; import gnu.lists.IString; import gnu.lists.LList; import gnu.mapping.Environment; import gnu.math.IntNum; +import kawadevutil.ast.AstElemWrapper; import kawadevutil.complete.*; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -21,40 +24,59 @@ import java.util.stream.Collectors; public class GeiserCompleteJava { public static String - completeJava(IString codeStr, IntNum cursorIndex, Language lang, Environment env) + completeJava( + IString codeStr, + IntNum cursorIndex) + throws Throwable { + return completeJava( + codeStr, + cursorIndex, + Language.getDefaultLanguage(), + Environment.user()); + } + + public static String + completeJava( + IString codeStr, + IntNum cursorIndex, + Language lang, + Environment env) throws Throwable { // Get Data - Optional<CompletionDataForJava> complDataMaybe = kawadevutil.complete.Complete.complete( - codeStr.toString(), - Integer.valueOf(cursorIndex.toString()), - lang, - env, - (String name) -> true); + Optional<CompletionDataForJava> complDataMaybe = + kawadevutil.complete.Complete.complete( + codeStr.toString(), + Integer.valueOf(cursorIndex.toString()), + lang, + env); + return complDataMaybe + .map(GeiserCompleteJava::complDataForJavaToLList) + .map(x -> Format.format("~S", x).toString()) + .orElse(Format.format("~A", LList.Empty).toString()); + } + + public static LList + complDataForJavaToLList( + CompletionDataForJava complData) { // Wrap data of interest in Scheme's LList - String resAsStr; - if (!complDataMaybe.isPresent()) { - resAsStr = gnu.kawa.functions.Format.format("~A", LList.Empty).toString(); + LList complDataAsLList = null; + if (complData.getClass().equals(CompletionDataForJavaField.class) + || complData.getClass().equals(CompletionDataForJavaMethod.class)) { + complDataAsLList = toLList((CompletionDataForJavaFOM) complData); + } else if (complData.getClass().equals(CompletionDataForJavaPackage.class)) { + complDataAsLList = toLList((CompletionDataForJavaPackage) complData); } else { - CompletionDataForJava complData = complDataMaybe.get(); - LList res = null; - if (complData.getClass().equals(CompletionDataForJavaField.class) - || complData.getClass().equals(CompletionDataForJavaMethod.class)) { - res = toLList((CompletionDataForJavaFOM) complData); - } else if (complData.getClass().equals(CompletionDataForJavaPackage.class)) { - res = toLList((CompletionDataForJavaPackage) complData); - } else { - throw new Error("[BUG SPOTTED] `complData's class is one not expected: " - + complData.getClass().toString()); - } - resAsStr = gnu.kawa.functions.Format.format("~S", res).toString(); + throw new Error("[BUG SPOTTED] `complData's class is one not expected: " + + complData.getClass().toString()); } - - return resAsStr; + return complDataAsLList; } - private static LList toLList(CompletionDataForJavaFOM complData) { + private static LList + toLList( + CompletionDataForJavaFOM complData) { String completionsForClass = complData.getForClass().getName(); // I don't know why it says "unchecked call" when using complData.getRequiredModifiers().stream() ArrayList<String> modifiers = new ArrayList<>(); @@ -71,7 +93,9 @@ public class GeiserCompleteJava { } - private static LList toLList(CompletionDataForJavaPackage complData) { + private static LList + toLList( + CompletionDataForJavaPackage complData) { ArrayList<LList> res = new ArrayList<>(getCommonData(complData)); res.addAll(Arrays.asList( LList.list2("package-name", complData.getPinfo().getName()) @@ -79,7 +103,9 @@ public class GeiserCompleteJava { return LList.makeList(res); } - private static List<LList> getCommonData(CompletionDataForJava complData) { + private static List<LList> + getCommonData( + CompletionDataForJava complData) { CompletionDataForJava.FieldOrMethodOrPackage fieldOrMethod = complData.getFieldOrMethodOrPackage(); List<String> names = (List<String>) complData.getNames().stream().distinct().collect(Collectors.toList()); String beforeCursor = complData.getCursorMatcher().getCursorMatch().getBeforeCursor(); @@ -93,4 +119,57 @@ public class GeiserCompleteJava { ); return res; } + + public static Optional<AstElemWrapper> + getExprTreeMaybe( + IString codeStr, + IntNum cursorIndex, + Language lang, + Environment env) + throws IOException { + Optional<CompletionDataForJava> complDataMaybe = + kawadevutil.complete.Complete.complete( + codeStr.toString(), + Integer.valueOf(cursorIndex.toString()), + lang, + env + ); + return complDataMaybe.map(complData -> + complData.getCursorMatcher().getRootWrapper()); + } + + public static Optional<AstElemWrapper> + getExprTreeMaybe( + IString codeStr, + IntNum cursorIndex) + throws IOException { + return getExprTreeMaybe( + codeStr, + cursorIndex, + Language.getDefaultLanguage(), + Environment.user()); + + } + + public static String getExprTreeAndFormat( + IString codeStr, + IntNum cursorIndex, + Language lang, + Environment env) + throws IOException { + return getExprTreeMaybe(codeStr, cursorIndex, lang, env) + .map(complData -> complData.formatElem(true)).get(); + } + + public static String getExprTreeAndFormat( + IString codeStr, + IntNum cursorIndex) + throws IOException { + return getExprTreeAndFormat( + codeStr, + cursorIndex, + Language.getDefaultLanguage(), + Environment.user() + ); + } }