From 8d2239380665a301c8e0c19f2faa4c9b97c4d45f Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sun, 31 Dec 2017 12:35:30 -0800 Subject: [PATCH] Introduce inf-clojure-completions-fn defcustom Now the user can provide a custom parsing function for completion and therefore has complete (pun intended) freedom in what to use for it. Some could use compliment completion for instance or even use directly what cider provides. The defcustom defaults to inf-clojure-list-completions, which can only parse candidates coming as a Lisp list of strings. --- CHANGELOG.md | 1 + README.md | 12 ++++++++++++ inf-clojure.el | 52 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eca521..80c5dd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * [#114](https://github.com/clojure-emacs/inf-clojure/pull/114): Introduce `inf-clojure-project-type` defcustom. * [#117](https://github.com/clojure-emacs/inf-clojure/pull/117): Introduce `tools.deps` project type and `inf-clojure-tools-deps-cmd`. +* [#122](https://github.com/clojure-emacs/inf-clojure/pull/122): Introduce `inf-clojure-completions-fn` defcustom. ## 2.0.1 (2017-05-18) diff --git a/README.md b/README.md index f528b1c..eebb9d1 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,18 @@ following to you Emacs config: ElDoc currently doesn't work with ClojureScript buffers and REPL's. You can leave it enabled, it just won't show anything in the echo area. +#### Code Completion + +Code completion is particularly open to customization. Not only you can `setq` +the customary `inf-clojure-completion-form`, `inf-clojure-completion-form-lumo` +and `inf-clojure-completion-form-planck` - the form to send to the REPL - but +you can also use `inf-clojure-completions-fn` for specifying a function that +given the REPL response should return elisp data compatible with +[`completion-at-point-functions`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html). +For more info run `M-x describe-variable RET inf-clojure-completions-fn`. +Another option is to have a look at +[how cider does it](https://github.com/clojure-emacs/cider/blob/3e9ed12e8cfbad04d7618e649322765dc9bff5d6/cider-interaction.el#L595). + #### Lumo Setup For an optimal Lumo experience the `-d` needs to be passed to Lumo diff --git a/inf-clojure.el b/inf-clojure.el index ed6058e..3106d8a 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1210,7 +1210,7 @@ prefix argument PROMPT-FOR-NS, it prompts for a namespace name." (defun inf-clojure-set-ns (prompt-for-ns) "Set the ns of the inferior Clojure process to NS. -See variable `inf-clojure-set-ns-form`. It defaults to the ns of +See variable `inf-clojure-set-ns-form'. It defaults to the ns of the current buffer. When invoked with a prefix argument PROMPT-FOR-NS, it prompts for a namespace name." (interactive "P") @@ -1254,14 +1254,52 @@ See variable `inf-clojure-buffer'." "Return DATA if and only if it is a list." (when (listp data) data)) +(defun inf-clojure-list-completions (response-str) + "Parse completions from RESPONSE-STR. + +Its only ability is to parse a Lisp list of candidate strings, +every other EXPR will be discarded and nil will be returned." + (thread-first + response-str + (inf-clojure--read-or-nil) + (inf-clojure--list-or-nil))) + (defun inf-clojure-completions (expr) - "Return a list of completions for the Clojure expression starting with EXPR." + "Return completions for the Clojure expression starting with EXPR. + +Under the hood it calls the function +\\[inf-clojure-completions-fn] passing in the result of +evaluating \\[inf-clojure-completion-form] at the REPL." (when (not (string-blank-p expr)) - (thread-first - (format (inf-clojure-completion-form) (substring-no-properties expr)) - (inf-clojure--process-response (inf-clojure-proc) "(" ")") - (inf-clojure--read-or-nil) - (inf-clojure--list-or-nil)))) + (let ((proc (inf-clojure-proc)) + (completion-form (format (inf-clojure-completion-form) (substring-no-properties expr)))) + (funcall inf-clojure-completions-fn + (inf-clojure--process-response completion-form proc "(" ")"))))) + +(defcustom inf-clojure-completions-fn 'inf-clojure-list-completions + "The function that parses completion results. + +It is a single-arity function that will receive the REPL +evaluation result of \\[inf-clojure-completion-form] as string and +should return elisp data compatible with your completion mode. + +The easiest possible data passed in input is a list of +candidates (e.g.: (\"def\" \"defn\")) but more complex libraries +like `alexander-yakushev/compliment' can return other things like +edn. + +The expected return depends on the mode that you use for +completion: usually it is something compatible with +\\[completion-at-point-functions] but other modes like +`company-mode' allow an even higher level of sophistication. + +The default value is the `inf-clojure-list-completions' function, +which is able to parse results in list form only. You can peek +at its implementation for getting to know some utility functions +you might want to use in your customization." + :type 'function + :safe #'functionp + :package-version '(inf-clojure . "2.1.0")) (defconst inf-clojure-clojure-expr-break-chars " \t\n\"\'`><,;|&{()[]")