emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/geiser-kawa 95573c2 019/119: Add initial support for colon


From: Philip Kaludercic
Subject: [nongnu] elpa/geiser-kawa 95573c2 019/119: Add initial support for colon-notation completion
Date: Sun, 1 Aug 2021 18:30:30 -0400 (EDT)

branch: elpa/geiser-kawa
commit 95573c2fed46fceed1a5a1cb26ddf818c7cae1fa
Author: spellcard199 <spellcard199@protonmail.com>
Commit: spellcard199 <spellcard199@protonmail.com>

    Add initial support for colon-notation completion
---
 README.org                         |  87 ++++++++++++++--------
 elisp/geiser-kawa-complete-java.el | 145 +++++++++++++++++++++++++++++++++++++
 elisp/geiser-kawa.el               |   4 +-
 pom.xml                            |   2 +-
 4 files changed, 206 insertions(+), 32 deletions(-)

diff --git a/README.org b/README.org
index 0e7574a..103b5ba 100644
--- a/README.org
+++ b/README.org
@@ -4,36 +4,6 @@
 
 geiser-kawa-java is the emacs side of a geiser-kawa implementation that uses 
[[https://gitlab.com/spellcard199/kawa-geiser][kawa-geiser]] for its Kawa side.
 
-** Supported features
-
-- eval
-- load-file
-- completions
-- module-completions (very fragile atm)
-- autodoc:
-    - for scheme procedures
-    - for java methods
-
-** Unsupported features
-
-geiser-related:
-- macroexpand
-- find-file
-- symbol-location
-- module-location
-- symbol-documentation
-- module-exports
-- callers
-- callees
-- generic-methods
-- (TODO) manual lookup: should work for both formats:
-    - info: using emacs' Info-mode
-    - epub: using emacs' eww browser
-
-kawa- and java-specific:
-- completion for java methods
-- completion for java classes
-
 ** Supported Kawa versions
 :PROPERTIES:
 :CUSTOM_ID:       85b51f74-b1b2-4863-a888-0b11580321f3
@@ -53,6 +23,63 @@ Only versions of Kawa > 3.1 are supported, mostly due to the 
fact that before th
 
 The reason you don't need Kawa to try geiser-kawa is that =quickstart.el= uses 
the compiled [[https://gitlab.com/groups/kashell/][Kawa's master branch]] that 
is one of [[http://gitlab.com/spellcard199/kawa-geiser][kawa-geiser]]'s 
dependencies. To do so =quickstart.el= calls =mvn package= (wrapped by 
=geiser-kawa-compile-java-dependencies=), which produces a jar that includes 
all [[http://gitlab.com/spellcard199/kawa-geiser][kawa-geiser]]'s dependencies.
 
+** Supported features
+
+- geiser-related:
+    - eval
+    - load-file
+    - completions
+    - module-completions (very fragile atm)
+    - autodoc:
+        - for scheme procedures
+        - for java methods
+    - manual lookup:
+        - remember to set variable =geiser-kawa-manual-path=
+        - should work for both formats:
+            - info: using emacs' Info-mode
+            - epub: using emacs' eww browser
+- kawa- and java-specific:
+    - completion for java classes' fields and methods accessed through 
colon-notation: don't expect java-grade reliability
+
+*** About completion for java classes' fields and methods
+
+The main interactive elisp function is 
=geiser-kawa-complete-java-fom-at-point=. It's not bound to a key by default.
+
+For this to work you have to:
+- use Kawa's type annotations: rememver that the Kawa compiler mostly trusts 
you and can't actually check
+- avoid syntax errors (e.g. unbalanced parentheses, wrong number of children 
sexps inside a form, etc...)
+
+How it works:
+1. Code sent is:
+     - from either:
+         - =(geiser-syntax--pop-to-top)=, if non-nil
+         - =(line-beginning-position)=, if =(geiser-syntax--pop-to-top)= is 
=nil=
+     - to either:
+         - end of sexp beginning at toplevel, if =(geiser-syntax--pop-to-top)= 
is non-nil
+         - =(line-end-position)=, if =(geiser-syntax--pop-to-top)= is =nil=
+2. Kawa code and cursor point inside the code are sent to 
[[https://gitlab.com/spellcard199/kawa-geiser][kawa-geiser]], which uses 
[[https://gitlab.com/spellcard199/kawa-devutil][kawa-devutil]] for actual 
functionality
+3. An arbitrary symbol is added at cursor point, so it can be found again in 
the AST
+4. Code is compiled into Kawa's AST but not evaluated
+5. Various AST "matchers" (functions that check if a certain pattern is found) 
are tried in order until the first matcher that matches
+     - "Matcher" functions also try to recognize the Class of the object of 
interest inside the AST
+     - If no matchers match, result is empty data
+
+** Unsupported features
+
+geiser-related:
+- macroexpand
+- find-file
+- symbol-location
+- module-location
+- symbol-documentation
+- module-exports
+- callers
+- callees
+- generic-methods
+
+kawa- and java-specific:
+- completion for java package names and class names
+
 ** Cask issue with geiser
 
 If you use geiser as a dependency in a Cask project, Cask eagerly expands the 
=define-geiser-implementation= macro with =load-file-name= having the wrong 
value. The result is that geiser implementations in geiser do not work when 
geiser is managed as a dependency by Cask.
diff --git a/elisp/geiser-kawa-complete-java.el 
b/elisp/geiser-kawa-complete-java.el
new file mode 100644
index 0000000..55eac45
--- /dev/null
+++ b/elisp/geiser-kawa-complete-java.el
@@ -0,0 +1,145 @@
+;; Copyright (C) 2020 spellcard199 <spellcard199@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 'subr-x)
+
+(defun geiser-kawa--repl--point-after-prompt ()
+  (save-excursion
+    (and (string-prefix-p
+          (geiser-repl-buffer-name 'kawa)
+          (buffer-name))
+         (re-search-backward geiser-kawa--prompt-regexp nil t)
+         (re-search-forward geiser-kawa--prompt-regexp nil t))))
+
+(defun geiser-kawa--point-at-toplevel-p ()
+  (equal (point)
+         (save-excursion
+           (geiser-syntax--pop-to-top)
+           (point))))
+
+(defun geiser-kawa-complete-java--get-data (code-str cursor-index)
+  "`code' is a string containing the code. It must be syntatically
+  scheme, including balanced parentheses.
+`cursor' is an integer representing where the cursor is in that code."
+  (let* ((geiser-question
+          ;; this formatting hell is caused by the fact geiser:eval
+          ;; takes a string instead of a form.
+          (format "(geiser:eval (interaction-environment) %S)"
+                  (format "%S"
+                          `(geiser:complete-java
+                            ,code-str
+                            ,cursor-index
+                            (gnu.expr.Language:getDefaultLanguage)
+                            (interaction-environment)))))
+         (geiser-answer (geiser-eval--send/wait
+                         geiser-question)))
+
+    (if (assoc 'error geiser-answer)
+        (signal 'peculiar-error
+                (list (string-trim
+                       (car (split-string (geiser-eval--retort-output
+                                           geiser-answer)
+                             "\t")))))
+      (geiser-eval--retort-result geiser-answer))))
+
+(defun geiser-kawa-complete-java--user-choice
+    (compl-for-class modifiers
+     field-or-method completions
+     before-cursor)
+  "`for-class' is the class that owns the field or methods in
+`completions'.
+`field-or-method' should be either 'field or 'method, but it's not
+checked.
+`completions' is a list of names (strings) that the user can pick
+from."
+  (completing-read
+   (concat "(" (string-join modifiers " ") " " field-or-method ") "
+           compl-for-class "."
+           ;; "- Exp  : " compl-for-expr "\n"
+           ;; ": "
+           )
+   completions
+   nil
+   nil
+   before-cursor))
+
+(defun geiser-kawa-complete-java--user-choice-data
+    (compl-data)
+  (let ((compl-for-class
+         (cadr (assoc "compl-for-class" compl-data)))
+        (modifiers
+         (cadr (assoc "modifiers" compl-data)))
+        (field-or-method
+         (cadr (assoc "field-or-method" compl-data)))
+        (completions
+         (cadr (assoc "completions" compl-data)))
+        ;; unused
+        (before-cursor
+         (cadr (assoc "before-cursor" compl-data)))
+        ;; unused
+        (after-cursor
+         (cadr (assoc "after-cursor" compl-data))))
+    (geiser-kawa-complete-java--user-choice
+     compl-for-class modifiers
+     field-or-method completions
+     before-cursor)))
+
+(defun geiser-kawa-complete-java--code-point-from-toplevel ()
+  (let* (reg-beg
+         reg-end
+         code-str
+         cursor-index)
+    (if (geiser-kawa--point-at-toplevel-p)
+        (progn
+          (setq reg-beg (line-beginning-position))
+          (setq reg-end (line-end-position))
+          (setq cursor-index (current-column)))
+      (progn
+        (save-excursion
+          (setq reg-beg (progn (geiser-syntax--pop-to-top)
+                               (point)))
+          (setq reg-end (condition-case data
+                            (progn (forward-sexp)
+                                   (point))
+                          (scan-error data))))
+        (when (and (listp reg-end)
+                   (equal (car reg-end) 'scan-error))
+          ;; For now, it's easier not to fix unbalanced parenses
+          (signal (car reg-end) (cdr reg-end)))
+        (setq cursor-index (- (point) reg-beg))))
+    (setq code-str (buffer-substring-no-properties
+                    reg-beg reg-end))
+    (list
+     `("reg-beg"      . ,reg-beg)
+     `("reg-end"      . ,reg-end)
+     `("code-str"     . ,code-str)
+     `("cursor-index" . ,cursor-index))))
+
+(defun geiser-kawa-complete-java-fom-at-point ()
+  (interactive)
+  "Complete java field or method at point"
+
+  (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)))
+         (compl-data (geiser-kawa-complete-java--get-data
+                      code-str cursor-index))
+         (user-choice (geiser-kawa-complete-java--user-choice-data
+                       compl-data)))
+    (when (word-at-point)
+      (if (looking-back ":" (- (point) 2))
+          (kill-word 1)
+          (kill-word -1)))
+    (insert user-choice)
+    ;; (when (not (equal (word-at-point) user-choice))
+    ;;   (kill-word 1)
+    ))
+
+(provide 'geiser-kawa-complete-java)
diff --git a/elisp/geiser-kawa.el b/elisp/geiser-kawa.el
index 3e8e3a3..5bf5435 100644
--- a/elisp/geiser-kawa.el
+++ b/elisp/geiser-kawa.el
@@ -1,7 +1,7 @@
 ;;; geiser-kawa.el --- geiser support for Kawa scheme -*- lexical-binding:t -*-
 
 ;; Copyright (C) 2018 Mathieu Lirzin <mthl@gnu.org>
-;; Copyright (C) 2019 spellcard199 <spellcard199@protonmail.com>
+;; Copyright (C) 2019, 2020 spellcard199 <spellcard199@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
@@ -36,6 +36,8 @@
 (require 'info-look)
 (require 'cl)
 
+(require 'geiser-kawa-complete-java)
+
 ;;; Code:
 
 
diff --git a/pom.xml b/pom.xml
index 4f63fd7..32e215e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,7 +55,7 @@
         <dependency>
             <groupId>com.gitlab.spellcard199</groupId>
             <artifactId>kawa-geiser</artifactId>
-            <version>f47df5ea22503b0eb4d83bc3be6066d9edb3cd18</version>
+            <version>3e7d104a58457e9710f57b1a9b79ea8b48467b5c</version>
         </dependency>
     </dependencies>
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]