branch: elpa/inf-clojure commit e33a546305819dc385e575028bc5636cfc7009f0 Author: dan sutton <d...@dpsutton.com> Commit: Bozhidar Batsov <bozhidar.bat...@gmail.com>
Bugfixes and readme updates - Check for completion feature before capf functionality - would throw an error in complete at point function rather than before starting - Repl type only in process buffer rather than juggling this in two places just put it in the process buffer. --- README.md | 113 +++++++++++++++++++++++---------------------------------- inf-clojure.el | 18 ++++----- todo.org | 18 ++++++++- 3 files changed, 69 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 5be7426..f1aac4b 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ You can install `inf-clojure` using the following command: or if you'd rather keep it in your dotfiles: -```el +```emacs-lisp (unless (package-installed-p 'inf-clojure) (package-refresh-contents) (package-install 'inf-clojure)) @@ -75,7 +75,7 @@ If the installation doesn't work try refreshing the package list: Add the following to your Emacs config to enable `inf-clojure-minor-mode` for Clojure source buffers: -```el +```emacs-lisp (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) ``` @@ -85,39 +85,27 @@ short of havoc.** ## Usage -Just invoke `M-x inf-clojure` or press `C-c C-z` within a Clojure source file. -This will start a REPL process for the current project and you can start -interacting with it. +Just invoke `M-x inf-clojure` or press `C-c C-z` within a Clojure +source file. You should get a prompt with the supported repl types and +common startup forms. You can select one of these or type in your own +custom startup. This will start a REPL process for the current project +and you can start interacting with it. -Inf-clojure has several custom variables which control the command used to -start a REPL for a particular project type: - - - `inf-clojure-lein-cmd` ([Leiningen][]) - - `inf-clojure-boot-cmd` ([Boot][]) - - `inf-clojure-tools-deps-cmd` ([Clojure cli tools][]) - - `inf-clojure-generic-cmd` - -Detection is attempted in the above order (see [function -`inf-clojure-project-type` in this -file](https://github.com/clojure-emacs/inf-clojure/blob/master/inf-clojure.el#L611-L618) -but the `inf-clojure-project-type` variable can force a particular -project type, useful for projects that don't have standard layouts. +If you've already started a socket repl, use `M-x inf-clojure-connect` +and enter the host and port numbers. It is highly recommended to use a cons pair like `("localhost" . 5555)` to connect to a socket REPL, terminal REPLs are inherently hard to work with and support will be deprecated in the foreseeable future. -Interactively, use `M-x inf-clojure-connect` (`C-c M-c`) to connect to a -running socket REPL or `C-u C-c C-z` for specifying a different command/cons -pair. - -You can also set custom values to `inf-clojure` variables on a per-project -basis using -[directory variables](https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html). +Inf-clojure aims to be very simple and offer tooling that the repl +itself exposes. A few commands are: -For a list of all available commands in `inf-clojure-mode` (a.k.a. the REPL) and -`inf-clojure-minor-mode` you can either invoke `C-h f RET inf-clojure-mode` and -`C-h f RET inf-clojure-minor-mode` or simply browse their menus. +- eval last sexp `C-x C-e` +- show arglists for function `C-c C-a` +- show var documentation `C-c C-v` +- show source `C-c C-s` +- insert top level form into repl `C-c C-j d` Many `inf-clojure-minor-mode` commands by default act on the symbol at point. You can, however, change this behaviour by invoking such @@ -136,13 +124,13 @@ clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" Then either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`: -```el +```emacs-lisp ((nil . ((inf-clojure-tools-deps-cmd . ("localhost" . 5555))))) ``` or the following to your [Emacs init file][]: -```el +```emacs-lisp (setf inf-clojure-tools-deps-cmd '("localhost" . 5555)): ``` @@ -154,38 +142,14 @@ For Leiningen, add the following option to your `~/.lein/profiles.clj` or your ` :jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"] ``` -Then run `lein repl` from within your project directory to start the REPL, and either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`: - -```el -((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555))))) -``` - -or the following to your [Emacs init file][]: - -```el -(setf inf-clojure-lein-cmd '("localhost" . 5555)) -``` - -#### Boot Socket REPL +Then run `lein repl` from within your project directory to start the +REPL. To connect, you can either `m-x inf-clojure-connect [RET] +localhost [RET] 5555` or you can put in a dir local file the +information on how connect: -For boot, export the environment variable `BOOT_JVM_OPTIONS`: - -```shell -export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"' -``` - -or add the following to your `.dir-locals.el`: - -```el -((nil . ((inf-clojure-boot-cmd . ("localhost" . 5555))))) -``` - -or the following to your [Emacs init file][]: - -```el -(setf inf-clojure-boot-cmd '("localhost" . 5555)) +```emacs-lisp +((nil (inf-clojure-custom-startup "localhost" . 5555))) ``` - The socket server REPL configuration options are described [here](https://clojure.org/reference/repl_and_main#_launching_a_socket_server). #### Lumo Socket REPL @@ -196,19 +160,19 @@ For example if a `project.clj` is present in the project root folder, `inf-cloju After you launch `lumo ... -n 5555`, as customary, either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`: -```el +```emacs-lisp ((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555))))) ``` or the following to your [Emacs init file][]: -```el +```emacs-lisp (setf inf-clojure-lein-cmd '("localhost" . 5555)) ``` Project detection can be completely skipped and the `generic` project type can be used instead: -```el +```emacs-lisp (setf inf-clojure-project-type . "generic") (setf inf-clojure-generic-cmd '("localhost" 5555)) ``` @@ -221,7 +185,7 @@ filter out ASCII escape characters at the moment and will not behave correctly. You can disable coloring the following way for `boot`: -```el +```emacs-lisp ((nil . ((inf-clojure-boot-cmd . "boot repl -C")))) ``` @@ -301,7 +265,7 @@ By default `inf-clojure` would start a standard Clojure REPL using right launch command (or connect to the REPL via a socket). For example, for Lumo just add the following in your `.dir-locals.el`: -```el +```emacs-lisp ((nil . ((inf-clojure-boot-cmd . "lumo -d")))) ;; inf-clojure-lein-cmd if you are using Leiningen ``` @@ -317,7 +281,7 @@ echo area. You can activate ElDoc with `M-x eldoc-mode` or by adding the following to you Emacs config: -```el +```emacs-lisp (add-hook 'clojure-mode-hook #'eldoc-mode) (add-hook 'inf-clojure-mode-hook #'eldoc-mode) ``` @@ -347,13 +311,26 @@ in order to play nicely with emacs. For example, you can use the following command (assuming `cp` contains the classpath) in your `.dir-locals.el`: -```el +```emacs-lisp ((nil . (eval . (setq inf-clojure-generic-cmd (concat "lumo -d -c " (f-read (concat (inf-clojure-project-root) "cp"))))))) ``` ## Troubleshooting +### Things seem broken + +Inf-clojure is intentionally quite simple and just sends commands to a +repl on your behalf to provide features. In order to do this +inf-clojure largely needs to know the repl type so it can format the +correct calls. Most end up in `(lumo.repl/doc [symbol])` or +`(cljs.repl/doc ...)` so its important that the repl type is set +correctly. This repl type exists in the process buffer (repl) and the +source buffers as a cache. If you have problems, run `m-x +inf-clojure-set-repl-type` from the source buffer to set the repl type +in both buffers. To see how simple inf-clojure is, look at +`inf-clojure-repl-features` to see largely how things are laid out. + ### REPL not responsive in Windows OS In Windows, the REPL is not returning anything. For example, type `(+ @@ -373,7 +350,7 @@ jline.terminal=unsupported Standard Emacs debugging turns out to be difficult when an asynchronous process is involved. In this case try to enable logging: -```el +```emacs-lisp (setq inf-clojure-log-activity t) ``` diff --git a/inf-clojure.el b/inf-clojure.el index 71d6355..008c6a1 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -148,8 +148,7 @@ (defun inf-clojure-get-feature (proc feature &optional no-error) "Get FEATURE based on repl type for PROC." - (let* ((repl-type (or inf-clojure-repl-type - (with-current-buffer (process-buffer proc) + (let* ((repl-type (or (with-current-buffer (process-buffer proc) inf-clojure-repl-type) (error "Repl type is not known"))) (feature-form (alist-get feature (alist-get repl-type inf-clojure-repl-features)))) @@ -195,21 +194,18 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte (type-to-set (intern (completing-read "Set repl type:" (sort (mapcar #'symbol-name types) #'string-lessp))))) - (setq-local inf-clojure-repl-type type-to-set) (with-current-buffer (process-buffer proc) (setq-local inf-clojure-repl-type type-to-set)))) (defun inf-clojure--set-repl-type (proc) "Set the REPL type if has not already been set. It requires a REPL PROC for inspecting the correct type." - (if (not inf-clojure-repl-type) - (let ((repl-type (inf-clojure--detect-repl-type proc))) - ;; set the REPL process buffer - (with-current-buffer inf-clojure-buffer + ;; todo: don't like this happening so frequently + (with-current-buffer (process-buffer proc) + (if (not inf-clojure-repl-type) + (let ((repl-type (inf-clojure--detect-repl-type proc))) (setq-local inf-clojure-repl-type repl-type)) - ;; set in the current buffer - (setq-local inf-clojure-repl-type repl-type)) - inf-clojure-repl-type)) + inf-clojure-repl-type))) (defgroup inf-clojure nil "Run an external Clojure process (REPL) in an Emacs buffer." @@ -1199,7 +1195,7 @@ This guy was taken from CIDER, thanks folks." "Retrieve the list of completions and prompt the user. Returns the selected completion or nil." (let ((bounds (inf-clojure-completion-bounds-of-expr-at-point))) - (when bounds + (when (and bounds (inf-clojure-get-feature (inf-clojure-proc) 'completion 'no-error)) (list (car bounds) (cdr bounds) (if (fboundp 'completion-table-with-cache) (completion-table-with-cache #'inf-clojure-completions) diff --git a/todo.org b/todo.org index e42524f..fd6052f 100644 --- a/todo.org +++ b/todo.org @@ -8,6 +8,9 @@ For some reason ~inf-clojure--set-repl-type~ is called in: Seems better to do this on the two different connection methods and then be done with it? +** DONE do we need repl type in both source buffer and connection? + these can get out of sync and lead to confusing errors when closing a repl and opening a new one. It seems like we keep the repl-type in the source buffer to prevent a single ~(with-current-buffer (process-buffer proc) inf-clojure-repl-type)~ + ** TODO nice startup There's some project detection but that's becoming less and less useful as time goes on. Shadow, lein, deps.edn can all easily be mixed in the same project. And then lumo, planck, or bb scripts could live side by side. Rather than trying to guess the project type, I think i'd like to mimic geiser's style of handling multiple scheme backends. Perhaps ~m-x inf-clojure-run-planck~ and similar could help out. @@ -15,7 +18,7 @@ Some considerations: - is this path aware? IE, don't show an option to run planck, lumo, etc, if they aren't visible or installed? - should it have a rebuild function so that user registered implementations can show up in the ~m-x~ menu as well? -** TODO Better dispatch for the implementations +** DONE Better dispatch for the implementations Right now the functions are kinda clunky cond statements: #+BEGIN_SRC emacs-lisp (defun inf-clojure-cljs-features-dispatch (feature) @@ -41,6 +44,19 @@ Right now everything is just a format string with a _single_ ~%s~ in it and that ** TODO Simpler way to define an implementation This first pass is very mechanical and just rearranging so we can easily see which features are where. In the future we should look into just providing the repl namespace and seeing how far we can get with that. For instance, an API like ~(inf-clojure-register 'bb "bb.repl")~ and this would tell us where ~source~, ~doc~, ~apropos~ ...etc live. No reason to duplicate all of these. +** TODO ability to update repl commands + we had this feature originally but now they are all literals. This is almost entirely fine but one problem. It would be common to toss clojure completions on the class path and then add the completions form for clojure. + +This should come back but only in a sense: if you don't have this on the classpath its obviously unacceptable to throw errors every time the user hits tab. Do we need some state recording if this is on the classpath or not maybe? + +#+BEGIN_SRC emacs-lisp + (defcustom inf-clojure-completion-form + "(complete.core/completions \"%s\")" + "Form to query inferior Clojure for completion candidates." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.0.0")) +#+END_SRC ** TODO Multiple connections As proven by CIDER, multiple connections are just a pain. Scoping, navigating into dependencies, etc. This is a monster lurking