[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/geiser-kawa 4247497 007/119: Add geiser-kawa.el (project i
From: |
Philip Kaludercic |
Subject: |
[nongnu] elpa/geiser-kawa 4247497 007/119: Add geiser-kawa.el (project is starting to work) |
Date: |
Sun, 1 Aug 2021 18:30:28 -0400 (EDT) |
branch: elpa/geiser-kawa
commit 42474970c14bf882f438c877cec17b63b711d4ce
Author: spellcard199 <spellcard199@protonmail.com>
Commit: spellcard199 <spellcard199@protonmail.com>
Add geiser-kawa.el (project is starting to work)
---
elisp/geiser-kawa.el | 393 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 393 insertions(+)
diff --git a/elisp/geiser-kawa.el b/elisp/geiser-kawa.el
new file mode 100644
index 0000000..63e2580
--- /dev/null
+++ b/elisp/geiser-kawa.el
@@ -0,0 +1,393 @@
+;;; 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>
+
+;; 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>.
+
+;; Author: spellcard199 <spellcard199@protonmail.com>
+;; Maintainer: spellcard199 <spellcard199@protonmail.com>
+;; Keywords: languages, kawa, scheme, geiser
+;; Homepage: https://gitlab.com/spellcard199/geiser-kawa
+;; Package-Requires: ((emacs "26.1") (geiser "20191025.650"))
+;; Version: 0.0.1
+
+;; This file is NOT part of GNU Emacs.
+
+;;; Commentary:
+
+;; geiser-kawa extends the `geiser' package to support the Kawa
+;; scheme implementation.
+
+
+(require 'geiser-base)
+(require 'geiser-custom)
+(require 'geiser-syntax)
+(require 'geiser-log)
+(require 'geiser-connection)
+(require 'geiser-eval)
+(require 'geiser-edit)
+(require 'geiser)
+
+(require 'compile)
+(require 'info-look)
+(require 'cl)
+
+;;; Code:
+
+
+;; Adaptations for making this package separate from geiser
+
+;; Adapted from geiser.el
+;;;###autoload
+(defconst geiser-kawa-elisp-dir
+ (file-name-directory (or load-file-name (buffer-file-name)))
+ "Directory containing geiser-kawa's Elisp files.")
+
+;; Adapted from geiser.el
+;;;###autoload
+(defconst geiser-kawa-dir
+ (if (string-suffix-p "elisp/" geiser-kawa-elisp-dir)
+ (expand-file-name "../" geiser-kawa-elisp-dir)
+ geiser-kawa-elisp-dir)
+ "geiser-kawa's directory.")
+
+;; Adapted from geiser.el
+(custom-add-load 'geiser-kawa (symbol-name 'geiser-kawa))
+(custom-add-load 'geiser (symbol-name 'geiser-kawa))
+
+;; Moved from geiser.el
+;;;###autoload
+(autoload 'run-kawa "geiser-kawa" "Start a Geiser Kawa Scheme REPL." t)
+
+;;;###autoload
+(autoload 'switch-to-kawa "geiser-kawa"
+ "Start a Geiser Kawa Scheme REPL, or switch to a running one." t)
+
+;; `geiser-active-implementations' is defined in `geiser-impl.el'
+(add-to-list 'geiser-active-implementations 'kawa)
+
+;; End of adaptations for making this package separate from geiser
+
+
+;; Compile the included "kawa-geiser" maven project into a fat jar
+(defun geiser-kawa-compile-java-dependencies()
+ (interactive)
+ (let ((default-directory geiser-kawa-dir))
+ (compile "mvn package")))
+
+;; Using `mvn package' from the pom.xml's directory should produce a
+;; jar containing all the java dependencies.
+(defcustom geiser-kawa-kawa-geiser-jar-path
+ (expand-file-name
+ "./target/kawa-geiser-wrapper-0.1-SNAPSHOT-jar-with-dependencies.jar"
+ geiser-kawa-dir)
+ "Path to the kawa-geiser fat jar."
+ :type 'string
+ :group 'geiser-kawa)
+
+
+;;; Customization:
+
+(defgroup geiser-kawa nil
+ "Customization for Geiser's Kawa Scheme flavour."
+ :group 'geiser)
+
+(geiser-custom--defcustom
+ geiser-kawa-binary "kawa"
+ "Name to use to call the Kawa Scheme executable when starting a REPL."
+ :type '(choice string (repeat string))
+ :group 'geiser-kawa)
+
+;; TODO: replace file-name-directory/directory-file-name with expand-file-name
+(geiser-custom--defcustom
+ geiser-kawa-manual-path
+ (concat
+ (file-name-directory
+ (directory-file-name
+ (file-name-directory
+ (directory-file-name
+ (executable-find geiser-kawa-binary)))))
+ "doc/kawa-manual.epub")
+ "Path of kawa manual. Supported formats are `.epub' (using
+`eww-mode') and `.info' (using `info.el')."
+ :type 'string
+ :group 'geiser-kawa)
+
+(defcustom geiser-kawa-use-kawa-version-included-in-kawa-geiser
+ nil
+ "Instead of downloading kawa yourself, you can use the Kawa version
+ included in geiser-kawa, which is the head of Kawa's master branch."
+ :type 'boolean
+ :group 'geiser-kawa)
+
+
+;;; REPL support:
+
+(defun geiser-kawa--binary ()
+ ". If `geiser-kawa-binary' is a list, take the first and ignore
+ `geiser-kawa-use-kawa-version-included-in-kawa-geiser'."
+ (if geiser-kawa-use-kawa-version-included-in-kawa-geiser
+ "java"
+ (if (listp geiser-kawa-binary)
+ (car geiser-kawa-binary)
+ geiser-kawa-binary)))
+
+(defun geiser-kawa--make-classpath ()
+ (let ((jars (append
+ (let ((lib-dir (expand-file-name
+ "../lib/"
+ (file-name-directory
+ (executable-find geiser-kawa-binary)))))
+ (if (and
+ (not
geiser-kawa-use-kawa-version-included-in-kawa-geiser)
+ (executable-find geiser-kawa-binary)
+ (file-directory-p lib-dir))
+ (list
+ (concat lib-dir "kawa.jar")
+ (concat lib-dir "servlet.jar")
+ (concat lib-dir "domterm.jar")
+ (concat lib-dir "jline.jar"))
+ nil))
+ (list geiser-kawa-kawa-geiser-jar-path))))
+ (mapconcat #'identity jars ":")))
+
+(defvar geiser-kawa--arglist
+ `(;; jline "invisibly" echoes user input and prints ansi chars that
+ ;; makes harder detecting end of output and finding the correct
+ ;; prompt regexp.
+ "console:use-jline=no"
+ "-e"
+ "(require <kawageiser.Geiser>)"
+ "--"))
+
+(defun geiser-kawa--parameters ()
+ "Return a list with all parameters needed to start Kawa Scheme."
+ (append
+ (list (format "-Djava.class.path=%s" (geiser-kawa--make-classpath)))
+ (if geiser-kawa-use-kawa-version-included-in-kawa-geiser
+ (list "kawa.repl"))
+ geiser-kawa--arglist))
+
+(defconst geiser-kawa--prompt-regexp
+ "#|kawa:[0-9]+|# ")
+
+(defun geiser-kawa--geiser-procedure (proc &rest args)
+
+ (case proc
+ ((eval compile)
+ (let* ((form (mapconcat 'identity args " ")) ;;unused
+ (send-this
+ (format
+ "(geiser:eval (interaction-environment) %S)"
+ (cadr args))))
+ send-this))
+
+ ((load-file compile-file)
+ (format "(geiser:load-file %s)" (car args)))
+
+ ((no-values) "(geiser:no-values)")
+
+ (t
+ (let ((form (mapconcat 'identity args " ")))
+ (format "(geiser:%s %s)" proc form)))))
+
+;; TODO
+;; (defun geiser-kawa--find-module (&optional module))
+
+;; Doesn't work:
+;; (defun geiser-kawa--symbol-begin (module)
+;; (save-excursion (skip-syntax-backward "^|#") (point)))
+;; TODO: see if it needs improvements.
+(defun geiser-kawa--symbol-begin (module)
+ ;; Needed for completion. Copied from geiser-chibi.el,
+ ;; geiser-guile.el, which are identical to each other.
+ (if module
+ (max (save-excursion (beginning-of-line) (point))
+ (save-excursion (skip-syntax-backward "^(>") (1- (point))))
+ (save-excursion (skip-syntax-backward "^'-()>") (point))))
+
+(defun geiser-kawa--import-command (module)
+ (format "(import %s)" module))
+
+(defun geiser-kawa--exit-command ()
+ "(exit 0)")
+
+
+;;; REPL startup
+
+(defun geiser-kawa--version-command (binary)
+ (let ((prog+vers (car (process-lines binary "--version"))))
+ (cadr (split-string prog+vers " "))))
+
+(defun geiser-kawa--repl-startup (remote)
+ (let ((geiser-log-verbose-p t))
+ (compilation-setup t)))
+
+
+;;; Error display
+
+;; TODO
+(defun geiser-kawa--enter-debugger ())
+
+(defun geiser-kawa--display-error (module key msg)
+ ;; Needed to show output (besides result). Modified from
+ ;; geiser-guile.el.
+ (when (stringp msg)
+ (save-excursion (insert msg))
+ (geiser-edit--buttonize-files))
+ (and (not key) (not (zerop (length msg))) msg))
+
+
+;;; Manual lookup
+
+;;;; Support for manual in .epub format
+
+;; FIXME: port old scheme logic to java
+(cl-defun geiser-kawa--manual-epub-unzip-to-tmpdir
+ (&optional (epub-path geiser-kawa--manual))
+ "Unzip the .epub file with kawa/java, since:
+- kawa is already a dependency
+- kawa/java is more portable that using emacs' arc-mode, which relies
+ on external executables installed"
+ (with-temp-buffer
+ (with--geiser-implementation
+ 'kawa
+ (geiser-eval--send/result
+ (format
+ "(geiser:eval (interaction-environment) %S)"
+ (format "(geiser:manual-epub-unzip-to-tmp-dir %S)"
+ epub-path))))))
+
+(defvar geiser-kawa--manual-epub-cached-overall-index
+ nil
+ "Since `eww-open-file' is slow we use it just the first time.
+Then we cache the result in this variable so that future lookups in
+the manual are more responsive.")
+
+(cl-defun geiser-kawa--manual-epub-search
+ (needle &optional (epub-path geiser-kawa-manual-path))
+ ;; Validate args
+ (assert (stringp needle) nil (type-of needle))
+ (assert (stringp epub-path) nil (type-of epub-path))
+ (assert (string-suffix-p ".epub" epub-path) nil epub-path)
+ (assert (file-exists-p epub-path) nil epub-path)
+
+ (with-current-buffer (get-buffer-create
+ " *geiser-kawa-epub-manual*")
+ (eww-mode)
+ (if geiser-kawa--manual-epub-cached-overall-index
+ (progn
+ (read-only-mode -1)
+ (delete-region (point-min) (point-max))
+ (insert geiser-kawa--manual-epub-cached-overall-index))
+ (let* ((unzipped-epub-dir
+ ;; Ask kawa to unzip epub: more portable than unzipping
+ ;; with emacs' `arc-mode'.
+ (geiser-kawa--manual-epub-unzip-to-tmpdir epub-path))
+ (overall-index-file
+ (format "%s/OEBPS/Overall-Index.xhtml" unzipped-epub-dir))
+ (epub-man-buffer
+ (get-buffer-create "*geiser-kawa-epub-manual*")))
+ (when (not unzipped-epub-dir)
+ (error "Can't open manual: Kawa did not unzip the epub when asked."))
+ (eww-open-file overall-index-file)
+ ;; Store overall index page in a variable to be used as cache.
+ (setq geiser-kawa--manual-epub-cached-overall-index (buffer-string))))
+
+ ;; At this point the Overall Index page should be opened.
+ (goto-char (point-min))
+ (if (search-forward (concat "\n" needle ": ") nil t) ;; Search
+ (progn
+ (backward-char 3) ;; Move point over link
+ (eww-browse-url (car (eww-links-at-point))) ;; Follow link
+ (recenter-top-bottom 'top))
+ (message (format "No match for `%s' found in Kawa's epub manual."
needle)))))
+
+;;;; Support for manual in .info format
+(cl-defun geiser-kawa--manual-info-search
+ (needle &optional (info-path geiser-kawa-manual-path))
+
+ ;; Validate args
+ (assert (stringp needle) nil (type-of needle))
+ (assert (stringp info-path) nil (type-of info-path))
+ (assert (string-suffix-p ".info" info-path) nil info-path)
+ (assert (file-exists-p info-path) nil info-path)
+
+ (with-current-buffer (get-buffer-create "*geiser-kawa-info-manual*")
+ (info info-path (current-buffer))
+ (Info-goto-node "Overall Index")
+ (if (search-forward (concat "\n* " needle) nil t)
+ (progn
+ (Info-follow-nearest-node)
+ (recenter-top-bottom 'top))
+ (progn
+ (quit-window)
+ (message (format "No match for `%s' found in Kawa's info manual."
+ needle))))))
+
+;;;; Dispatch to epub or info manual function based on
+;;;; `geiser-kawa-manual-path's file extension.
+(defun geiser-kawa--manual-look-up (id mod)
+ "Use epub or info manual depending on `geiser-kawa-manual-path'.
+
+Argument ID is the symbol to look for in the manual.
+Argument MOD is passed by geiser, but it's not used here."
+ (assert (file-exists-p geiser-kawa-manual-path)
+ nil (format
+ (concat
+ "Kawa's manual file specified by "
+ "`geiser-kawa-manual-path' does not exist: \"%s\"")
+ geiser-kawa-manual-path))
+ (cond
+ ((string-suffix-p ".epub" geiser-kawa-manual-path)
+ (geiser-kawa--manual-epub-search (symbol-name id)
+ geiser-kawa-manual-path))
+ ((string-suffix-p ".info" geiser-kawa-manual-path)
+ (geiser-kawa--manual-info-search (symbol-name id)
+ geiser-kawa-manual-path))
+ (t (error "Supported formats for `geiser-kawa-manual-path' are only `.epub'
and `.info'"))))
+
+
+;;; Implementation definition:
+
+(eval
+ ;; (temporary?) Workaround for Cask issue. Wrapping
+ ;; `define-geiser-implementation' with `eval' avoids issue
+ ;; https://github.com/cask/cask/issues/472 in projects that depend on
+ ;; geiser-kawa.
+ '(define-geiser-implementation kawa
+ (unsupported-procedures '(macroexpand
+ find-file
+ symbol-location
+ module-location
+ symbol-documentation
+ module-exports
+ callers
+ callees
+ generic-methods))
+ (binary geiser-kawa--binary)
+ (arglist geiser-kawa--parameters)
+ (version-command geiser-kawa--version-command)
+ (repl-startup geiser-kawa--repl-startup)
+ (prompt-regexp geiser-kawa--prompt-regexp)
+ (debugger-prompt-regexp nil)
+ (marshall-procedure geiser-kawa--geiser-procedure)
+ ;; TODO
+ ;; (find-module geiser-kawa--find-module nil)
+ (exit-command geiser-kawa--exit-command)
+ (import-command geiser-kawa--import-command)
+ (find-symbol-begin geiser-kawa--symbol-begin)
+ (display-error geiser-kawa--display-error)
+ (case-sensitive nil)
+ (external-help geiser-kawa--manual-look-up)))
+
+(geiser-impl--add-to-alist 'regexp "\\.scm$" 'kawa t)
+(geiser-impl--add-to-alist 'regexp "\\.sld$" 'kawa t)
+
+(provide 'geiser-kawa)
+
+;;; geiser-kawa.el ends here
- [nongnu] elpa/geiser-kawa 9cc5ee1 083/119: Update kawa-devutil version + add default for evaluator, (continued)
- [nongnu] elpa/geiser-kawa 9cc5ee1 083/119: Update kawa-devutil version + add default for evaluator, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 19d97d2 098/119: Small fix for package linting, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 6cb6826 107/119: melpa/melpa#6858 - Change regex in geiser-impl--add-to-alist to respect convention, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa fe548f9 104/119: melpa/melpa#6858 - Rename non-standard "geiser-kawa-util--eval/result" to "geiser-kawa-util--eval-get-result", Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa c7c8dae 110/119: melpa/melpa#6858 - Sharp-quote "identity" function, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 52605a4 109/119: melpa/melpa#6858 - Rename 'geiser-kawa-deps--run-kawa--compil-hook' to 'geiser-kawa-deps--run-kawa--compile-hook', Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa e171876 001/119: First commit, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 2e9138c 034/119: Small refactor + update comment in GeiserEval, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 05e1eaa 029/119: Add initial support for completing java packages, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 5d8256d 041/119: Fix re-importing exception, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 4247497 007/119: Add geiser-kawa.el (project is starting to work),
Philip Kaludercic <=
- [nongnu] elpa/geiser-kawa f1d6f8d 023/119: Add maven-wrapper, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 0f5c744 016/119: Avoid issues with older Kawa versions when using quickstart.el, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 5651a3a 031/119: Add message if no completions found, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa cebaa28 042/119: Add test, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 6495077 064/119: Fix: replace lang.getEnvironment() with Environment.user() as default environment, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa b15c4bc 069/119: TODO.org: add todo, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 56b7524 076/119: Add more elisp tests, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa 0fd7c30 086/119: README.org: update, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa f8cf352 096/119: Update kawa-devutil version + add Random_notes.org, Philip Kaludercic, 2021/08/01
- [nongnu] elpa/geiser-kawa df35e6b 099/119: Add unwind-protect in geiser-kawa-deps--run-kawa-unadviced, Philip Kaludercic, 2021/08/01