From f4478ad09359e0edfc7c423315ccce61eff788a4 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 12 Jan 2018 16:51:20 -0800 Subject: [PATCH 001/189] Fix and reword docstring I went through a checkdoc session and fixed what was easiest to fix. Not everything, but it is a good start. --- inf-clojure.el | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 351c3b1..15da3bc 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -392,7 +392,7 @@ This should usually be a combination of `inf-clojure-prompt' and :package-version '(inf-clojure . "2.0.0")) (defvar inf-clojure-buffer nil - "The current inf-clojure process buffer. + "The current `inf-clojure' process buffer. MULTIPLE PROCESS SUPPORT =========================================================================== @@ -558,9 +558,10 @@ Fallback to `default-directory.' if not within a project." "Run an inferior Clojure process, input and output via buffer `*inf-clojure*'. If there is a process already running in `*inf-clojure*', just switch to that buffer. -With argument, allows you to edit the command line (default is value -of `inf-clojure-*-cmd'). Runs the hooks from -`inf-clojure-mode-hook' (after the `comint-mode-hook' is run). +With argument, allows you to edit the CMD used to launch +it (default is value of `inf-clojure-*-cmd'). Runs the hooks +from `inf-clojure-mode-hook' (after the `comint-mode-hook' is +run). \(Type \\[describe-mode] in the process buffer for a list of commands.)" (interactive (list (if current-prefix-arg (read-string "Run Clojure: " (inf-clojure-cmd (inf-clojure-project-type))) @@ -680,9 +681,11 @@ Used by this command to determine defaults." :type '(repeat symbol)) (defun inf-clojure-load-file (&optional switch-to-repl file-name) - "Load a Clojure file FILE-NAME into the inferior Clojure process. + "Load a Clojure file into the inferior Clojure process. -The prefix argument SWITCH-TO-REPL controls whether to switch to REPL after the file is loaded or not." +The prefix argument SWITCH-TO-REPL controls whether to switch to +REPL after the file is loaded or not. If the argument FILE-NAME +is present it will be used instead of the current file." (interactive "P") (let ((file-name (or file-name (car (comint-get-source "Load Clojure file: " inf-clojure-prev-l/c-dir/file @@ -1004,8 +1007,11 @@ If you are using REPL types, it will pickup the most approapriate ;;; Ancillary functions ;;; =================== -;;; Reads a string from the user. (defun inf-clojure-symprompt (prompt default) + "Read a string from the user. + +It allows to specify a PROMPT string and a DEFAULT string to +display." (list (let* ((prompt (if default (format "%s (default %s): " prompt default) (concat prompt ": "))) @@ -1222,16 +1228,16 @@ PROMPT-FOR-NS, it prompts for a namespace name." (user-error "No namespace selected")) (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-set-ns-form) ns)))) -(defun inf-clojure-apropos (var) - "Send a form to the inferior Clojure to give apropos for VAR. +(defun inf-clojure-apropos () + "Send an expression to the inferior Clojure for apropos. See variable `inf-clojure-apropos-form'." (interactive (inf-clojure-symprompt "Var apropos" (inf-clojure-symbol-at-point))) (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-apropos-form) var))) (defun inf-clojure-macroexpand (&optional macro-1) - "Send a form to the inferior Clojure to give apropos for VAR. + "Send a form to the inferior Clojure for macro expansion. See variable `inf-clojure-macroexpand-form'. -With a prefix arg MACRO-1 uses `inf-clojure-macroexpand-1-form'." +With a prefix arg MACRO-1 uses function `inf-clojure-macroexpand-1-form'." (interactive "P") (let ((last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point)))) (inf-clojure--send-string @@ -1418,9 +1424,9 @@ Return the number of nested sexp the point was over or after." (message "inf-clojure (version %s)" inf-clojure-version)) (defun inf-clojure-select-target-repl () - "Find or select an inf-clojure buffer to operate on. + "Find or select an ‘inf-clojure’ buffer to operate on. -Useful for commands that can invoked outside of an inf-clojure buffer +Useful for commands that can invoked outside of an ‘inf-clojure’ buffer \\(e.g. from a Clojure buffer\\)." ;; if we're in a inf-clojure buffer we simply return in (if (eq major-mode 'inf-clojure-mode) @@ -1461,7 +1467,7 @@ to suppress the usage of the target buffer discovery logic." (rename-buffer target-buffer-name))) (defun inf-clojure--response-match-p (form match-p proc) - "Return MATCH-P on the result of sending FORM to PROC. + "Send FORM and apply MATCH-P on the result of sending it to PROC. Note that this function will add a \n to the end of the string for evaluation, therefore FORM should not include it." (funcall match-p (inf-clojure--process-response form proc nil))) From 7b2fcd7b468a14e98d0a5d3dd90faabf7d00089e Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sun, 21 Jan 2018 12:24:58 -0800 Subject: [PATCH 002/189] Revive inf-clojure-apropos The function signature was broken, also update the docstring. --- inf-clojure.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 15da3bc..eca2c27 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1228,11 +1228,12 @@ PROMPT-FOR-NS, it prompts for a namespace name." (user-error "No namespace selected")) (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-set-ns-form) ns)))) -(defun inf-clojure-apropos () +(defun inf-clojure-apropos (expr) "Send an expression to the inferior Clojure for apropos. -See variable `inf-clojure-apropos-form'." +EXPR can be either a regular expression or a stringable +thing. See variable `inf-clojure-apropos-form'." (interactive (inf-clojure-symprompt "Var apropos" (inf-clojure-symbol-at-point))) - (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-apropos-form) var))) + (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-apropos-form) expr))) (defun inf-clojure-macroexpand (&optional macro-1) "Send a form to the inferior Clojure for macro expansion. From 8baa7ade4d1777720df512ffb8000f6a940eae99 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sun, 21 Jan 2018 12:35:43 -0800 Subject: [PATCH 003/189] Correct inf-clojure-apropos key binding Broken because emacs interprets C-A as C-a. This patch also adds the same key binding to inf-clojure-mode (in the REPL). --- inf-clojure.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index eca2c27..ee0eae8 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -101,6 +101,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (define-key map "\C-c\C-a" #'inf-clojure-show-arglists) (define-key map "\C-c\C-v" #'inf-clojure-show-var-documentation) (define-key map "\C-c\C-s" #'inf-clojure-show-var-source) + (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) (define-key map "\C-c\M-o" #'inf-clojure-clear-repl-buffer) (define-key map "\C-c\C-q" #'inf-clojure-quit) (easy-menu-define inf-clojure-mode-menu map @@ -113,6 +114,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword ["Show arglists" inf-clojure-show-arglists t] ["Show documentation for var" inf-clojure-show-var-documentation t] ["Show source for var" inf-clojure-show-var-source t] + ["Apropos" inf-clojure-apropos t] "--" ["Clear REPL" inf-clojure-clear-repl-buffer] ["Restart" inf-clojure-restart] @@ -132,7 +134,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (define-key map "\C-c\C-n" #'inf-clojure-eval-form-and-next) (define-key map "\C-c\C-z" #'inf-clojure-switch-to-repl) (define-key map "\C-c\C-i" #'inf-clojure-show-ns-vars) - (define-key map "\C-c\C-A" #'inf-clojure-apropos) + (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) (define-key map "\C-c\C-m" #'inf-clojure-macroexpand) (define-key map "\C-c\C-l" #'inf-clojure-load-file) (define-key map "\C-c\C-a" #'inf-clojure-show-arglists) From 62bb0fce3183c32c0461098eb3d4614f51bcc68d Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sun, 21 Jan 2018 12:40:19 -0800 Subject: [PATCH 004/189] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19fb15a..d9c384c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,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. +* [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Expose `inf-clojure-apropos` as `C-c C-S-a` in `inf-clojure-mode` (the REPL). ### Bugs Fixed @@ -18,6 +19,7 @@ * [#101](https://github.com/clojure-emacs/inf-clojure/pull/101): `inf-clojure-set-ns` hangs Emacs. * [#119](https://github.com/clojure-emacs/inf-clojure/pull/119): Set inf-clojure-buffer REPL type on detect. * [#120](https://github.com/clojure-emacs/inf-clojure/pull/120): Send REPL string always, even if empty. +* [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Fix inf-clojure-apropos. ## 2.0.1 (2017-05-18) From d3c0d4f31d66e141f6a787902a45967081092cba Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 12 Jan 2018 09:56:59 -0800 Subject: [PATCH 005/189] Avoid throwing an error for frequent operations like completion This patch introduces an argument to inf-clojure-proc so that client code can decide when to error out return the processs. This is necessary because while it is good to communicate an error on "eval" operations, it is not good to have it on "under the hood" and very frequent ones like completion and get arglists. --- CHANGELOG.md | 1 + inf-clojure.el | 141 ++++++++++++++++++++++++++----------------------- 2 files changed, 75 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9c384c..9f63d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * [#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. * [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Expose `inf-clojure-apropos` as `C-c C-S-a` in `inf-clojure-mode` (the REPL). +* [#125](https://github.com/clojure-emacs/inf-clojure/pull/125): Avoid throwing an error for frequent operations like completion. ### Bugs Fixed diff --git a/inf-clojure.el b/inf-clojure.el index ee0eae8..2854761 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -363,11 +363,11 @@ Clojure to load that file." :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-load-form () - "Return the form to query inferior Clojure for a var's documentation. +(defun inf-clojure-load-form (proc) + "Return the form to query the Inf-Clojure PROC for var's documentation. If you are using REPL types, it will pickup the most appropriate `inf-clojure-var-doc-form` variant." - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-load-form-lumo) (`planck inf-clojure-load-form-planck) (_ inf-clojure-load-form))) @@ -689,15 +689,15 @@ The prefix argument SWITCH-TO-REPL controls whether to switch to REPL after the file is loaded or not. If the argument FILE-NAME is present it will be used instead of the current file." (interactive "P") - (let ((file-name (or file-name + (let ((proc (inf-clojure-proc)) + (file-name (or file-name (car (comint-get-source "Load Clojure file: " inf-clojure-prev-l/c-dir/file ;; nil because doesn't need an exact name inf-clojure-source-modes nil))))) (comint-check-source file-name) ; Check to see if buffer needs saved. (setq inf-clojure-prev-l/c-dir/file (cons (file-name-directory file-name) (file-name-nondirectory file-name))) - (inf-clojure--send-string (inf-clojure-proc) - (format (inf-clojure-load-form) file-name)) + (inf-clojure--send-string proc (format (inf-clojure-load-form proc) file-name)) (when switch-to-repl (inf-clojure-switch-to-repl t)))) @@ -736,12 +736,12 @@ is present it will be used instead of the current file." :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-var-doc-form () - "Return the form to query inferior Clojure for a var's documentation. +(defun inf-clojure-var-doc-form (proc) + "Return the form to query the Inf-Clojure PROC for a var's documentation. If you are using REPL types, it will pickup the most approapriate `inf-clojure-var-doc-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-var-doc-form-lumo) (`planck inf-clojure-var-doc-form-planck) (_ inf-clojure-var-doc-form)))) @@ -767,12 +767,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-var-source-form () - "Return the form to query inferior Clojure for a var's source. +(defun inf-clojure-var-source-form (proc) + "Return the form to query the Inf-Clojure PROC for a var's source. If you are using REPL types, it will pickup the most approapriate `inf-clojure-var-source-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-var-source-form-lumo) (`planck inf-clojure-var-source-form-planck) (_ inf-clojure-var-source-form)))) @@ -810,12 +810,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.1.0")) -(defun inf-clojure-arglists-form () - "Return the form to query inferior Clojure for arglists of a var. +(defun inf-clojure-arglists-form (proc) + "Return the form to query the Inf-Clojure PROC for arglists of a var. If you are using REPL types, it will pickup the most approapriate `inf-clojure-arglists-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-arglists-form-lumo) (`planck inf-clojure-arglists-form-planck) (_ inf-clojure-arglists-form)))) @@ -846,12 +846,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-completion-form () - "Return the form to query inferior Clojure for a var's documentation. +(defun inf-clojure-completion-form (proc) + "Return the form to query the Inf-Clojure PROC for completions. If you are using REPL types, it will pickup the most approapriate `inf-clojure-completion-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-completion-form-lumo) (`planck inf-clojure-completion-form-planck) (_ inf-clojure-completion-form)))) @@ -877,12 +877,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-ns-vars-form () - "Return the form to query inferior Clojure for public vars in a namespace. +(defun inf-clojure-ns-vars-form (proc) + "Return the form to query the Inf-Clojure PROC for public vars in a namespace. If you are using REPL types, it will pickup the most approapriate `inf-clojure-ns-vars-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-ns-vars-form-lumo) (`planck inf-clojure-ns-vars-form-planck) (_ inf-clojure-ns-vars-form)))) @@ -910,11 +910,11 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-set-ns-form () - "Return the form to set the ns of the inferior Clojure process. +(defun inf-clojure-set-ns-form (proc) + "Return the form to set the namespace of the Inf-Clojure PROC. If you are using REPL types, it will pickup the most approapriate `inf-clojure-set-ns-form` variant." - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`planck inf-clojure-set-ns-form-planck) (`lumo inf-clojure-set-ns-form-lumo) (_ inf-clojure-set-ns-form))) @@ -944,12 +944,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-apropos-form () - "Return the form to query inferior Clojure for public vars in a namespace. +(defun inf-clojure-apropos-form (proc) + "Return the form to query the Inf-Clojure PROC for a var's apropos. If you are using REPL types, it will pickup the most approapriate -`inf-clojure-ns-vars-form` variant." +`inf-clojure-apropos-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-apropos-form-lumo) (`planck inf-clojure-apropos-form-planck) (_ inf-clojure-apropos-form)))) @@ -970,12 +970,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-macroexpand-form () - "Return the form for macroexpansion in the inferior Clojure process. +(defun inf-clojure-macroexpand-form (proc) + "Return the form for macroexpansion in the Inf-Clojure PROC. If you are using REPL types, it will pickup the most approapriate `inf-clojure-macroexpand-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`planck inf-clojure-macroexpand-form-planck) (_ inf-clojure-macroexpand-form)))) @@ -995,12 +995,12 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) -(defun inf-clojure-macroexpand-1-form () - "Return the form for macroexpand-1 in the inferior Clojure process. +(defun inf-clojure-macroexpand-1-form (proc) + "Return the form for macroexpand-1 in the Inf-Clojure PROC. If you are using REPL types, it will pickup the most approapriate `inf-clojure-macroexpand-1-form` variant." (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type (inf-clojure-proc)) + (pcase (inf-clojure--set-repl-type proc) (`planck inf-clojure-macroexpand-1-form-planck) (_ inf-clojure-macroexpand-1-form)))) @@ -1047,20 +1047,22 @@ The value is nil if it can't find one." See function `inf-clojure-var-doc-form'. When invoked with a prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name." (interactive "P") - (let ((var (if prompt-for-symbol - (car (inf-clojure-symprompt "Var doc" (inf-clojure-symbol-at-point))) - (inf-clojure-symbol-at-point)))) - (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-var-doc-form) var)))) + (let ((proc (inf-clojure-proc)) + (var (if prompt-for-symbol + (car (inf-clojure-symprompt "Var doc" (inf-clojure-symbol-at-point))) + (inf-clojure-symbol-at-point)))) + (inf-clojure--send-string proc (format (inf-clojure-var-doc-form proc) var)))) (defun inf-clojure-show-var-source (prompt-for-symbol) "Send a command to the inferior Clojure to give source for VAR. See variable `inf-clojure-var-source-form'. When invoked with a prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name." (interactive "P") - (let ((var (if prompt-for-symbol + (let ((proc (inf-clojure-proc)) + (var (if prompt-for-symbol (car (inf-clojure-symprompt "Var source" (inf-clojure-symbol-at-point))) (inf-clojure-symbol-at-point)))) - (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-var-source-form) var)))) + (inf-clojure--send-string proc (format (inf-clojure-var-source-form proc) var)))) ;;;; Response parsing ;;;; ================ @@ -1190,10 +1192,11 @@ for evaluation, therefore FORM should not include it." (defun inf-clojure-arglists (fn) "Send a query to the inferior Clojure for the arglists for function FN. See variable `inf-clojure-arglists-form'." - (thread-first - (format (inf-clojure-arglists-form) fn) - (inf-clojure--process-response (inf-clojure-proc) "(" ")") - (inf-clojure--some))) + (when-let ((proc (inf-clojure-proc 'no-error))) + (thread-first + (format (inf-clojure-arglists-form proc) fn) + (inf-clojure--process-response proc "(" ")") + (inf-clojure--some)))) (defun inf-clojure-show-arglists (prompt-for-symbol) "Show the arglists for function FN in the mini-buffer. @@ -1212,10 +1215,11 @@ prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name." See variable `inf-clojure-ns-vars-form'. When invoked with a prefix argument PROMPT-FOR-NS, it prompts for a namespace name." (interactive "P") - (let ((ns (if prompt-for-ns - (car (inf-clojure-symprompt "Ns vars" (clojure-find-ns))) - (clojure-find-ns)))) - (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-ns-vars-form) ns)))) + (let ((proc (inf-clojure-proc)) + (ns (if prompt-for-ns + (car (inf-clojure-symprompt "Ns vars" (clojure-find-ns))) + (clojure-find-ns)))) + (inf-clojure--send-string proc (format (inf-clojure-ns-vars-form proc) ns)))) (defun inf-clojure-set-ns (prompt-for-ns) "Set the ns of the inferior Clojure process to NS. @@ -1223,41 +1227,44 @@ 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") - (let ((ns (if prompt-for-ns + (let ((proc (inf-clojure-proc)) + (ns (if prompt-for-ns (car (inf-clojure-symprompt "Set ns to" (clojure-find-ns))) (clojure-find-ns)))) (when (or (not ns) (equal ns "")) (user-error "No namespace selected")) - (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-set-ns-form) ns)))) + (inf-clojure--send-string proc (format (inf-clojure-set-ns-form proc) ns)))) (defun inf-clojure-apropos (expr) "Send an expression to the inferior Clojure for apropos. EXPR can be either a regular expression or a stringable thing. See variable `inf-clojure-apropos-form'." (interactive (inf-clojure-symprompt "Var apropos" (inf-clojure-symbol-at-point))) - (inf-clojure--send-string (inf-clojure-proc) (format (inf-clojure-apropos-form) expr))) + (let ((proc (inf-clojure-proc))) + (inf-clojure--send-string proc (format (inf-clojure-apropos-form proc) expr)))) (defun inf-clojure-macroexpand (&optional macro-1) "Send a form to the inferior Clojure for macro expansion. See variable `inf-clojure-macroexpand-form'. With a prefix arg MACRO-1 uses function `inf-clojure-macroexpand-1-form'." (interactive "P") - (let ((last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point)))) + (let ((proc (inf-clojure-proc)) + (last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point)))) (inf-clojure--send-string - (inf-clojure-proc) + proc (format (if macro-1 - (inf-clojure-macroexpand-1-form) - (inf-clojure-macroexpand-form)) + (inf-clojure-macroexpand-1-form proc) + (inf-clojure-macroexpand-form proc)) last-sexp)))) - -(defun inf-clojure-proc () +(defun inf-clojure-proc (&optional no-error) "Return the current inferior Clojure process. -See variable `inf-clojure-buffer'." - (let ((proc (get-buffer-process (if (derived-mode-p 'inf-clojure-mode) - (current-buffer) - inf-clojure-buffer)))) - (or proc +When NO-ERROR is non-nil, don't throw an error when no connection +has been found. See also variable `inf-clojure-buffer'." + (or (get-buffer-process (if (derived-mode-p 'inf-clojure-mode) + (current-buffer) + inf-clojure-buffer)) + (unless no-error (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) (defun inf-clojure--list-or-nil (data) @@ -1280,11 +1287,11 @@ every other EXPR will be discarded and nil will be returned." 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)) - (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 "(" ")"))))) + (let ((proc (inf-clojure-proc 'no-error))) + (when (and proc (not (string-blank-p expr))) + (let ((completion-form (format (inf-clojure-completion-form proc) (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. From 715bd82721aae1f15e3f297abf465e89728417ae Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Thu, 25 Jan 2018 19:13:07 -0800 Subject: [PATCH 006/189] Add macroexpand forms for Lumo --- CHANGELOG.md | 1 + inf-clojure.el | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f63d38..e455d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ * [#119](https://github.com/clojure-emacs/inf-clojure/pull/119): Set inf-clojure-buffer REPL type on detect. * [#120](https://github.com/clojure-emacs/inf-clojure/pull/120): Send REPL string always, even if empty. * [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Fix inf-clojure-apropos. +* [#131](https://github.com/clojure-emacs/inf-clojure/pull/131): Add macroexpand forms for Lumo. ## 2.0.1 (2017-05-18) diff --git a/inf-clojure.el b/inf-clojure.el index 2854761..b09b34c 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -970,12 +970,20 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-macroexpand-form-lumo + "(macroexpand '%s)" + "Lumo form to invoke macroexpand." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-macroexpand-form (proc) "Return the form for macroexpansion in the Inf-Clojure PROC. If you are using REPL types, it will pickup the most approapriate `inf-clojure-macroexpand-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) + (`lumo inf-clojure-macroexpand-form-lumo) (`planck inf-clojure-macroexpand-form-planck) (_ inf-clojure-macroexpand-form)))) @@ -995,12 +1003,20 @@ If you are using REPL types, it will pickup the most approapriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-macroexpand-1-form-lumo + "(macroexpand-1 '%s)" + "Lumo form to invoke macroexpand-1." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-macroexpand-1-form (proc) "Return the form for macroexpand-1 in the Inf-Clojure PROC. If you are using REPL types, it will pickup the most approapriate `inf-clojure-macroexpand-1-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) + (`lumo inf-clojure-macroexpand-1-form-lumo) (`planck inf-clojure-macroexpand-1-form-planck) (_ inf-clojure-macroexpand-1-form)))) From ec99211bbe9bef6d579a313ab6422694ef63b181 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Thu, 25 Jan 2018 18:28:59 -0800 Subject: [PATCH 007/189] Support loading directory locals in our buffers A couple of changes to the way the redirect buffer and the main REPL buffer are created was needed in order to have actual loading of .dir-locals.el. Additionally, code in inf-clojure--process-response has been simplified and corrected. --- CHANGELOG.md | 1 + inf-clojure.el | 60 +++++++++++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e455d27..4864593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [#122](https://github.com/clojure-emacs/inf-clojure/pull/122): Introduce `inf-clojure-completions-fn` defcustom. * [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Expose `inf-clojure-apropos` as `C-c C-S-a` in `inf-clojure-mode` (the REPL). * [#125](https://github.com/clojure-emacs/inf-clojure/pull/125): Avoid throwing an error for frequent operations like completion. +* [#130](https://github.com/clojure-emacs/inf-clojure/pull/130): Support loading directory locals in our buffers. ### Bugs Fixed diff --git a/inf-clojure.el b/inf-clojure.el index b09b34c..b1956e8 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -575,9 +575,10 @@ run). (list cmd) (split-string cmd)))) (message "Starting Clojure REPL via `%s'..." cmd) - (set-buffer (apply #'make-comint - "inf-clojure" (car cmdlist) nil (cdr cmdlist))) - (inf-clojure-mode))) + (with-current-buffer (apply #'make-comint + "inf-clojure" (car cmdlist) nil (cdr cmdlist)) + (inf-clojure-mode) + (hack-dir-local-variables-non-file-buffer)))) (setq inf-clojure-buffer "*inf-clojure*") (if inf-clojure-repl-use-same-window (pop-to-buffer-same-window "*inf-clojure*") @@ -1124,6 +1125,17 @@ are going to match those." (length string)) (or (string-match prompt string) (length string)))) +(defun inf-clojure--get-redirect-buffer () + "Get the redirection buffer, creating it if necessary. + +It is the buffer used for processing REPL responses, see variable +\\[inf-clojure--redirect-buffer-name]." + (or (get-buffer inf-clojure--redirect-buffer-name) + (let ((buffer (generate-new-buffer inf-clojure--redirect-buffer-name))) + (with-current-buffer buffer + (hack-dir-local-variables-non-file-buffer) + buffer)))) + ;; Originally from: ;; https://github.com/glycerine/lush2/blob/master/lush2/etc/lush.el#L287 (defun inf-clojure--process-response (command process &optional beg-regexp end-regexp) @@ -1134,31 +1146,29 @@ If BEG-REGEXP is nil, the result string will start from (point) in the results buffer. If END-REGEXP is nil, the result string will end at (point-max) in the results buffer. It cuts out the output from and including the `inf-clojure-prompt`." - (let ((work-buffer inf-clojure--redirect-buffer-name) + (let ((redirect-buffer-name inf-clojure--redirect-buffer-name) (sanitized-command (inf-clojure--sanitize-command command))) (when (not (string-empty-p sanitized-command)) (inf-clojure--log-string command "----CMD->") - (with-current-buffer (get-buffer-create work-buffer) - (erase-buffer) - (comint-redirect-send-command-to-process sanitized-command work-buffer process nil t) - ;; Wait for the process to complete - (set-buffer (process-buffer process)) - (while (and (null comint-redirect-completed) - (accept-process-output process 1 0 t)) - (sleep-for 0.01)) - ;; Collect the output - (set-buffer work-buffer) - (goto-char (point-min)) - (let* ((buffer-string (buffer-substring-no-properties (point-min) (point-max))) - (boundaries (inf-clojure--string-boundaries buffer-string inf-clojure-prompt beg-regexp end-regexp)) - (beg-pos (car boundaries)) - (end-pos (car (cdr boundaries))) - (prompt-pos (car (cdr (cdr boundaries)))) - (response-string (substring buffer-string beg-pos (min end-pos prompt-pos)))) - (inf-clojure--log-string buffer-string "<-BUF----") - (inf-clojure--log-string boundaries "<-BND----") - (inf-clojure--log-string response-string "<-RES----") - response-string))))) + (set-buffer (inf-clojure--get-redirect-buffer)) + (erase-buffer) + (comint-redirect-send-command-to-process sanitized-command redirect-buffer-name process nil t) + ;; Wait for the process to complete + (set-buffer (process-buffer process)) + (while (and (null comint-redirect-completed) + (accept-process-output process 1 0 t)) + (sleep-for 0.01)) + ;; Collect the output + (set-buffer redirect-buffer-name) + (goto-char (point-min)) + (let* ((buffer-string (buffer-substring-no-properties (point-min) (point-max))) + (boundaries (inf-clojure--string-boundaries buffer-string inf-clojure-prompt beg-regexp end-regexp)) + (beg-pos (car boundaries)) + (end-pos (car (cdr boundaries))) + (prompt-pos (car (cdr (cdr boundaries)))) + (response-string (substring buffer-string beg-pos (min end-pos prompt-pos)))) + (inf-clojure--log-string buffer-string "<-RES----") + response-string)))) (defun inf-clojure--nil-string-match-p (string) "Return true iff STRING is not nil. From d4010db0c95f495531ac6505dd5114db736f24a5 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 22 Jan 2018 14:24:44 -0800 Subject: [PATCH 008/189] Add @ (deref) and ^ to the expression breaking chars They were both missing and therefore the inf-clojure was not able to identify completions bounds correctly. --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index b1956e8..8c5befd 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1344,7 +1344,7 @@ you might want to use in your customization." :safe #'functionp :package-version '(inf-clojure . "2.1.0")) -(defconst inf-clojure-clojure-expr-break-chars " \t\n\"\'`><,;|&{()[]") +(defconst inf-clojure-clojure-expr-break-chars " \t\n\"\'`><,;|&{()[]@\\^") (defun inf-clojure-completion-bounds-of-expr-at-point () "Return bounds of expression at point to complete." From dcb523bf8bd21189e18a6751a8c2d3e1a698573d Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 22 Jan 2018 16:25:41 -0800 Subject: [PATCH 009/189] Avoid computing completion bounds when no valid chars are at point For instance we want to avoid using substring-no-properties while typing ^| (where | is point) because it will error out. --- inf-clojure.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 8c5befd..127ff9c 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1352,9 +1352,11 @@ you might want to use in your customization." (save-excursion (let ((end (point))) (skip-chars-backward (concat "^" inf-clojure-clojure-expr-break-chars)) - (let ((first-char (substring-no-properties (thing-at-point 'symbol) 0 1))) - (when (string-match-p "[^0-9]" first-char) - (cons (point) end))))))) + (let ((chars (thing-at-point 'symbol))) + (when (> (length chars) 0) + (let ((first-char (substring-no-properties chars 0 1))) + (when (string-match-p "[^0-9]" first-char) + (cons (point) end))))))))) (defun inf-clojure-completion-expr-at-point () "Return expression at point to complete." From 94f440e141c4dbe1293d90c2297c9d9239ff56bd Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 26 Jan 2018 12:36:37 -0800 Subject: [PATCH 010/189] Extract keyword words for completion The patch copies functionality from cider so that now inf-clojure can detect and extract keywords (colons included) when a symbol at point is not found. --- inf-clojure.el | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 127ff9c..382f223 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1344,19 +1344,38 @@ you might want to use in your customization." :safe #'functionp :package-version '(inf-clojure . "2.1.0")) -(defconst inf-clojure-clojure-expr-break-chars " \t\n\"\'`><,;|&{()[]@\\^") +(defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()[@\\^]" + "Regexp are hard. + +This regex has been built in order to match the first of the +listed chars. There are a couple of quirks to consider: + +- the ] is always a special in elisp regex so you have to put it + directly AFTER [ if you want to match it as literal. +- The ^ needs to be escaped with \\^. + +Tests and `re-builder' are your friends.") + +(defun inf-clojure--kw-to-symbol (kw) + "Convert the keyword KW to a symbol. + +This guy was taken from CIDER, thanks folks." + (when kw + (replace-regexp-in-string "\\`:+" "" kw))) (defun inf-clojure-completion-bounds-of-expr-at-point () "Return bounds of expression at point to complete." (when (not (memq (char-syntax (following-char)) '(?w ?_))) (save-excursion - (let ((end (point))) - (skip-chars-backward (concat "^" inf-clojure-clojure-expr-break-chars)) - (let ((chars (thing-at-point 'symbol))) - (when (> (length chars) 0) - (let ((first-char (substring-no-properties chars 0 1))) - (when (string-match-p "[^0-9]" first-char) - (cons (point) end))))))))) + (let* ((end (point)) + (skipped-back (skip-chars-backward inf-clojure-clojure-expr-break-chars)) + (start (+ end skipped-back)) + (chars (or (thing-at-point 'symbol) + (inf-clojure--kw-to-symbol (buffer-substring start end))))) + (when (> (length chars) 0) + (let ((first-char (substring-no-properties chars 0 1))) + (when (string-match-p "[^0-9]" first-char) + (cons (point) end)))))))) (defun inf-clojure-completion-expr-at-point () "Return expression at point to complete." From 803a419de6cff6515fbb10644dd1e85df801883e Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 22 Jan 2018 15:55:23 -0800 Subject: [PATCH 011/189] Add test harness (finally?) This patch add ert test harness and some tests around the inf-clojure-completion-bounds-of-expr-at-point function. --- .gitignore | 12 ++++ .travis.yml | 17 ++++++ Cask | 11 ++++ test/inf-clojure-tests.el | 114 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Cask create mode 100644 test/inf-clojure-tests.el diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c724233 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*~ +*\#*\# +*.\#* +*.elc +.cask +elpa* +.depend +TAGS +.DS_STORE +dist +.vagrant/ +.dir-locals?.el diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..57ec6dd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: generic +sudo: false +before_install: + - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > x.sh && source ./x.sh + - evm install $EVM_EMACS --use --skip + - cask +env: + - EVM_EMACS=emacs-24.3-travis + - EVM_EMACS=emacs-24.4-travis + - EVM_EMACS=emacs-24.5-travis + - EVM_EMACS=emacs-25.1-travis + - EVM_EMACS=emacs-25.2-travis + - EVM_EMACS=emacs-25.3-travis +script: + - emacs --version + - cask install + - cask exec buttercup -L . diff --git a/Cask b/Cask new file mode 100644 index 0000000..d2a5667 --- /dev/null +++ b/Cask @@ -0,0 +1,11 @@ +(source gnu) +(source melpa) + +(package-file "inf-clojure.el") + +(files "*.el" (:exclude ".dir-locals.el")) + +(development + (depends-on "clojure-mode") + (depends-on "buttercup") + (depends-on "assess")) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el new file mode 100644 index 0000000..994801c --- /dev/null +++ b/test/inf-clojure-tests.el @@ -0,0 +1,114 @@ +;;; inf-clojure-tests.el --- Tests for Inf-Clojure -*- lexical-binding: t; -*- +;; +;; Copyright © 2014-2018 Bozhidar Batsov + +;; Authors: Bozhidar Batsov +;; Andrea Richiardi +;; URL: http://github.com/clojure-emacs/inf-clojure +;; Keywords: processes, clojure +;; Package-Requires: ((emacs "24.4") (clojure-mode "5.3")) + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; Code completion using alexander-yakushev/compliment. + +;;; Code: + +;; Tests for inf-clojure.el + +(message "Running tests on Emacs %s" emacs-version) + +(require 'buttercup) +(require 'assess) +(require 'inf-clojure) + +(cl-defmacro ict-with-assess-buffers ((&rest varlist) &body body) + `(assess-with-temp-buffers (,@varlist) + (clojure-mode) + (inf-clojure-minor-mode) + ,@body)) + +(defun ict-bounds-string (bounds) + (buffer-substring (car bounds) (cdr bounds))) + +(describe "inf-clojure--kw-to-symbol" + (it "returns symbol form of the given keyword" + (expect (inf-clojure--kw-to-symbol "symbol") :to-equal "symbol") + (expect (inf-clojure--kw-to-symbol ":clj.core/str") :to-equal "clj.core/str") + (expect (inf-clojure--kw-to-symbol "::keyword") :to-equal "keyword") + (expect (inf-clojure--kw-to-symbol nil) :to-equal nil))) + +(describe "completion bounds at point" () + (it "computes bounds for plain-text" + (ict-with-assess-buffers + ((a (insert "plain-text"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "plain-text")))) + + (it "computes bounds for @deref" + (ict-with-assess-buffers + ((a (insert "@deref"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "deref")))) + + (it "computes bounds for ^:keyword" + (ict-with-assess-buffers + ((a (insert "^:keyword"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal ":keyword")))) + + (it "computes bounds for ::keyword" + (ict-with-assess-buffers + ((a (insert "::keyword"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "::keyword")))) + + (it "computes bounds for [^:keyword (combined break chars and keyword)" + (ict-with-assess-buffers + ((a (insert "[^:keyword"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal ":keyword")))) + + (it "computes no bounds for point directly after a break expression" + (ict-with-assess-buffers + ((a (insert "@"))) + (with-current-buffer a + (expect + (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :not :to-be nil)))) + + (it "computes bounds for [symbol" + (ict-with-assess-buffers + ((a (insert "[symbol"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "symbol")))) + + (it "computes bounds for (@deref (multiple break chars)" + (ict-with-assess-buffers + ((a (insert "(@deref"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "deref"))))) + +;;; inf-clojure-tests.el ends here From 630471b5141cb493305b623e6800c26bc91b3913 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 26 Jan 2018 12:41:29 -0800 Subject: [PATCH 012/189] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4864593..87b78fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Expose `inf-clojure-apropos` as `C-c C-S-a` in `inf-clojure-mode` (the REPL). * [#125](https://github.com/clojure-emacs/inf-clojure/pull/125): Avoid throwing an error for frequent operations like completion. * [#130](https://github.com/clojure-emacs/inf-clojure/pull/130): Support loading directory locals in our buffers. +* [#129](https://github.com/clojure-emacs/inf-clojure/pull/129): Improve the completion bounds detection (now with keywords). ### Bugs Fixed From be3e2e7c5ec9302cf1a7d5e39defc2ecc78bd9de Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Tue, 30 Jan 2018 18:12:06 -0800 Subject: [PATCH 013/189] Introduce inf-clojure-reload It will evaluate (require 'ns :reload) or (require 'ns :reload-all) at the REPL, depending on the arguments passed in. This works only from source buffers at the moment (like all the other namespace commands). --- CHANGELOG.md | 1 + README.md | 1 + inf-clojure.el | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b78fe..31e1fa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [#125](https://github.com/clojure-emacs/inf-clojure/pull/125): Avoid throwing an error for frequent operations like completion. * [#130](https://github.com/clojure-emacs/inf-clojure/pull/130): Support loading directory locals in our buffers. * [#129](https://github.com/clojure-emacs/inf-clojure/pull/129): Improve the completion bounds detection (now with keywords). +* [#132](https://github.com/clojure-emacs/inf-clojure/pull/132): Introduce inf-clojure-reload. ### Bugs Fixed diff --git a/README.md b/README.md index 16f78b1..23fa630 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Clojure(Script) development: * ElDoc * Apropos * Macroexpansion +* Require `:reload`/`:reload-all` * Support connecting to socket REPLs * Support for Lumo * Support for Planck diff --git a/inf-clojure.el b/inf-clojure.el index 382f223..385b149 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -131,6 +131,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (define-key map "\C-c\C-c" #'inf-clojure-eval-defun) ; SLIME/CIDER style (define-key map "\C-c\C-b" #'inf-clojure-eval-buffer) (define-key map "\C-c\C-r" #'inf-clojure-eval-region) + (define-key map "\C-c\M-r" #'inf-clojure-reload) (define-key map "\C-c\C-n" #'inf-clojure-eval-form-and-next) (define-key map "\C-c\C-z" #'inf-clojure-switch-to-repl) (define-key map "\C-c\C-i" #'inf-clojure-show-ns-vars) @@ -152,6 +153,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword ["Eval buffer" inf-clojure-eval-buffer t] "--" ["Load file..." inf-clojure-load-file t] + ["Reload file... " inf-clojure-reload t] "--" ["Switch to REPL" inf-clojure-switch-to-repl t] ["Set REPL ns" inf-clojure-set-ns t] @@ -372,6 +374,48 @@ If you are using REPL types, it will pickup the most appropriate (`planck inf-clojure-load-form-planck) (_ inf-clojure-load-form))) +(defcustom inf-clojure-reload-form "(require '\"%s\" :reload)" + "Format-string for building a Clojure expression to reload a file. +Reload forces loading of all the identified libs even if they are +already loaded. +This format string should use `%s' to substitute a namespace and +should result in a Clojure form that will be sent to the inferior +Clojure to load that file." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + +;; :reload forces loading of all the identified libs even if they are + ;; already loaded +;; :reload-all implies :reload and also forces loading of all libs that the +;; identified libs directly or indirectly load via require or use + +(defun inf-clojure-reload-form (proc) + "Return the form to query the Inf-Clojure PROC for reloading a namespace. +If you are using REPL types, it will pickup the most appropriate +`inf-clojure-reload-form` variant." + (inf-clojure--set-repl-type proc) + inf-clojure-reload-form) + +(defcustom inf-clojure-reload-all-form "(require '\"%s\" :reload-all)" + "Format-string for building a Clojure expression to :reload-all a file. +Reload-all implies :reload and also forces loading of all libs +that the identified libs directly or indirectly load via require +or use. +This format string should use `%s' to substitute a namespace and +should result in a Clojure form that will be sent to the inferior +Clojure to load that file." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + +(defun inf-clojure-reload-all-form (proc) + "Return the form to query the Inf-Clojure PROC for :reload-all of a namespace. +If you are using REPL types, it will pickup the most appropriate +`inf-clojure-reload-all-form` variant." + (inf-clojure--set-repl-type proc) + inf-clojure-reload-all-form) + (defcustom inf-clojure-prompt "^[^=> \n]+=> *" "Regexp to recognize prompts in the Inferior Clojure mode." :type 'regexp) @@ -702,6 +746,28 @@ is present it will be used instead of the current file." (when switch-to-repl (inf-clojure-switch-to-repl t)))) +(defun inf-clojure-reload (arg) + "Send a query to the inferior Clojure for reloading the namespace. +See variable `inf-clojure-reload-form' and +`inf-clojure-reload-all-form'. + +The prefix argument ARG can change the behavior of the command: + + - C-u M-x `inf-clojure-reload': prompts for a namespace name. + - M-- M-x `inf-clojure-reload': executes (require ... :reload-all). + - M-- C-u M-x `inf-clojure-reload': reloads all AND prompts." + (interactive "P") + (let* ((proc (inf-clojure-proc)) + (invertp (or (equal arg "-") (equal arg '(-4)))) + (promptp (or (equal arg '(4)) (equal arg '(-4)))) + (ns (if promptp + (car (inf-clojure-symprompt "Namespace" (clojure-find-ns))) + (clojure-find-ns))) + (form (if (not invertp) + (inf-clojure-reload-form proc) + (inf-clojure-reload-all-form proc)))) + (inf-clojure--send-string proc (format form ns)))) + (defun inf-clojure-connected-p () "Return t if inferior Clojure is currently connected, nil otherwise." (not (null inf-clojure-buffer))) From 903dd739c575a1b0d5495a3f6a2baf9ccc23d174 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 19 Feb 2018 11:55:19 -0800 Subject: [PATCH 014/189] Set explicitly inf-clojure-repl-type for REPL and source buffer Fixing a wrong behavior that was previously never setting it for source buffers. --- inf-clojure.el | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 385b149..e9920f9 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -296,10 +296,14 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte (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." - (with-current-buffer inf-clojure-buffer - (if (not inf-clojure-repl-type) - (setq inf-clojure-repl-type (inf-clojure--detect-repl-type proc)) - inf-clojure-repl-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 + (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)) (defun inf-clojure--single-linify (string) "Convert a multi-line STRING in a single-line STRING. From 6c719c6e8bdaedf4f98888bcba31afe1989c9229 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 23 Feb 2018 12:03:24 -0800 Subject: [PATCH 015/189] Avoid leaking buffers from inf-clojure--process-response --- inf-clojure.el | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index e9920f9..817147d 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1220,25 +1220,25 @@ output from and including the `inf-clojure-prompt`." (sanitized-command (inf-clojure--sanitize-command command))) (when (not (string-empty-p sanitized-command)) (inf-clojure--log-string command "----CMD->") - (set-buffer (inf-clojure--get-redirect-buffer)) - (erase-buffer) - (comint-redirect-send-command-to-process sanitized-command redirect-buffer-name process nil t) + (with-current-buffer (inf-clojure--get-redirect-buffer) + (erase-buffer) + (comint-redirect-send-command-to-process sanitized-command redirect-buffer-name process nil t)) ;; Wait for the process to complete - (set-buffer (process-buffer process)) - (while (and (null comint-redirect-completed) - (accept-process-output process 1 0 t)) - (sleep-for 0.01)) + (with-current-buffer (process-buffer process) + (while (and (null comint-redirect-completed) + (accept-process-output process 1 0 t)) + (sleep-for 0.01))) ;; Collect the output - (set-buffer redirect-buffer-name) - (goto-char (point-min)) - (let* ((buffer-string (buffer-substring-no-properties (point-min) (point-max))) - (boundaries (inf-clojure--string-boundaries buffer-string inf-clojure-prompt beg-regexp end-regexp)) - (beg-pos (car boundaries)) - (end-pos (car (cdr boundaries))) - (prompt-pos (car (cdr (cdr boundaries)))) - (response-string (substring buffer-string beg-pos (min end-pos prompt-pos)))) - (inf-clojure--log-string buffer-string "<-RES----") - response-string)))) + (with-current-buffer redirect-buffer-name + (goto-char (point-min)) + (let* ((buffer-string (buffer-substring-no-properties (point-min) (point-max))) + (boundaries (inf-clojure--string-boundaries buffer-string inf-clojure-prompt beg-regexp end-regexp)) + (beg-pos (car boundaries)) + (end-pos (car (cdr boundaries))) + (prompt-pos (car (cdr (cdr boundaries)))) + (response-string (substring buffer-string beg-pos (min end-pos prompt-pos)))) + (inf-clojure--log-string buffer-string "<-RES----") + response-string))))) (defun inf-clojure--nil-string-match-p (string) "Return true iff STRING is not nil. From 953feb0041b631b49395c73a7f0a446a2faed698 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 23 Feb 2018 14:47:34 -0800 Subject: [PATCH 016/189] Improve command sanitation code This patch improves the parsing and sanitation of command and make sure, with tests, that we do things correctly. --- CHANGELOG.md | 2 ++ inf-clojure.el | 8 ++++---- test/inf-clojure-tests.el | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31e1fa2..6701933 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +* [#135](https://github.com/clojure-emacs/inf-clojure/pull/135): Improve command sanitation code. + ## 2.1.0 (2018-01-02) ### New Features diff --git a/inf-clojure.el b/inf-clojure.el index 817147d..61f7d73 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -307,10 +307,10 @@ It requires a REPL PROC for inspecting the correct type." (defun inf-clojure--single-linify (string) "Convert a multi-line STRING in a single-line STRING. -It also reduces/adds redundant whitespace for readability. Note -that this function will transform the empty string in \" \" (it -adds an empty space)." - (replace-regexp-in-string "[ \\|\n]+" " " string)) +It also reduces redundant whitespace for readability." + (thread-last string + (replace-regexp-in-string "[ \\|\n]+" " ") + (replace-regexp-in-string " $" ""))) (defun inf-clojure--trim-newline-right (string) "Trim newlines (only) in STRING." diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 994801c..6147dd3 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -111,4 +111,24 @@ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) :to-equal "deref"))))) +(describe "inf-clojure--single-linify" + (it "replaces newlines with whitespace" + (expect (inf-clojure--single-linify "(do\n(println \"hello world\")\n)") :to-equal "(do (println \"hello world\") )")) + + (it "does not leave whitespace at the end" + (expect (inf-clojure--single-linify "(do\n(println \"hello world\")\n)\n\n") :to-equal "(do (println \"hello world\") )")) + + (it "returns empty string in case of only newline" + (expect (inf-clojure--single-linify "\n\n\n\n") :to-equal ""))) + +(describe "inf-clojure--sanitize-command" + (it "sanitizes the command correctly" + (expect (inf-clojure--sanitize-command "(doc println)") :to-equal "(doc println)\n")) + + (it "trims newline at the right of a command" + (expect (inf-clojure--sanitize-command "(doc println)\n\n\n\n") :to-equal "(doc println)\n")) + + (it "returns empty string when the command is empty" + (expect (inf-clojure--sanitize-command " ") :to-equal ""))) + ;;; inf-clojure-tests.el ends here From f420c8a4d27c7c2dfea2ebee230d4d1b632a4e3f Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 23 Feb 2018 14:59:12 -0800 Subject: [PATCH 017/189] Add sanitation to inf-clojure-send-string The function did not have sanitation and therefore it has been added. Some more logging has been added so that .inf-clojure.log can show every interaction. --- inf-clojure.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 61f7d73..c44694b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -338,7 +338,10 @@ always be preferred over `comint-send-string`. It delegates to the string for evaluation. Refer to `comint-simple-send` for customizations." (inf-clojure--set-repl-type proc) - (comint-simple-send proc string)) + (let ((sanitized (inf-clojure--sanitize-command string))) + (when (not (string-empty-p sanitized)) + (inf-clojure--log-string sanitized "----CMD->") + (comint-simple-send proc sanitized)))) (defcustom inf-clojure-load-form "(clojure.core/load-file \"%s\")" "Format-string for building a Clojure expression to load a file. @@ -559,6 +562,7 @@ to continue it." (defun inf-clojure-preoutput-filter (str) "Preprocess the output STR from interactive commands." + (inf-clojure--log-string str "<-RES----") (cond ((string-prefix-p "inf-clojure-" (symbol-name (or this-command last-command))) ;; Remove subprompts and prepend a newline to the output string @@ -1177,7 +1181,7 @@ STRING if present." (concat tag "\n") (concat (prin1-to-string tag) "\n"))) (let ((print-escape-newlines t)) - (prin1-to-string string))) + (prin1-to-string (substring-no-properties string)))) nil (expand-file-name inf-clojure--log-file-name (inf-clojure-project-root)) From c3217c3fad1a06b0d40f25b64fffee8f115316d2 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 23 Feb 2018 19:45:47 -0800 Subject: [PATCH 018/189] Skip sanitation of comments --- inf-clojure.el | 30 ++++++++++++++++-------------- test/inf-clojure-tests.el | 18 +++++++++++++----- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index c44694b..de64f39 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -305,27 +305,29 @@ It requires a REPL PROC for inspecting the correct type." (setq-local inf-clojure-repl-type repl-type)) inf-clojure-repl-type)) -(defun inf-clojure--single-linify (string) +(defun inf-clojure--whole-comment-line-p (string) + "Return true iff STRING is a whole line semicolon comment." + (string-match-p "^\s*;" string)) + +(defun inf-clojure--make-single-line (string) "Convert a multi-line STRING in a single-line STRING. -It also reduces redundant whitespace for readability." - (thread-last string - (replace-regexp-in-string "[ \\|\n]+" " ") - (replace-regexp-in-string " $" ""))) - -(defun inf-clojure--trim-newline-right (string) - "Trim newlines (only) in STRING." - (if (string-match "\n+\\'" string) - (replace-match "" t t string) - string)) +It also reduces redundant whitespace for readability and removes +comments." + (let* ((lines (seq-filter (lambda (s) (not (inf-clojure--whole-comment-line-p s))) + (split-string string "[\r\n]" t)))) + (mapconcat (lambda (s) + (if (not (string-match-p ";" s)) + (replace-regexp-in-string "\s+" " " s) + (concat s "\n"))) + lines " "))) (defun inf-clojure--sanitize-command (command) "Sanitize COMMAND for sending it to a process. An example of things that this function does is to add a final newline at the end of the form. Return an empty string if the sanitized command is empty." - (let* ((linified (inf-clojure--single-linify command)) - (sanitized (inf-clojure--trim-newline-right linified))) - (if (or (string-blank-p linified) (string-blank-p sanitized)) + (let ((sanitized (inf-clojure--make-single-line command))) + (if (string-blank-p sanitized) "" (concat sanitized "\n")))) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 6147dd3..09b224e 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -111,15 +111,23 @@ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) :to-equal "deref"))))) -(describe "inf-clojure--single-linify" +(describe "inf-clojure--make-single-line" (it "replaces newlines with whitespace" - (expect (inf-clojure--single-linify "(do\n(println \"hello world\")\n)") :to-equal "(do (println \"hello world\") )")) + (expect (inf-clojure--make-single-line "(do\n(println \"hello world\")\n)") :to-equal "(do (println \"hello world\") )")) (it "does not leave whitespace at the end" - (expect (inf-clojure--single-linify "(do\n(println \"hello world\")\n)\n\n") :to-equal "(do (println \"hello world\") )")) + (expect (inf-clojure--make-single-line "(do\n(println \"hello world\")\n)\n\n") :to-equal "(do (println \"hello world\") )")) - (it "returns empty string in case of only newline" - (expect (inf-clojure--single-linify "\n\n\n\n") :to-equal ""))) + (it "returns empty string when the line is only newlines" + (expect (inf-clojure--make-single-line "\n\n\n\n") :to-equal "")) + + (it "removes comments when on their own line" + (expect (inf-clojure--make-single-line "(do\n(println \"hello world\")\n ;; remove me\n)") :to-equal "(do (println \"hello world\") )")) + + (it "preserves newlines of inline comments" + (expect (inf-clojure--make-single-line "(do\n(println \"hello world\") ;; don't remove this\n)") :to-equal "(do (println \"hello world\") ;; don't remove this\n )")) + + ) (describe "inf-clojure--sanitize-command" (it "sanitizes the command correctly" From feca1cc392cef79118f0e757dae12c5012c744b0 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 23 Feb 2018 19:46:49 -0800 Subject: [PATCH 019/189] Send string even when empty I fixed it once why not fixing it twice, see #120. --- inf-clojure.el | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index de64f39..730cf86 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -341,9 +341,8 @@ the string for evaluation. Refer to `comint-simple-send` for customizations." (inf-clojure--set-repl-type proc) (let ((sanitized (inf-clojure--sanitize-command string))) - (when (not (string-empty-p sanitized)) - (inf-clojure--log-string sanitized "----CMD->") - (comint-simple-send proc sanitized)))) + (inf-clojure--log-string sanitized "----CMD->") + (comint-simple-send proc sanitized))) (defcustom inf-clojure-load-form "(clojure.core/load-file \"%s\")" "Format-string for building a Clojure expression to load a file. From 9deb1988832ec723fbd652a327325c4b9b285153 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 23 Feb 2018 21:38:29 -0800 Subject: [PATCH 020/189] Use comint-send-string This one is solving the weird duplicating prompt issue. After the sanitation patch we were sending newline twice. Using comint-send-string because it is more low-level and does not modify the input string, which we are building correctly already (hopefully). --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 730cf86..fbad183 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -342,7 +342,7 @@ customizations." (inf-clojure--set-repl-type proc) (let ((sanitized (inf-clojure--sanitize-command string))) (inf-clojure--log-string sanitized "----CMD->") - (comint-simple-send proc sanitized))) + (comint-send-string proc sanitized))) (defcustom inf-clojure-load-form "(clojure.core/load-file \"%s\")" "Format-string for building a Clojure expression to load a file. From 7ed4f442127fe628b3b10b455ef32a90cb6e7c55 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 2 Mar 2018 13:26:00 -0800 Subject: [PATCH 021/189] Remove emacs 24.3 and add 26 to Travis tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 57ec6dd..76b69fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,12 @@ before_install: - evm install $EVM_EMACS --use --skip - cask env: - - EVM_EMACS=emacs-24.3-travis - EVM_EMACS=emacs-24.4-travis - EVM_EMACS=emacs-24.5-travis - EVM_EMACS=emacs-25.1-travis - EVM_EMACS=emacs-25.2-travis - EVM_EMACS=emacs-25.3-travis + - EVM_EMACS=emacs-26-pretest-travis script: - emacs --version - cask install From b5e915c39989fc05f77abe30ce5ae030cfb7e906 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 2 Mar 2018 13:30:17 -0800 Subject: [PATCH 022/189] Travis test like in cider They know what they are doing. --- .travis.yml | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 76b69fd..540c29d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,28 @@ -language: generic +language: emacs-lisp sudo: false -before_install: +env: + matrix: + - EMACS_BINARY=emacs-24.4-travis MAKE_TEST=test + - EMACS_BINARY=emacs-24.4-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-24.5-travis MAKE_TEST=test + - EMACS_BINARY=emacs-24.5-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-25.1-travis MAKE_TEST=test + - EMACS_BINARY=emacs-25.1-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-25.2-travis MAKE_TEST=test + - EMACS_BINARY=emacs-25.2-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-25.3-travis MAKE_TEST=test + - EMACS_BINARY=emacs-25.3-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-25.3-travis MAKE_TEST=test-checks + - EMACS_BINARY=emacs-26-pretest-travis MAKE_TEST=test + - EMACS_BINARY=emacs-26-pretest-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-26-pretest-travis MAKE_TEST=test-checks + - EMACS_BINARY=emacs-git-snapshot-travis MAKE_TEST=test + - EMACS_BINARY=emacs-git-snapshot-travis MAKE_TEST=test-bytecomp + - EMACS_BINARY=emacs-git-snapshot-travis MAKE_TEST=test-checks +before_script: - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > x.sh && source ./x.sh - - evm install $EVM_EMACS --use --skip + - evm install $EMACS_BINARY --use --skip - cask -env: - - EVM_EMACS=emacs-24.4-travis - - EVM_EMACS=emacs-24.5-travis - - EVM_EMACS=emacs-25.1-travis - - EVM_EMACS=emacs-25.2-travis - - EVM_EMACS=emacs-25.3-travis - - EVM_EMACS=emacs-26-pretest-travis script: - emacs --version - cask install From da88c8ceda702d8b859956c76312ff4fa0a60c1d Mon Sep 17 00:00:00 2001 From: Austin Haas Date: Fri, 2 Mar 2018 14:08:39 -0800 Subject: [PATCH 023/189] Require seq library. Fixes https://github.com/clojure-emacs/inf-clojure/issues/141 --- inf-clojure.el | 1 + 1 file changed, 1 insertion(+) diff --git a/inf-clojure.el b/inf-clojure.el index fbad183..cc669b4 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -68,6 +68,7 @@ (require 'ansi-color) (require 'cl-lib) (require 'subr-x) +(require 'seq) (defgroup inf-clojure nil From 9b7747943cb68c740b7d516e93786940ba806145 Mon Sep 17 00:00:00 2001 From: Tianshu Shi Date: Mon, 5 Mar 2018 01:18:53 +0800 Subject: [PATCH 024/189] Set inf-clojure-tools-deps-cmd to "clojure" (#144) Fix https://github.com/clojure-emacs/inf-clojure/issues/134 --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index cc669b4..6dac275 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -230,7 +230,7 @@ often connecting to a remote REPL process." :safe #'inf-clojure--endpoint-p :package-version '(inf-clojure . "2.0.0")) -(defcustom inf-clojure-tools-deps-cmd "clj" +(defcustom inf-clojure-tools-deps-cmd "clojure" "The command used to start a Clojure REPL for tools.deps projects. Alternatively you can specify a TCP connection cons pair, instead From 3d723056cd1f4be121a87caf521f2673a177d6d9 Mon Sep 17 00:00:00 2001 From: Austin Haas Date: Mon, 5 Mar 2018 09:47:18 -0800 Subject: [PATCH 025/189] README: Add section describing how to start and connect to a socket server. --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 23fa630..ff702d8 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,19 @@ point. You can, however, change this behaviour by invoking such commands with a prefix argument. For instance: `C-u C-c C-v` will ask for the symbol you want to show the docstring for. +#### Starting and connecting to a socket server + +For Leiningen, add this to your ~/.lein/profiles.clj or your project.clj: +```:jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"]``` + +Then run `lein repl` from within your project directory, and `C-c M-c RET localhost RET 5555` from within Emacs. + +For boot, export the environment variable BOOT_JVM_OPTIONS: +```export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"'``` + +You can also start a socket server via the [Clojure CLI tools](https://clojure.org/guides/getting_started). +Configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). + #### Caveats Note that if you decide _NOT_ to use the socket repl, it is highly recommended From 7bf6f3d4a119e91beb39b091a61366cea1508cb0 Mon Sep 17 00:00:00 2001 From: Austin Haas Date: Mon, 5 Mar 2018 09:51:00 -0800 Subject: [PATCH 026/189] README: Improve formatting. --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ff702d8..00c9984 100644 --- a/README.md +++ b/README.md @@ -105,13 +105,17 @@ for the symbol you want to show the docstring for. #### Starting and connecting to a socket server -For Leiningen, add this to your ~/.lein/profiles.clj or your project.clj: -```:jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"]``` +For Leiningen, add the following option to your ~/.lein/profiles.clj or your project.clj: +``` +:jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"] +``` -Then run `lein repl` from within your project directory, and `C-c M-c RET localhost RET 5555` from within Emacs. +Then run `lein repl` from within your project directory to start the REPL, and `C-c M-c RET localhost RET 5555` from within Emacs to connect. For boot, export the environment variable BOOT_JVM_OPTIONS: -```export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"'``` +``` +export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"' +``` You can also start a socket server via the [Clojure CLI tools](https://clojure.org/guides/getting_started). Configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). From fcf30b5166dd4be6d6e7de96b5b2dce7c689d650 Mon Sep 17 00:00:00 2001 From: Austin Haas Date: Mon, 5 Mar 2018 10:22:38 -0800 Subject: [PATCH 027/189] README: Add instructions for including socket config in .dir-locals.el or .emacs. --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 00c9984..fa28360 100644 --- a/README.md +++ b/README.md @@ -110,12 +110,29 @@ For Leiningen, add the following option to your ~/.lein/profiles.clj or your pro :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 `C-c M-c RET localhost RET 5555` from within Emacs to connect. +Then run `lein repl` from within your project directory to start the +REPL, and `C-c M-c RET localhost RET 5555` from within Emacs to +connect, or add the following to your `.dir-locals.el` +``` +((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555))))) +``` +or the following to your `.emacs` +``` +(setf inf-clojure-lein-cmd '("localhost" . 5555)) +``` For boot, export the environment variable BOOT_JVM_OPTIONS: ``` export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"' ``` +or add the following to your `.dir-locals.el`: +``` +((nil . ((inf-clojure-boot-cmd . ("localhost" . 5555))))) +``` +or the following to your `.emacs` +``` +(setf inf-clojure-boot-cmd '("localhost" . 5555)) +``` You can also start a socket server via the [Clojure CLI tools](https://clojure.org/guides/getting_started). Configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). From 5aa9c155ccb8d68b025d639cf53c45ba779da32c Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 5 Mar 2018 10:57:26 -0800 Subject: [PATCH 028/189] Add clojure socket REPL command and tweak --- README.md | 58 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index fa28360..b00a7ee 100644 --- a/README.md +++ b/README.md @@ -103,39 +103,65 @@ point. You can, however, change this behaviour by invoking such commands with a prefix argument. For instance: `C-u C-c C-v` will ask for the symbol you want to show the docstring for. -#### Starting and connecting to a socket server +#### Starting and connecting to a socket REPL -For Leiningen, add the following option to your ~/.lein/profiles.clj or your project.clj: +If you have the new [Clojure CLI tools][] installed you can use the `clojure` command: + +_do not use `clj` because it adds readline support_ + +```shell +clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" ``` -:jvm-opts ["-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 +((nil . ((inf-clojure-tools-deps-cmd . ("localhost" . 5555))))) ``` -Then run `lein repl` from within your project directory to start the -REPL, and `C-c M-c RET localhost RET 5555` from within Emacs to -connect, or add the following to your `.dir-locals.el` +or the following to your [Emacs init file][]: + +```el +(setf inf-clojure-tools-deps-cmd '("localhost" . 5555)): ``` -((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555))))) + +For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `project.clj`: + +```clojure +:jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"] ``` -or the following to your `.emacs` + +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)) ``` -For boot, export the environment variable BOOT_JVM_OPTIONS: -``` +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` -``` + +or the following to your [Emacs init file][]: + +```el (setf inf-clojure-boot-cmd '("localhost" . 5555)) ``` -You can also start a socket server via the [Clojure CLI tools](https://clojure.org/guides/getting_started). -Configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). +The socket server REPL configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). #### Caveats @@ -320,3 +346,5 @@ Distributed under the GNU General Public License; type C-h C-c to vie [contributors]: https://github.com/clojure-emacs/inf-clojure/contributors [melpa]: http://melpa.org [melpa stable]: http://stable.melpa.org +[Emacs init file]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html +[Clojure cli tools]: https://clojure.org/guides/getting_started From e68108d2cc86aea8fb8062fd3fed40c804cd9147 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 5 Mar 2018 11:09:06 -0800 Subject: [PATCH 029/189] Make three sections for the socket REPLs --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b00a7ee..9e5d448 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ point. You can, however, change this behaviour by invoking such commands with a prefix argument. For instance: `C-u C-c C-v` will ask for the symbol you want to show the docstring for. -#### Starting and connecting to a socket REPL +#### Clojure cli socket REPL If you have the new [Clojure CLI tools][] installed you can use the `clojure` command: @@ -125,6 +125,8 @@ or the following to your [Emacs init file][]: (setf inf-clojure-tools-deps-cmd '("localhost" . 5555)): ``` +#### Leiningen socket REPL + For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `project.clj`: ```clojure @@ -143,6 +145,8 @@ or the following to your [Emacs init file][]: (setf inf-clojure-lein-cmd '("localhost" . 5555)) ``` +#### Boot socket REPL + For boot, export the environment variable `BOOT_JVM_OPTIONS`: ```shell From 1295e58e9f7fb575149a7b9b2604547c7331b4d5 Mon Sep 17 00:00:00 2001 From: Thibault Polge Date: Fri, 16 Mar 2018 19:40:42 +0100 Subject: [PATCH 030/189] [security] Don't execute arbitrary functions (#146) Marking values which validate functionp as "safe" meant that any file could potentially execute any code on the Emacs instance it's been opened on. This commit removes this possibility. --- inf-clojure.el | 1 - 1 file changed, 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 6dac275..ccd25ab 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1417,7 +1417,6 @@ 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 "^[] \"'`><,;|&{()[@\\^]" From b87c5fb0d4b9ed7df607a4abc7bd4f9cd7d044bf Mon Sep 17 00:00:00 2001 From: Priyatam Mudivarti Date: Thu, 22 Mar 2018 17:34:01 -0700 Subject: [PATCH 031/189] update instructions to setup lumo repl (#147) thanks @arichiardi! --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9e5d448..018ffe5 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Clojure(Script) development: * Support for Lumo * Support for Planck -For a more powerful/full-featured solution see [CIDER][]. +For a more powerful/full-featured solution see [CIDER](https://github.com/clojure-emacs/cider). ## Installation @@ -62,22 +62,26 @@ Add the following to your Emacs config to enable (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) ``` -**Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same -time. They have overlapping functionality and keybindings and the -result will be nothing short of havoc.** +**Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same time. They +have overlapping functionality and keybindings and the result will be nothing +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. +interacting with it. By defaul this will look for `lein` command on the path. + +For configuring other repls, read below. `inf-clojure` has several custom variables which control the command used to -start a REPL for particular project type - `inf-clojure-lein-cmd`, -`inf-clojure-boot-cmd`, `inf-clojure-tools-deps-cmd` and -`inf-clojure-generic-cmd`. The `inf-clojure-project-type` can force a -particular project type, skipping the project detection, which can be useful -for projects that don't have standard layouts. +start a REPL for particular project type - `inf-clojure-lein-cmd` (lein), +`inf-clojure-boot-cmd` (boot), `inf-clojure-tools-deps-cmd` (clj cli) and +`inf-clojure-generic-cmd` (lumo). + +The `inf-clojure-project-type` can force a particular project type, skipping the +project detection, which can be useful for projects that don't have standard +layouts. By default all those variables are set to strings (e.g. `lein repl`). However, it is possible to use a cons pair like `("localhost" . 5555)` @@ -167,6 +171,32 @@ or the following to your [Emacs init file][]: The socket server REPL configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). +#### Lumo Socket REPL + +For lumo, setup a generic command in `init.el` to start the socket repl (say, port 5555) + +```el +(setq inf-clojure-repl-use-same-window nil) +(setq inf-clojure-generic-cmd '("localhost" 5555)) +``` + +Then start lumo repl, like so: + +```bash +lumo -n 5555 +``` + +If you want to use lumo with Clojure devtools +[dependencies](https://clojure.org/guides/deps_and_cli) without lein or boot, +add a `deps.edn` in the project root and run this command: + +```bash +lumo -c `clj -Spath` -n 5555 +``` + +You can use `M-x inf-clojure-connect` (`C-c M-c`) to connect to a running +socket-repl. You will be prompted for host and port. + #### Caveats Note that if you decide _NOT_ to use the socket repl, it is highly recommended @@ -301,7 +331,7 @@ For example, you can use the following command (assuming `cp` contains the classpath) in your `.dir-locals.el`: ```el -((nil . (eval . (setq inf-clojure-boot-cmd (concat "lumo -d -c " +((nil . (eval . (setq inf-clojure-generic-cmd (concat "lumo -d -c " (f-read (concat (inf-clojure-project-root) "cp"))))))) ``` From b53074a1eeae9e21f6f99f4d5a96bb294c7ba79a Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Thu, 22 Mar 2018 17:56:42 -0700 Subject: [PATCH 032/189] Tweak README and discourage terminal REPLs --- README.md | 71 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 018ffe5..7ba910d 100644 --- a/README.md +++ b/README.md @@ -70,33 +70,32 @@ short of havoc.** 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. By defaul this will look for `lein` command on the path. +interacting with it. -For configuring other repls, read below. +Inf-clojure has several custom variables which control the command used to +start a REPL for a particular project type: -`inf-clojure` has several custom variables which control the command used to -start a REPL for particular project type - `inf-clojure-lein-cmd` (lein), -`inf-clojure-boot-cmd` (boot), `inf-clojure-tools-deps-cmd` (clj cli) and -`inf-clojure-generic-cmd` (lumo). + - `inf-clojure-lein-cmd` ([Leiningen][]) + - `inf-clojure-boot-cmd` ([Boot][]) + - `inf-clojure-tools-deps-cmd` ([Clojure cli tools][]) + - `inf-clojure-generic-cmd` -The `inf-clojure-project-type` can force a particular project type, skipping the -project detection, which can be useful for projects that don't have standard -layouts. +Detection is attempted +[in the above order](https://github.com/clojure-emacs/inf-clojure/blob/master/inf-clojure.el#L589-L596) +but the `inf-clojure-project-type` variable can force a particular project +type, useful for projects that don't have standard layouts. -By default all those variables are set to strings (e.g. `lein repl`). -However, it is possible to use a cons pair like `("localhost" . 5555)` -to connect to a socket REPL like the one provided -with [planck](http://planck-repl.org/), which can be started from the -command line with `planck -n 5555`. +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. -Use `C-u C-c C-z` to start a REPL with a different command/cons pair than -the default specified in `inf-clojure-program`. +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 use `M-x inf-clojure-connect` (`C-c M-c`) to connect to a running -socket-repl. You will be prompted for host and port. - -You can 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). +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). 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 @@ -173,30 +172,29 @@ The socket server REPL configuration options are described [here](https://dev.cl #### Lumo Socket REPL -For lumo, setup a generic command in `init.el` to start the socket repl (say, port 5555) +Lumo is decoupled from `inf-clojure-project-type` and therefore the command used depends on what you are using for dependency resolution. + +For example if a `project.clj` is present in the project root folder, `inf-clojure-lein-cmd` will be used. + +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 -(setq inf-clojure-repl-use-same-window nil) -(setq inf-clojure-generic-cmd '("localhost" 5555)) +((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555))))) ``` -Then start lumo repl, like so: +or the following to your [Emacs init file][]: -```bash -lumo -n 5555 +```el +(setf inf-clojure-lein-cmd '("localhost" . 5555)) ``` -If you want to use lumo with Clojure devtools -[dependencies](https://clojure.org/guides/deps_and_cli) without lein or boot, -add a `deps.edn` in the project root and run this command: +Project detection can be completely skipped and the `generic` project type can be used instead: -```bash -lumo -c `clj -Spath` -n 5555 +```el +(inf-clojure-project-type . "generic") +(setq inf-clojure-generic-cmd '("localhost" 5555)) ``` -You can use `M-x inf-clojure-connect` (`C-c M-c`) to connect to a running -socket-repl. You will be prompted for host and port. - #### Caveats Note that if you decide _NOT_ to use the socket repl, it is highly recommended @@ -332,7 +330,7 @@ the classpath) in your `.dir-locals.el`: ```el ((nil . (eval . (setq inf-clojure-generic-cmd (concat "lumo -d -c " - (f-read (concat (inf-clojure-project-root) "cp"))))))) + (f-read (concat (inf-clojure-project-root) "cp"))))))) ``` ## Troubleshooting @@ -382,3 +380,4 @@ Distributed under the GNU General Public License; type C-h C-c to vie [melpa stable]: http://stable.melpa.org [Emacs init file]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html [Clojure cli tools]: https://clojure.org/guides/getting_started +[Boot]: http://boot-clj.com From 69137983d368af0dc76cfa2e9e33338b796df5f4 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Thu, 22 Mar 2018 18:00:58 -0700 Subject: [PATCH 033/189] Fix small things in README again --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7ba910d..ef3011d 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ point. You can, however, change this behaviour by invoking such commands with a prefix argument. For instance: `C-u C-c C-v` will ask for the symbol you want to show the docstring for. -#### Clojure cli socket REPL +#### Clojure Command Line Socket REPL If you have the new [Clojure CLI tools][] installed you can use the `clojure` command: @@ -128,7 +128,7 @@ or the following to your [Emacs init file][]: (setf inf-clojure-tools-deps-cmd '("localhost" . 5555)): ``` -#### Leiningen socket REPL +#### Leiningen Socket REPL For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `project.clj`: @@ -148,7 +148,7 @@ or the following to your [Emacs init file][]: (setf inf-clojure-lein-cmd '("localhost" . 5555)) ``` -#### Boot socket REPL +#### Boot Socket REPL For boot, export the environment variable `BOOT_JVM_OPTIONS`: @@ -191,8 +191,8 @@ or the following to your [Emacs init file][]: Project detection can be completely skipped and the `generic` project type can be used instead: ```el -(inf-clojure-project-type . "generic") -(setq inf-clojure-generic-cmd '("localhost" 5555)) +(setf inf-clojure-project-type . "generic") +(setf inf-clojure-generic-cmd '("localhost" 5555)) ``` #### Caveats From 59868ff0433f7631c362ce25879bd4271d350ebc Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Mon, 2 Apr 2018 14:03:06 -0700 Subject: [PATCH 034/189] Remove quotes from reload and fix argument parsing (#148) The feature was kind of broken, this patch makes sure it actually works. --- inf-clojure.el | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index ccd25ab..a5c1a92 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -383,7 +383,7 @@ If you are using REPL types, it will pickup the most appropriate (`planck inf-clojure-load-form-planck) (_ inf-clojure-load-form))) -(defcustom inf-clojure-reload-form "(require '\"%s\" :reload)" +(defcustom inf-clojure-reload-form "(require '%s :reload)" "Format-string for building a Clojure expression to reload a file. Reload forces loading of all the identified libs even if they are already loaded. @@ -406,7 +406,7 @@ If you are using REPL types, it will pickup the most appropriate (inf-clojure--set-repl-type proc) inf-clojure-reload-form) -(defcustom inf-clojure-reload-all-form "(require '\"%s\" :reload-all)" +(defcustom inf-clojure-reload-all-form "(require '%s :reload-all)" "Format-string for building a Clojure expression to :reload-all a file. Reload-all implies :reload and also forces loading of all libs that the identified libs directly or indirectly load via require @@ -768,12 +768,12 @@ The prefix argument ARG can change the behavior of the command: - M-- C-u M-x `inf-clojure-reload': reloads all AND prompts." (interactive "P") (let* ((proc (inf-clojure-proc)) - (invertp (or (equal arg "-") (equal arg '(-4)))) - (promptp (or (equal arg '(4)) (equal arg '(-4)))) - (ns (if promptp + (reload-all-p (or (equal arg '-) (equal arg '(-4)))) + (prompt-p (or (equal arg '(4)) (equal arg '(-4)))) + (ns (if prompt-p (car (inf-clojure-symprompt "Namespace" (clojure-find-ns))) (clojure-find-ns))) - (form (if (not invertp) + (form (if (not reload-all-p) (inf-clojure-reload-form proc) (inf-clojure-reload-all-form proc)))) (inf-clojure--send-string proc (format form ns)))) From 010d859434bcc8d71e3dd911193ef683465a014f Mon Sep 17 00:00:00 2001 From: Laurent Charignon Date: Sat, 19 Jan 2019 11:23:13 -0800 Subject: [PATCH 035/189] Fix spelling issues (#156) --- inf-clojure.el | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index a5c1a92..6fe151e 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -815,7 +815,7 @@ The prefix argument ARG can change the behavior of the command: (defun inf-clojure-var-doc-form (proc) "Return the form to query the Inf-Clojure PROC for a var's documentation. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-var-doc-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -846,7 +846,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-var-source-form (proc) "Return the form to query the Inf-Clojure PROC for a var's source. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-var-source-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -889,7 +889,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-arglists-form (proc) "Return the form to query the Inf-Clojure PROC for arglists of a var. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-arglists-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -925,7 +925,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-completion-form (proc) "Return the form to query the Inf-Clojure PROC for completions. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-completion-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -956,7 +956,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-ns-vars-form (proc) "Return the form to query the Inf-Clojure PROC for public vars in a namespace. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-ns-vars-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -989,7 +989,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-set-ns-form (proc) "Return the form to set the namespace of the Inf-Clojure PROC. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-set-ns-form` variant." (pcase (inf-clojure--set-repl-type proc) (`planck inf-clojure-set-ns-form-planck) @@ -1023,7 +1023,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-apropos-form (proc) "Return the form to query the Inf-Clojure PROC for a var's apropos. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-apropos-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -1056,7 +1056,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-macroexpand-form (proc) "Return the form for macroexpansion in the Inf-Clojure PROC. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-macroexpand-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) @@ -1089,7 +1089,7 @@ If you are using REPL types, it will pickup the most approapriate (defun inf-clojure-macroexpand-1-form (proc) "Return the form for macroexpand-1 in the Inf-Clojure PROC. -If you are using REPL types, it will pickup the most approapriate +If you are using REPL types, it will pickup the most appropriate `inf-clojure-macroexpand-1-form` variant." (inf-clojure--sanitize-command (pcase (inf-clojure--set-repl-type proc) From cf53284774865ac9f0a562e9703e11ff45d23ae7 Mon Sep 17 00:00:00 2001 From: Austin Haas Date: Sat, 26 Jan 2019 10:33:08 -0800 Subject: [PATCH 036/189] Fix for https://github.com/clojure-emacs/inf-clojure/issues/154 (#158) [Fix #154] Use setq-local for comint-input-sender --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 6fe151e..e1cfa31 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -178,7 +178,7 @@ The following commands are available: \\{inf-clojure-minor-mode-map}" :lighter "" :keymap inf-clojure-minor-mode-map - (setq comint-input-sender 'inf-clojure--send-string) + (setq-local comint-input-sender 'inf-clojure--send-string) (inf-clojure-eldoc-setup) (make-local-variable 'completion-at-point-functions) (add-to-list 'completion-at-point-functions From b29a3f1c2a3050f1cb1dedf7d49a7f1b7b73d16c Mon Sep 17 00:00:00 2001 From: Daniel Compton Date: Thu, 28 Feb 2019 14:45:43 +1300 Subject: [PATCH 037/189] Use CircleCI for CI testing (#159) --- .circleci/config.yml | 37 +++++++++++++++++++++++++++++++++++++ .travis.yml | 29 ----------------------------- Makefile | 9 +++++++++ README.md | 4 +++- 4 files changed, 49 insertions(+), 30 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 .travis.yml create mode 100644 Makefile diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..0c22fca --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,37 @@ +version: 2.1 + +# Default actions to perform on each Emacs version +default: &default-steps + steps: + - checkout + - run: apt-get update && apt-get install make + - run: make elpa + - run: make test + +# Enumerated list of Emacs versions +jobs: + test-emacs-25: + docker: + - image: silex/emacs:25-dev + entrypoint: bash + <<: *default-steps + + test-emacs-26: + docker: + - image: silex/emacs:26-dev + entrypoint: bash + <<: *default-steps + + test-emacs-master: + docker: + - image: silex/emacs:master-dev + entrypoint: bash + <<: *default-steps + +workflows: + version: 2 + ci-test-matrix: + jobs: + - test-emacs-25 + - test-emacs-26 + - test-emacs-master diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 540c29d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: emacs-lisp -sudo: false -env: - matrix: - - EMACS_BINARY=emacs-24.4-travis MAKE_TEST=test - - EMACS_BINARY=emacs-24.4-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-24.5-travis MAKE_TEST=test - - EMACS_BINARY=emacs-24.5-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-25.1-travis MAKE_TEST=test - - EMACS_BINARY=emacs-25.1-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-25.2-travis MAKE_TEST=test - - EMACS_BINARY=emacs-25.2-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-25.3-travis MAKE_TEST=test - - EMACS_BINARY=emacs-25.3-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-25.3-travis MAKE_TEST=test-checks - - EMACS_BINARY=emacs-26-pretest-travis MAKE_TEST=test - - EMACS_BINARY=emacs-26-pretest-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-26-pretest-travis MAKE_TEST=test-checks - - EMACS_BINARY=emacs-git-snapshot-travis MAKE_TEST=test - - EMACS_BINARY=emacs-git-snapshot-travis MAKE_TEST=test-bytecomp - - EMACS_BINARY=emacs-git-snapshot-travis MAKE_TEST=test-checks -before_script: - - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > x.sh && source ./x.sh - - evm install $EMACS_BINARY --use --skip - - cask -script: - - emacs --version - - cask install - - cask exec buttercup -L . diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..34fa168 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +version: + emacs --version + +test : version + cask exec buttercup -L . + +elpa: + cask install + cask update diff --git a/README.md b/README.md index ef3011d..57b643e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![License GPL 3][badge-license]][copying] [![MELPA][melpa-badge]][melpa-package] [![MELPA Stable][melpa-stable-badge]][melpa-stable-package] +[![Circle CI][circle-ci-badge]][circleci] # inf-clojure @@ -372,7 +373,8 @@ Distributed under the GNU General Public License; type C-h C-c to vie [melpa-package]: http://melpa.org/#/inf-clojure [melpa-stable-package]: http://stable.melpa.org/#/inf-clojure [COPYING]: http://www.gnu.org/copyleft/gpl.html -[badge-travis]: https://travis-ci.org/clojure-emacs/inf-clojure.svg?branch=master +[circleci]: https://circleci.com/gh/clojure-emacs/inf-clojure +[circleci-badge]: https://circleci.com/gh/clojure-emacs/inf-clojure.svg?style=svg [CIDER]: https://github.com/clojure-emacs/cider [Leiningen]: http://leiningen.org [contributors]: https://github.com/clojure-emacs/inf-clojure/contributors From 975e58061aa9e8fa421630ffc9559bf20f0662fc Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Wed, 27 Feb 2019 17:51:54 -0800 Subject: [PATCH 038/189] Fix CircleCI badge in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57b643e..692f3a7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![License GPL 3][badge-license]][copying] [![MELPA][melpa-badge]][melpa-package] [![MELPA Stable][melpa-stable-badge]][melpa-stable-package] -[![Circle CI][circle-ci-badge]][circleci] +[![Circle CI][circleci-badge]][circleci] # inf-clojure From f3d6a6878c9b3bbf457c1756443afaa385921b14 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Fri, 22 Mar 2019 23:02:43 -0700 Subject: [PATCH 039/189] Add support for joker (#160) This patch introduces the defcustoms necessary for supporting joker. --- CHANGELOG.md | 1 + README.md | 20 +++++----- inf-clojure.el | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6701933..c1d3360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## master (unreleased) +* [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). * [#135](https://github.com/clojure-emacs/inf-clojure/pull/135): Improve command sanitation code. ## 2.1.0 (2018-01-02) diff --git a/README.md b/README.md index 692f3a7..3420f76 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,9 @@ Clojure(Script) development: * Macroexpansion * Require `:reload`/`:reload-all` * Support connecting to socket REPLs -* Support for Lumo -* Support for Planck +* Support for [Lumo](https://github.com/anmonteiro/lumo) +* Support for [Planck](http://planck-repl.org/) +* Support for [Joker](https://joker-lang.org/) For a more powerful/full-featured solution see [CIDER](https://github.com/clojure-emacs/cider). @@ -267,9 +268,9 @@ You can see all the configuration options available using the command An `inf-clojure` REPL can be of different types: Clojure, ClojureScript, Lumo and Planck are all potentially valid options. - At the moment, the default Clojure REPL, the Lumo REPL and the Planck REPL are -supported (standard ClojureScript is lacking mostly because some features -require to access the compiler state, +At the moment, the default Clojure REPL, the Lumo REPL, the Planck REPL and the +Joker REPL are supported (standard ClojureScript is lacking mostly because some +features require to access the compiler state, [cljs-tooling](https://github.com/clojure-emacs/cljs-tooling) is a good candidate for enabling support). @@ -311,10 +312,11 @@ 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 +the customary `inf-clojure-completion-form`, +`inf-clojure-completion-form-lumo`, `inf-clojure-completion-form-planck` and +`inf-clojure-completion-form-joker` - 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 diff --git a/inf-clojure.el b/inf-clojure.el index e1cfa31..84eac7d 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -48,6 +48,7 @@ ;; * Support connecting to socket REPLs ;; * Support for Lumo ;; * Support for Planck +;; * Support for Joker ;; ;; For a more powerful/full-featured solution see https://github.com/clojure-emacs/cider. ;; @@ -276,6 +277,16 @@ often connecting to a remote REPL process." :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +;;;; Joker +;;;; ==== + +(defcustom inf-clojure--joker-repl-form + "(find-ns 'joker.repl)" + "Form to invoke in order to verify that we launched a Planck REPL." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defvar-local inf-clojure-repl-type nil "Symbol to define your REPL type. Its root binding is nil and it can be further customized using @@ -292,6 +303,7 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte (cond ((inf-clojure--some-response-p proc inf-clojure--lumo-repl-form) 'lumo) ((inf-clojure--some-response-p proc inf-clojure--planck-repl-form) 'planck) + ((inf-clojure--some-response-p proc inf-clojure--joker-repl-form) 'joker) (t 'clojure))))) (defun inf-clojure--set-repl-type (proc) @@ -374,6 +386,15 @@ Clojure to load that file." :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-load-form-joker "(load-file \"%s\")" + "Joker format-string for building a Clojure expression to load a file. +This format string should use `%s' to substitute a file name and +should result in a Clojure form that will be sent to the inferior +Clojure to load that file." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-load-form (proc) "Return the form to query the Inf-Clojure PROC for var's documentation. If you are using REPL types, it will pickup the most appropriate @@ -381,6 +402,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-load-form-lumo) (`planck inf-clojure-load-form-planck) + (`joker inf-clojure-load-form-joker) (_ inf-clojure-load-form))) (defcustom inf-clojure-reload-form "(require '%s :reload)" @@ -813,6 +835,13 @@ The prefix argument ARG can change the behavior of the command: :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-var-doc-form-joker + "(joker.repl/doc %s)" + "Joker form to query inferior Clojure for a var's documentation." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-var-doc-form (proc) "Return the form to query the Inf-Clojure PROC for a var's documentation. If you are using REPL types, it will pickup the most appropriate @@ -821,6 +850,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-var-doc-form-lumo) (`planck inf-clojure-var-doc-form-planck) + (`joker inf-clojure-var-doc-form-joker) (_ inf-clojure-var-doc-form)))) (defcustom inf-clojure-var-source-form @@ -844,6 +874,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-var-source-form-joker + "" + "Joker form to query inferior Clojure for a var's source." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-var-source-form (proc) "Return the form to query the Inf-Clojure PROC for a var's source. If you are using REPL types, it will pickup the most appropriate @@ -852,6 +889,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-var-source-form-lumo) (`planck inf-clojure-var-source-form-planck) + (`joker inf-clojure-var-source-form-joker) (_ inf-clojure-var-source-form)))) (define-obsolete-variable-alias 'inf-clojure-var-source-command 'inf-clojure-var-source-form "2.0.0") @@ -887,6 +925,18 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.1.0")) +(defcustom inf-clojure-arglists-form-joker + "(try + (:arglists + (joker.core/meta + (joker.core/resolve + (joker.core/read-string \"%s\")))) + (catch Error _ nil))" + "Joker form to query inferior Clojure for a function's arglists." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-arglists-form (proc) "Return the form to query the Inf-Clojure PROC for arglists of a var. If you are using REPL types, it will pickup the most appropriate @@ -895,6 +945,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-arglists-form-lumo) (`planck inf-clojure-arglists-form-planck) + (`joker inf-clojure-arglists-form-joker) (_ inf-clojure-arglists-form)))) (defcustom inf-clojure-completion-form @@ -923,6 +974,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-completion-form-joker + "" + "Joker form to query inferior Clojure for completion candidates." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-completion-form (proc) "Return the form to query the Inf-Clojure PROC for completions. If you are using REPL types, it will pickup the most appropriate @@ -931,6 +989,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-completion-form-lumo) (`planck inf-clojure-completion-form-planck) + (`joker inf-clojure-completion-form-joker) (_ inf-clojure-completion-form)))) (defcustom inf-clojure-ns-vars-form @@ -954,6 +1013,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-ns-vars-form-joker + "" + "Joker form to show the public vars in a namespace." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-ns-vars-form (proc) "Return the form to query the Inf-Clojure PROC for public vars in a namespace. If you are using REPL types, it will pickup the most appropriate @@ -962,6 +1028,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-ns-vars-form-lumo) (`planck inf-clojure-ns-vars-form-planck) + (`joker inf-clojure-ns-vars-form-joker) (_ inf-clojure-ns-vars-form)))) (define-obsolete-variable-alias 'inf-clojure-ns-vars-command 'inf-clojure-ns-vars-form "2.0.0") @@ -987,6 +1054,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-set-ns-form-joker + "(in-ns '%s)" + "Joker form to set the namespace of the inferior Clojure process." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-set-ns-form (proc) "Return the form to set the namespace of the Inf-Clojure PROC. If you are using REPL types, it will pickup the most appropriate @@ -994,6 +1068,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`planck inf-clojure-set-ns-form-planck) (`lumo inf-clojure-set-ns-form-lumo) + (`joker inf-clojure-set-ns-form-joker) (_ inf-clojure-set-ns-form))) (define-obsolete-variable-alias 'inf-clojure-set-ns-command 'inf-clojure-set-ns-form "2.0.0") @@ -1021,6 +1096,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-apropos-form-joker + "" + "Joker form to invoke apropos." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-apropos-form (proc) "Return the form to query the Inf-Clojure PROC for a var's apropos. If you are using REPL types, it will pickup the most appropriate @@ -1029,6 +1111,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-apropos-form-lumo) (`planck inf-clojure-apropos-form-planck) + (`joker inf-clojure-apropos-form-joker) (_ inf-clojure-apropos-form)))) (define-obsolete-variable-alias 'inf-clojure-apropos-command 'inf-clojure-apropos-form "2.0.0") @@ -1054,6 +1137,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.2.0")) +(defcustom inf-clojure-macroexpand-form-joker + "(macroexpand '%s)" + "Joker form to invoke macroexpand." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-macroexpand-form (proc) "Return the form for macroexpansion in the Inf-Clojure PROC. If you are using REPL types, it will pickup the most appropriate @@ -1062,6 +1152,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-macroexpand-form-lumo) (`planck inf-clojure-macroexpand-form-planck) + (`joker inf-clojure-macroexpand-form-joker) (_ inf-clojure-macroexpand-form)))) (define-obsolete-variable-alias 'inf-clojure-macroexpand-command 'inf-clojure-macroexpand-form "2.0.0") @@ -1087,6 +1178,13 @@ If you are using REPL types, it will pickup the most appropriate :safe #'stringp :package-version '(inf-clojure . "2.2.0")) +(defcustom inf-clojure-macroexpand-1-form-joker + "(macroexpand-1 '%s)" + "Joker form to invoke macroexpand-1." + :type 'string + :safe #'stringp + :package-version '(inf-clojure . "2.2.0")) + (defun inf-clojure-macroexpand-1-form (proc) "Return the form for macroexpand-1 in the Inf-Clojure PROC. If you are using REPL types, it will pickup the most appropriate @@ -1095,6 +1193,7 @@ If you are using REPL types, it will pickup the most appropriate (pcase (inf-clojure--set-repl-type proc) (`lumo inf-clojure-macroexpand-1-form-lumo) (`planck inf-clojure-macroexpand-1-form-planck) + (`joker inf-clojure-macroexpand-1-form-joker) (_ inf-clojure-macroexpand-1-form)))) (define-obsolete-variable-alias 'inf-clojure-macroexpand-1-command 'inf-clojure-macroexpand-1-form "2.0.0") From 16455abd28933af7c7d6f22dd41414a3c3c66d63 Mon Sep 17 00:00:00 2001 From: Steve Ashton Date: Wed, 27 Mar 2019 12:08:52 -0400 Subject: [PATCH 040/189] Fix typo in inf-clojure--joker-repl-form (#163) --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 84eac7d..1403432 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -282,7 +282,7 @@ often connecting to a remote REPL process." (defcustom inf-clojure--joker-repl-form "(find-ns 'joker.repl)" - "Form to invoke in order to verify that we launched a Planck REPL." + "Form to invoke in order to verify that we launched a Joker REPL." :type 'string :safe #'stringp :package-version '(inf-clojure . "2.2.0")) From 0fc23509a1e66bcc3e694066f5067fdbd7b7961d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D0=B0?= =?UTF-8?q?=D1=80=20=D0=A1=D0=B8=D0=BC=D0=B8=D1=9B?= Date: Fri, 31 May 2019 11:30:00 +0100 Subject: [PATCH 041/189] Fix for eldoc-mode for ClojureCLR When using the REPL, whenever you'd type the function name, because Throwable is JVM specific, eldoc-mode would try to look up the function and when it wouldn't find it, it would bomb out with the complaint that Throwable wasn't defined. Which is to be expected since it's not running on JVM. Looking at the documentation https://docs.oracle.com/javase/10/docs/api/java/lang/Throwable.html "The Throwable class is the superclass of all errors and exceptions in the Java language." And in C#, Exception https://docs.microsoft.com/en-us/dotnet/api/system.exception?redirectedfrom=MSDN&view=netframework-4.8 "This class is the base class for all exceptions." --- CHANGELOG.md | 1 + inf-clojure.el | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1d3360..d28d305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## master (unreleased) +# [#164](https://github.com/clojure-emacs/inf-clojure/pull/164): Fix for eldoc-mode on ClojureCLR * [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). * [#135](https://github.com/clojure-emacs/inf-clojure/pull/135): Improve command sanitation code. diff --git a/inf-clojure.el b/inf-clojure.el index 1403432..47e1e6a 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -900,7 +900,7 @@ If you are using REPL types, it will pickup the most appropriate (clojure.core/meta (clojure.core/resolve (clojure.core/read-string \"%s\")))) - (catch Throwable t nil))" + (catch #?(:clj Throwable :cljr Exception) e nil))" "Form to query inferior Clojure for a function's arglists." :type 'string :safe #'stringp From d0d269dcfcc72611aff524a46eaa1eb4363c951f Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 8 Oct 2019 11:42:16 +0300 Subject: [PATCH 042/189] Tweak the changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d28d305..7ced329 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,15 @@ ## master (unreleased) -# [#164](https://github.com/clojure-emacs/inf-clojure/pull/164): Fix for eldoc-mode on ClojureCLR +### New features + * [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). + +### Bugs fixed + +* [#164](https://github.com/clojure-emacs/inf-clojure/pull/164): Fix for eldoc-mode on ClojureCLR. * [#135](https://github.com/clojure-emacs/inf-clojure/pull/135): Improve command sanitation code. +* Fix `info-clojure-apropos`. ## 2.1.0 (2018-01-02) From 98db4c8a38ee149171fa1bb65f2f246210302ed8 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 8 Oct 2019 11:42:53 +0300 Subject: [PATCH 043/189] Bump the copyright years --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 47e1e6a..20d25fa 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1,6 +1,6 @@ ;;; inf-clojure.el --- Run an external Clojure process in an Emacs buffer -*- lexical-binding: t; -*- -;; Copyright © 2014-2018 Bozhidar Batsov +;; Copyright © 2014-2019 Bozhidar Batsov ;; Authors: Bozhidar Batsov ;; Olin Shivers From 173d0e7f118b0009bf210be115485160abf554b1 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 8 Oct 2019 11:43:42 +0300 Subject: [PATCH 044/189] Bump the development version --- inf-clojure.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 20d25fa..d250d60 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 2.1.0 +;; Version: 2.2.0-snapshot ;; Package-Requires: ((emacs "24.4") (clojure-mode "5.6")) ;; This file is part of GNU Emacs. @@ -79,7 +79,7 @@ :link '(url-link :tag "GitHub" "https://github.com/clojure-emacs/inf-clojure") :link '(emacs-commentary-link :tag "Commentary" "inf-clojure")) -(defconst inf-clojure-version "2.1.0" +(defconst inf-clojure-version "2.2.0-snapshot" "The current version of `inf-clojure'.") (defcustom inf-clojure-prompt-read-only t From bd06d4fd6278013248533ed180ba3300ed69c0fb Mon Sep 17 00:00:00 2001 From: Andy Fingerhut Date: Sun, 5 Jan 2020 12:36:26 -0800 Subject: [PATCH 045/189] A few updates to links and formatting in README --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3420f76..269f92e 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,11 @@ start a REPL for a particular project type: - `inf-clojure-tools-deps-cmd` ([Clojure cli tools][]) - `inf-clojure-generic-cmd` -Detection is attempted -[in the above order](https://github.com/clojure-emacs/inf-clojure/blob/master/inf-clojure.el#L589-L596) -but the `inf-clojure-project-type` variable can force a particular project -type, useful for projects that don't have standard layouts. +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. 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 @@ -170,7 +171,7 @@ or the following to your [Emacs init file][]: (setf inf-clojure-boot-cmd '("localhost" . 5555)) ``` -The socket server REPL configuration options are described [here](https://dev.clojure.org/display/design/Socket+Server+REPL). +The socket server REPL configuration options are described [here](https://clojure.org/reference/repl_and_main#_launching_a_socket_server). #### Lumo Socket REPL @@ -243,7 +244,7 @@ Suppose you have three inferior Clojures running: If you do a `inf-clojure-eval-defun` command on some Clojure source code, what process do you send it to? -- If you're in a process buffer (foo, bar, or *inf-clojure*), +- If you're in a process buffer (foo, bar, or `*inf-clojure*`), you send it to that process. - If you're in some other buffer (e.g., a source file), you send it to the process attached to buffer `inf-clojure-buffer`. From 575538e27bf0109693c30afd1a0b5b5bd3eeba0c Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 6 Jan 2020 11:47:43 +0200 Subject: [PATCH 046/189] Create FUNDING.yml --- .github/FUNDING.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7c87286 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +github: bbatsov +patreon: bbatsov +custom: https://www.paypal.me/bbatsov From 49390d9dfde1d6354629b7662edd0ee422477f4a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 18 Jan 2020 17:33:23 +0200 Subject: [PATCH 047/189] Bump the copyright years --- README.md | 2 +- inf-clojure.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 269f92e..53d68b1 100644 --- a/README.md +++ b/README.md @@ -366,7 +366,7 @@ This creates `.inf-clojure.log` in the project directory so that you can `tail - ## License -Copyright © 2014-2018 Bozhidar Batsov and [contributors][]. +Copyright © 2014-2020 Bozhidar Batsov and [contributors][]. Distributed under the GNU General Public License; type C-h C-c to view it. diff --git a/inf-clojure.el b/inf-clojure.el index d250d60..dd26d25 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1,6 +1,6 @@ ;;; inf-clojure.el --- Run an external Clojure process in an Emacs buffer -*- lexical-binding: t; -*- -;; Copyright © 2014-2019 Bozhidar Batsov +;; Copyright © 2014-2020 Bozhidar Batsov ;; Authors: Bozhidar Batsov ;; Olin Shivers From a61dd84dfb83b6c2b0100c77a4b80226ecfbeeb3 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sun, 12 Apr 2020 12:15:47 -0500 Subject: [PATCH 048/189] Insert top level defun into repl Nice interaction to see the form and then the output. --- inf-clojure.el | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index dd26d25..740deb2 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -135,6 +135,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (define-key map "\C-c\C-r" #'inf-clojure-eval-region) (define-key map "\C-c\M-r" #'inf-clojure-reload) (define-key map "\C-c\C-n" #'inf-clojure-eval-form-and-next) + (define-key map (kbd "C-c C-j") #'inf-clojure-insert-defun) (define-key map "\C-c\C-z" #'inf-clojure-switch-to-repl) (define-key map "\C-c\C-i" #'inf-clojure-show-ns-vars) (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) @@ -682,15 +683,25 @@ Prefix argument AND-GO means switch to the Clojure buffer afterwards." "Send the string CODE to the inferior Clojure process to be executed." (inf-clojure--send-string (inf-clojure-proc) code)) +(defun inf-clojure--defun-at-point (&optional bounds) + "Return text or range of defun at point. +If BOUNDS is truthy return a dotted pair of beginning and end of +current defun else return the string.." + (save-excursion + (end-of-defun) + (let ((end (point)) + (case-fold-search t) + (func (if bounds #'cons #'buffer-substring-no-properties))) + (beginning-of-defun) + (funcall func (point) end)))) + (defun inf-clojure-eval-defun (&optional and-go) "Send the current defun to the inferior Clojure process. Prefix argument AND-GO means switch to the Clojure buffer afterwards." (interactive "P") (save-excursion - (end-of-defun) - (let ((end (point)) (case-fold-search t)) - (beginning-of-defun) - (inf-clojure-eval-region (point) end and-go)))) + (let ((bounds (inf-clojure--defun-at-point t))) + (inf-clojure-eval-region (car bounds) (cdr bounds) and-go)))) (defun inf-clojure-eval-buffer (&optional and-go) "Send the current buffer to the inferior Clojure process. @@ -731,6 +742,24 @@ With prefix argument EOB-P, positions cursor at end of buffer." (push-mark) (goto-char (point-max)))) +(defun inf-clojure-insert-and-eval (form) + "Insert FORM into process and evaluate. +Indent FORM. FORM is expected to have been trimmed." + (let ((clojure-process (inf-clojure-proc))) + (with-current-buffer (process-buffer clojure-process) + (comint-goto-process-mark) + (let ((beginning (point))) + (insert (format "%s" form)) + (let ((end (point))) + (goto-char beginning) + (indent-sexp end))) + (comint-send-input t)))) + +(defun inf-clojure-insert-defun () + "Send current defun to process." + (interactive) + (inf-clojure-insert-and-eval (string-trim (inf-clojure--defun-at-point)))) + ;;; Now that inf-clojure-eval-/defun/region takes an optional prefix arg, ;;; these commands are redundant. But they are kept around for the user From 0697d6f361e8d834e6f10c361eb4ab4722eefeed Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sun, 12 Apr 2020 12:55:19 -0500 Subject: [PATCH 049/189] Add insert last sexp and keymap to hold them all --- inf-clojure.el | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 740deb2..8aafb3a 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -125,6 +125,14 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword ["Version" inf-clojure-display-version])) map)) +(defvar inf-clojure-insert-commands-map + (let ((map (define-prefix-command 'inf-clojure-insert-commands-map))) + (define-key map (kbd "d") #'inf-clojure-insert-defun) + (define-key map (kbd "C-d") #'inf-clojure-insert-defun) + (define-key map (kbd "e") #'inf-clojure-insert-last-sexp) + (define-key map (kbd "C-e") #'inf-clojure-insert-last-sexp) + map)) + (defvar inf-clojure-minor-mode-map (let ((map (make-sparse-keymap))) (define-key map "\M-\C-x" #'inf-clojure-eval-defun) ; Gnu convention @@ -135,7 +143,7 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (define-key map "\C-c\C-r" #'inf-clojure-eval-region) (define-key map "\C-c\M-r" #'inf-clojure-reload) (define-key map "\C-c\C-n" #'inf-clojure-eval-form-and-next) - (define-key map (kbd "C-c C-j") #'inf-clojure-insert-defun) + (define-key map (kbd "C-c C-j") 'inf-clojure-insert-commands-map) (define-key map "\C-c\C-z" #'inf-clojure-switch-to-repl) (define-key map "\C-c\C-i" #'inf-clojure-show-ns-vars) (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) @@ -760,6 +768,13 @@ Indent FORM. FORM is expected to have been trimmed." (interactive) (inf-clojure-insert-and-eval (string-trim (inf-clojure--defun-at-point)))) +(defun inf-clojure-insert-last-sexp () + "Send last sexp to process." + (interactive) + (inf-clojure-insert-and-eval + (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) + (point)))) + ;;; Now that inf-clojure-eval-/defun/region takes an optional prefix arg, ;;; these commands are redundant. But they are kept around for the user From eb5e6a286e664afdf2667b0d087457ffaf8ccdd2 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sun, 12 Apr 2020 12:56:33 -0500 Subject: [PATCH 050/189] Remove whitespace --- inf-clojure.el | 1 - 1 file changed, 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 8aafb3a..35df4ae 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -775,7 +775,6 @@ Indent FORM. FORM is expected to have been trimmed." (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point)))) - ;;; Now that inf-clojure-eval-/defun/region takes an optional prefix arg, ;;; these commands are redundant. But they are kept around for the user ;;; to bind if he wishes, for backwards functionality, and because it's From 2445af755c89d4fb04c32105d99c97d0d68460a1 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sun, 12 Apr 2020 13:01:50 -0500 Subject: [PATCH 051/189] Add insert commands to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ced329..d02ddc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### New features +* [#170](https://github.com/clojure-emacs/inf-clojure/pull/170): Add insert defun and last sexp commands * [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). ### Bugs fixed From ff72d667c2709166d19ac15a36f7aac3423cefa1 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 15 Apr 2020 07:45:48 +0300 Subject: [PATCH 052/189] [Fix #171] Release 2.2.0 --- CHANGELOG.md | 4 +++- inf-clojure.el | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d02ddc2..ffe24b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ## master (unreleased) +## 2.2.0 (2020-04-15) + ### New features -* [#170](https://github.com/clojure-emacs/inf-clojure/pull/170): Add insert defun and last sexp commands +* [#170](https://github.com/clojure-emacs/inf-clojure/pull/170): Add insert defun and last sexp commands. * [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). ### Bugs fixed diff --git a/inf-clojure.el b/inf-clojure.el index 35df4ae..5e2962f 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,8 +6,8 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 2.2.0-snapshot -;; Package-Requires: ((emacs "24.4") (clojure-mode "5.6")) +;; Version: 2.2.0 +;; Package-Requires: ((emacs "24.4") (clojure-mode "5.11")) ;; This file is part of GNU Emacs. @@ -79,7 +79,9 @@ :link '(url-link :tag "GitHub" "https://github.com/clojure-emacs/inf-clojure") :link '(emacs-commentary-link :tag "Commentary" "inf-clojure")) -(defconst inf-clojure-version "2.2.0-snapshot" +(defconst inf-clojure-version + (eval-when-compile + (lm-version (or load-file-name buffer-file-name))) "The current version of `inf-clojure'.") (defcustom inf-clojure-prompt-read-only t From 1e93db8909d21a08170958adf49e8db23f3c6290 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 15 Apr 2020 09:15:01 +0300 Subject: [PATCH 053/189] Bump the development version --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 5e2962f..76122b7 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 2.2.0 +;; Version: 2.3.0-snapshot ;; Package-Requires: ((emacs "24.4") (clojure-mode "5.11")) ;; This file is part of GNU Emacs. From 7a5b32ff8cc24955112b7baabdf8e845c518e26c Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 15 Apr 2020 09:27:07 +0300 Subject: [PATCH 054/189] Extend a bit the README --- README.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 53d68b1..5be7426 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,27 @@ Clojure(Script) development: * Macroexpansion * Require `:reload`/`:reload-all` * Support connecting to socket REPLs -* Support for [Lumo](https://github.com/anmonteiro/lumo) -* Support for [Planck](http://planck-repl.org/) -* Support for [Joker](https://joker-lang.org/) + +In addition to the standard Clojure and ClojureScript REPLs, `inf-clojure` supports also: + +* [Lumo](https://github.com/anmonteiro/lumo) +* [Planck](http://planck-repl.org/) +* [Joker](https://joker-lang.org/) For a more powerful/full-featured solution see [CIDER](https://github.com/clojure-emacs/cider). +## Rationale + +`inf-clojure`'s goal is to provide the simplest possible way to interact with a Clojure REPL. +In Emacs terminology "inferior" process is a subprocess started by Emacs (it being the "superior" process, of course). + +`inf-clojure` doesn't require much of setup, as at its core it simply runs a terminal REPL process, pipes input to it, and +processes its output. As the Clojure socket REPL works in exactly the same manner `inf-clojure` can also interact with it. + +Functionality like code completion and eldoc is powered by evaluation of predefined code snippets that provide the necessary results. +As different Clojure REPLs have different capabilities, `inf-clojure` has to determine the type of a REPL and invoke +the right code for each REPL type. + ## Installation Available on all major `package.el` community maintained repos - From 2cfc38fa409718e150dcdc9278e23aa8dcb4e531 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Mon, 13 Apr 2020 08:28:10 -0500 Subject: [PATCH 055/189] Move repl features into single datastructure for clarity want to make the logic of inf-clojure clear and open. No more case statements Clojure, joker, and planck implementations Loop over them during startup and offer those forms as the way to startup. --- inf-clojure.el | 825 ++++++++++++++++--------------------------------- todo.org | 58 ++++ 2 files changed, 317 insertions(+), 566 deletions(-) create mode 100644 todo.org diff --git a/inf-clojure.el b/inf-clojure.el index 76122b7..1545e14 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -71,7 +71,201 @@ (require 'subr-x) (require 'seq) - +(defvar inf-clojure-implementations (make-hash-table :size 6)) +(defvar inf-clojure-recognize-alist '()) +(defvar inf-clojure-startup-forms '()) + +(defun inf-clojure-register-implementation + (repl-type implementation &optional recognize default-startup) + "Register a REPL-TYPE for `inf-clojure'. +REPL-TYPE is a symbol of the repl type (lumo, planck, etc) + +IMPLEMENTATION is a function from feature-symbol to format +string. For instance, (implementation 'doc) > (cljs.repl/doc +\"%s\"). The full list of feature symbols is: load, doc, source, +arglists, apropos, ns-vars, set-ns, macroexpand, macroexpand-1, +and completion. + +RECOGNIZE is a namespace that, if present, will indicate that the +currently connected repl is a repl of this type. + +DEFAULT-STARTUP is a command to start a repl of this type from +the repl" + (puthash repl-type implementation inf-clojure-implementations) + (when recognize + (add-to-list 'inf-clojure-recognize-alist (cons repl-type recognize))) + (when default-startup + (add-to-list 'inf-clojure-startup-forms (cons repl-type default-startup)))) + +(defun inf-clojure-cljs-features-dispatch (feature) + (case feature + ;; ((load) "(cljs.core/load-file \"%s\")") + ((doc) "(cljs.repl/doc %s)") + ((source) "(cljs.repl/source %s)") + ((arglists) "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") + ((apropos) "(cljs.repl/apropos \"%s\")") + ((ns-vars) "(cljs.repl/dir %s)") + ((set-ns) "(in-ns '%s)") + ((macroexpand) "(cljs.core/macroexpand '%s)") + ((macroexpand-1) "(cljs.core/macroexpand-1 '%s)") + ;; ((completion) inf-clojure-completion-form-lumo) + )) + +(inf-clojure-register-implementation + 'cljs #'inf-clojure-cljs-features-dispatch "cljs.repl" "clojure -m cljs.main -r") + +(defun inf-clojure-lumo-features-dispatch (feature) + (case feature + ((load) "(clojure.core/load-file \"%s\")") + ((doc) "(lumo.repl/doc %s)") + ((source) "(lumo.repl/source %s)") + ((arglists) + "(let [old-value lumo.repl/*pprint-results*] + (set! lumo.repl/*pprint-results* false) + (js/setTimeout #(set! lumo.repl/*pprint-results* old-value) 0) + (lumo.repl/get-arglists \"%s\"))") + ((apropos) "(lumo.repl/apropos \"%s\")") + ((ns-vars) "(lumo.repl/dir %s)") + ((set-ns) "(in-ns '%s)") + ((macroexpand) "(macroexpand-1 '%s)") + ((macroexpand-1) "(macroexpand-1 '%s)") + ((completion) + "(let [ret (atom nil)] + (lumo.repl/get-completions \"%s\" (fn [res] (reset! ret (map str res)))) + @ret)")) ) + +(inf-clojure-register-implementation + 'lumo #'inf-clojure-lumo-features-dispatch "lumo.repl" "lumo") + +(defun inf-clojure-planck-features-dispatch (feature) + (case feature + ((load) "(load-file \"%s\")") + ((doc) "(planck.repl/doc %s)") + ((source) "(planck.repl/source %s)") + ((arglists) "(planck.repl/get-arglists \"%s\")") + ((apropos) "(doseq [var (sort (planck.repl/apropos \"%s\"))] (println (str var)))") + ((ns-vars) "(planck.repl/dir %s)") + ((set-ns) "(in-ns '%s)") + ((macroexpand) "(macroexpand '%s)") + ((macroexpand-1) "(macroexpand-1 '%s)") + ;; ((completion) inf-clojure-completion-form-planck ) + )) + +(inf-clojure-register-implementation + 'planck #'inf-clojure-planck-features-dispatch "planck.repl" "planck") + +(defun inf-clojure-joker-features-dispatch (feature) + (case feature + ((load) "(load-file \"%s\")") + ((doc) "(joker.repl/doc %s)") + ;; ((source) "") + ((arglists) + "(try + (:arglists + (joker.core/meta + (joker.core/resolve + (joker.core/read-string \"%s\")))) + (catch Error _ nil))") + ;; ((apropos) "") + ;; ((ns-vars) "") + ((set-ns) "(in-ns '%s)") + ((macroexpand) "(macroexpand '%s)") + ((macroexpand-1) "(macroexpand-1 '%s)") + ;; ((completion) "") + )) + +(inf-clojure-register-implementation + 'joker #'inf-clojure-joker-features-dispatch "joker.repl" "joker") + +(defun inf-clojure-clojure-features-dispatch (feature) + (case feature + ((load) "(clojure.core/load-file \"%s\")") + ((doc) "(clojure.repl/doc %s)") + ((source) "(clojure.repl/source %s)") + ((arglists) + "(try + (:arglists + (clojure.core/meta + (clojure.core/resolve + (clojure.core/read-string \"%s\")))) +(catch #?(:clj Throwable :cljr Exception) e nil))") + ((apropos) "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))") + ((ns-vars) "(clojure.repl/dir %s)") + ((set-ns) "(clojure.core/in-ns '%s)") + ((macroexpand) "(clojure.core/macroexpand '%s)") + ((macroexpand-1) "(clojure.core/macroexpand-1 '%s)") + ;; ((completion) nil) + )) + +(inf-clojure-register-implementation + 'clojure #'inf-clojure-clojure-features-dispatch "clojure.core.server" "clojure") + +(defun inf-clojure-proc (&optional no-error) + "Return the current inferior Clojure process. +When NO-ERROR is non-nil, don't throw an error when no connection +has been found. See also variable `inf-clojure-buffer'." + (or (get-buffer-process (if (derived-mode-p 'inf-clojure-mode) + (current-buffer) + inf-clojure-buffer)) + (unless no-error + (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) + +(defvar-local inf-clojure-repl-type nil + "Symbol to define your REPL type. +Its root binding is nil and it can be further customized using +either `setq-local` or an entry in `.dir-locals.el`." ) + +(defvar inf-clojure--repl-type-lock nil + "Global lock for protecting against proc filter race conditions. +See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filter.html") + +(defun inf-clojure--detect-repl-type (proc) + "Identifies the current REPL type for PROC." + (when (not inf-clojure--repl-type-lock) + (let ((inf-clojure--repl-type-lock t)) + (or (seq-some (lambda (r) + (when (inf-clojure--some-response-p + proc (format "(find-ns '%s)" (cdr r))) + (car r))) + inf-clojure-recognize-alist) + 'clojure)))) + +(defun inf-clojure-set-repl-type () + "Set the REPL type to one of the available implementations." + (interactive) + (let* ((proc (inf-clojure-proc)) + (types (hash-table-keys inf-clojure-implementations)) + (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 + (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)) + +(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) + inf-clojure-repl-type) + (error "Repl type is not known"))) + (implementation (gethash repl-type inf-clojure-implementations)) + (feature-form (and implementation (funcall implementation feature)))) + (cond (feature-form feature-form) + (no-error nil) + (t (error "%s not configured for %s" feature repl-type))))) + (defgroup inf-clojure nil "Run an external Clojure process (REPL) in an Emacs buffer." :prefix "inf-clojure-" @@ -227,8 +421,6 @@ often connecting to a remote REPL process." :safe #'inf-clojure--endpoint-p :package-version '(inf-clojure . "2.0.0")) -(define-obsolete-variable-alias 'inf-clojure-program 'inf-clojure-lein-cmd "2.0.0") - (defcustom inf-clojure-boot-cmd "boot repl -C" "The command used to start a Clojure REPL for Boot projects. @@ -268,69 +460,8 @@ often connecting to a remote REPL process." :safe #'inf-clojure--endpoint-p :package-version '(inf-clojure . "2.0.0")) -;;;; Lumo -;;;; ==== - -(defcustom inf-clojure--lumo-repl-form - "(find-ns 'lumo.repl)" - "Form to invoke in order to verify that we launched a Lumo REPL." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -;;;; Planck -;;;; ==== - -(defcustom inf-clojure--planck-repl-form - "(find-ns 'planck.repl)" - "Form to invoke in order to verify that we launched a Planck REPL." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -;;;; Joker -;;;; ==== - -(defcustom inf-clojure--joker-repl-form - "(find-ns 'joker.repl)" - "Form to invoke in order to verify that we launched a Joker REPL." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defvar-local inf-clojure-repl-type nil - "Symbol to define your REPL type. -Its root binding is nil and it can be further customized using -either `setq-local` or an entry in `.dir-locals.el`." ) - -(defvar inf-clojure--repl-type-lock nil - "Global lock for protecting against proc filter race conditions. -See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filter.html") - -(defun inf-clojure--detect-repl-type (proc) - "Identifies the current REPL type for PROC." - (when (not inf-clojure--repl-type-lock) - (let ((inf-clojure--repl-type-lock t)) - (cond - ((inf-clojure--some-response-p proc inf-clojure--lumo-repl-form) 'lumo) - ((inf-clojure--some-response-p proc inf-clojure--planck-repl-form) 'planck) - ((inf-clojure--some-response-p proc inf-clojure--joker-repl-form) 'joker) - (t 'clojure))))) - -(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 - (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)) - (defun inf-clojure--whole-comment-line-p (string) - "Return true iff STRING is a whole line semicolon comment." + "Return non-nil iff STRING is a whole line semicolon comment." (string-match-p "^\s*;" string)) (defun inf-clojure--make-single-line (string) @@ -368,54 +499,6 @@ customizations." (inf-clojure--log-string sanitized "----CMD->") (comint-send-string proc sanitized))) -(defcustom inf-clojure-load-form "(clojure.core/load-file \"%s\")" - "Format-string for building a Clojure expression to load a file. -This format string should use `%s' to substitute a file name and -should result in a Clojure form that will be sent to the inferior -Clojure to load that file." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(define-obsolete-variable-alias 'inf-clojure-load-command 'inf-clojure-load-form "2.0.0") - -(defcustom inf-clojure-load-form-lumo "(clojure.core/load-file \"%s\")" - "Lumo format-string for building a Clojure expression to load a file. -This format string should use `%s' to substitute a file name and -should result in a Clojure form that will be sent to the inferior -Clojure to load that file." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-load-form-planck "(load-file \"%s\")" - "Planck format-string for building a Clojure expression to load a file. -This format string should use `%s' to substitute a file name and -should result in a Clojure form that will be sent to the inferior -Clojure to load that file." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-load-form-joker "(load-file \"%s\")" - "Joker format-string for building a Clojure expression to load a file. -This format string should use `%s' to substitute a file name and -should result in a Clojure form that will be sent to the inferior -Clojure to load that file." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-load-form (proc) - "Return the form to query the Inf-Clojure PROC for var's documentation. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-var-doc-form` variant." - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-load-form-lumo) - (`planck inf-clojure-load-form-planck) - (`joker inf-clojure-load-form-joker) - (_ inf-clojure-load-form))) - (defcustom inf-clojure-reload-form "(require '%s :reload)" "Format-string for building a Clojure expression to reload a file. Reload forces loading of all the identified libs even if they are @@ -652,9 +735,10 @@ it (default is value of `inf-clojure-*-cmd'). Runs the hooks from `inf-clojure-mode-hook' (after the `comint-mode-hook' is run). \(Type \\[describe-mode] in the process buffer for a list of commands.)" - (interactive (list (if current-prefix-arg - (read-string "Run Clojure: " (inf-clojure-cmd (inf-clojure-project-type))) - (inf-clojure-cmd (inf-clojure-project-type))))) + (interactive (list (completing-read "Clojure startup command: " + (mapcar #'cdr inf-clojure-startup-forms) + nil + 'confirm-after-completion))) (if (not (comint-check-proc "*inf-clojure*")) ;; run the new process in the project's root when in a project folder (let ((default-directory (inf-clojure-project-root)) @@ -680,7 +764,8 @@ HOST is the host the process is running on, PORT is where it's listening." (defun inf-clojure-eval-region (start end &optional and-go) "Send the current region to the inferior Clojure process. -Prefix argument AND-GO means switch to the Clojure buffer afterwards." +Sends substring between START and END. Prefix argument AND-GO +means switch to the Clojure buffer afterwards." (interactive "r\nP") ;; drops newlines at the end of the region (let ((str (replace-regexp-in-string @@ -783,7 +868,8 @@ Indent FORM. FORM is expected to have been trimmed." ;;; easier to type C-c e than C-u C-c C-e. (defun inf-clojure-eval-region-and-go (start end) - "Send the current region to the inferior Clojure, and switch to its buffer." + "Send the current region to the inferior Clojure, and switch to its buffer. +START and END are the beginning and end positions in the buffer to send." (interactive "r") (inf-clojure-eval-region start end t)) @@ -811,15 +897,16 @@ The prefix argument SWITCH-TO-REPL controls whether to switch to REPL after the file is loaded or not. If the argument FILE-NAME is present it will be used instead of the current file." (interactive "P") - (let ((proc (inf-clojure-proc)) - (file-name (or file-name - (car (comint-get-source "Load Clojure file: " inf-clojure-prev-l/c-dir/file - ;; nil because doesn't need an exact name - inf-clojure-source-modes nil))))) + (let* ((proc (inf-clojure-proc)) + (file-name (or file-name + (car (comint-get-source "Load Clojure file: " inf-clojure-prev-l/c-dir/file + ;; nil because doesn't need an exact name + inf-clojure-source-modes nil)))) + (load-form (inf-clojure-get-feature proc 'load))) (comint-check-source file-name) ; Check to see if buffer needs saved. (setq inf-clojure-prev-l/c-dir/file (cons (file-name-directory file-name) (file-name-nondirectory file-name))) - (inf-clojure--send-string proc (format (inf-clojure-load-form proc) file-name)) + (inf-clojure--send-string proc (format load-form file-name)) (when switch-to-repl (inf-clojure-switch-to-repl t)))) @@ -850,398 +937,6 @@ The prefix argument ARG can change the behavior of the command: (not (null inf-clojure-buffer))) -;;; Documentation functions: function doc, var doc, arglists, and -;;; describe symbol. -;;; =========================================================================== - -;;; Command forms -;;; ============= - -(defcustom inf-clojure-var-doc-form - "(clojure.repl/doc %s)" - "Form to query inferior Clojure for a var's documentation." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(define-obsolete-variable-alias 'inf-clojure-var-doc-command 'inf-clojure-var-doc-form "2.0.0") - -(defcustom inf-clojure-var-doc-form-lumo - "(lumo.repl/doc %s)" - "Lumo form to query inferior Clojure for a var's documentation." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-var-doc-form-planck - "(planck.repl/doc %s)" - "Planck form to query inferior Clojure for a var's documentation." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-var-doc-form-joker - "(joker.repl/doc %s)" - "Joker form to query inferior Clojure for a var's documentation." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-var-doc-form (proc) - "Return the form to query the Inf-Clojure PROC for a var's documentation. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-var-doc-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-var-doc-form-lumo) - (`planck inf-clojure-var-doc-form-planck) - (`joker inf-clojure-var-doc-form-joker) - (_ inf-clojure-var-doc-form)))) - -(defcustom inf-clojure-var-source-form - "(clojure.repl/source %s)" - "Form to query inferior Clojure for a var's source." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-var-source-form-planck - "(planck.repl/source %s)" - "Planck form to query inferior Clojure for a var's source." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-var-source-form-lumo - "(lumo.repl/source %s)" - "Lumo form to query inferior Clojure for a var's source." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-var-source-form-joker - "" - "Joker form to query inferior Clojure for a var's source." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-var-source-form (proc) - "Return the form to query the Inf-Clojure PROC for a var's source. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-var-source-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-var-source-form-lumo) - (`planck inf-clojure-var-source-form-planck) - (`joker inf-clojure-var-source-form-joker) - (_ inf-clojure-var-source-form)))) - -(define-obsolete-variable-alias 'inf-clojure-var-source-command 'inf-clojure-var-source-form "2.0.0") - -(defcustom inf-clojure-arglists-form - "(try - (:arglists - (clojure.core/meta - (clojure.core/resolve - (clojure.core/read-string \"%s\")))) - (catch #?(:clj Throwable :cljr Exception) e nil))" - "Form to query inferior Clojure for a function's arglists." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(define-obsolete-variable-alias 'inf-clojure-arglist-command 'inf-clojure-arglists-form "2.0.0") - -(defcustom inf-clojure-arglists-form-lumo - "(let [old-value lumo.repl/*pprint-results*] - (set! lumo.repl/*pprint-results* false) - (js/setTimeout #(set! lumo.repl/*pprint-results* old-value) 0) - (lumo.repl/get-arglists \"%s\"))" - "Lumo form to query inferior Clojure for a function's arglists." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-arglists-form-planck - "(planck.repl/get-arglists \"%s\")" - "Planck form to query inferior Clojure for a function's arglists." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.1.0")) - -(defcustom inf-clojure-arglists-form-joker - "(try - (:arglists - (joker.core/meta - (joker.core/resolve - (joker.core/read-string \"%s\")))) - (catch Error _ nil))" - "Joker form to query inferior Clojure for a function's arglists." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-arglists-form (proc) - "Return the form to query the Inf-Clojure PROC for arglists of a var. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-arglists-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-arglists-form-lumo) - (`planck inf-clojure-arglists-form-planck) - (`joker inf-clojure-arglists-form-joker) - (_ inf-clojure-arglists-form)))) - -(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")) - -(define-obsolete-variable-alias 'inf-clojure-completion-command 'inf-clojure-completion-form "2.0.0") - -(defcustom inf-clojure-completion-form-lumo - "(let [ret (atom nil)] - (lumo.repl/get-completions \"%s\" - (fn [res] (reset! ret (map str res)))) - @ret)" - "Lumo form to query inferior Clojure for completion candidates." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-completion-form-planck - "(planck.repl/get-completions \"%s\")" - "Planck form to query inferior Clojure for completion candidates." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-completion-form-joker - "" - "Joker form to query inferior Clojure for completion candidates." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-completion-form (proc) - "Return the form to query the Inf-Clojure PROC for completions. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-completion-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-completion-form-lumo) - (`planck inf-clojure-completion-form-planck) - (`joker inf-clojure-completion-form-joker) - (_ inf-clojure-completion-form)))) - -(defcustom inf-clojure-ns-vars-form - "(clojure.repl/dir %s)" - "Form to show the public vars in a namespace." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-ns-vars-form-lumo - "(lumo.repl/dir %s)" - "Lumo form to show the public vars in a namespace." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-ns-vars-form-planck - "(planck.repl/dir %s)" - "Planck form to show the public vars in a namespace." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-ns-vars-form-joker - "" - "Joker form to show the public vars in a namespace." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-ns-vars-form (proc) - "Return the form to query the Inf-Clojure PROC for public vars in a namespace. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-ns-vars-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-ns-vars-form-lumo) - (`planck inf-clojure-ns-vars-form-planck) - (`joker inf-clojure-ns-vars-form-joker) - (_ inf-clojure-ns-vars-form)))) - -(define-obsolete-variable-alias 'inf-clojure-ns-vars-command 'inf-clojure-ns-vars-form "2.0.0") - -(defcustom inf-clojure-set-ns-form - "(clojure.core/in-ns '%s)" - "Form to set the namespace of the inferior Clojure process." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-set-ns-form-planck - "(in-ns '%s)" - "Planck form to set the namespace of the inferior Clojure process." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-set-ns-form-lumo - "(in-ns '%s)" - "Lumo form to set the namespace of the inferior Clojure process." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-set-ns-form-joker - "(in-ns '%s)" - "Joker form to set the namespace of the inferior Clojure process." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-set-ns-form (proc) - "Return the form to set the namespace of the Inf-Clojure PROC. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-set-ns-form` variant." - (pcase (inf-clojure--set-repl-type proc) - (`planck inf-clojure-set-ns-form-planck) - (`lumo inf-clojure-set-ns-form-lumo) - (`joker inf-clojure-set-ns-form-joker) - (_ inf-clojure-set-ns-form))) - -(define-obsolete-variable-alias 'inf-clojure-set-ns-command 'inf-clojure-set-ns-form "2.0.0") - -(defcustom inf-clojure-apropos-form - "(doseq [var (sort (clojure.repl/apropos \"%s\"))] - (println (str var)))" - "Form to invoke apropos." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-apropos-form-lumo - "(lumo.repl/apropos \"%s\")" - "Planck form to invoke apropos." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-apropos-form-planck - "(doseq [var (sort (planck.repl/apropos \"%s\"))] - (println (str var)))" - "Planck form to invoke apropos." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-apropos-form-joker - "" - "Joker form to invoke apropos." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-apropos-form (proc) - "Return the form to query the Inf-Clojure PROC for a var's apropos. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-apropos-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-apropos-form-lumo) - (`planck inf-clojure-apropos-form-planck) - (`joker inf-clojure-apropos-form-joker) - (_ inf-clojure-apropos-form)))) - -(define-obsolete-variable-alias 'inf-clojure-apropos-command 'inf-clojure-apropos-form "2.0.0") - -(defcustom inf-clojure-macroexpand-form - "(clojure.core/macroexpand '%s)" - "Form to invoke macroexpand." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-macroexpand-form-planck - "(macroexpand '%s)" - "Planck form to invoke macroexpand." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-macroexpand-form-lumo - "(macroexpand '%s)" - "Lumo form to invoke macroexpand." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defcustom inf-clojure-macroexpand-form-joker - "(macroexpand '%s)" - "Joker form to invoke macroexpand." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-macroexpand-form (proc) - "Return the form for macroexpansion in the Inf-Clojure PROC. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-macroexpand-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-macroexpand-form-lumo) - (`planck inf-clojure-macroexpand-form-planck) - (`joker inf-clojure-macroexpand-form-joker) - (_ inf-clojure-macroexpand-form)))) - -(define-obsolete-variable-alias 'inf-clojure-macroexpand-command 'inf-clojure-macroexpand-form "2.0.0") - -(defcustom inf-clojure-macroexpand-1-form - "(clojure.core/macroexpand-1 '%s)" - "Form to invoke macroexpand-1." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-macroexpand-1-form-planck - "(macroexpand-1 '%s)" - "Planck form to invoke macroexpand-1." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-macroexpand-1-form-lumo - "(macroexpand-1 '%s)" - "Lumo form to invoke macroexpand-1." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defcustom inf-clojure-macroexpand-1-form-joker - "(macroexpand-1 '%s)" - "Joker form to invoke macroexpand-1." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.2.0")) - -(defun inf-clojure-macroexpand-1-form (proc) - "Return the form for macroexpand-1 in the Inf-Clojure PROC. -If you are using REPL types, it will pickup the most appropriate -`inf-clojure-macroexpand-1-form` variant." - (inf-clojure--sanitize-command - (pcase (inf-clojure--set-repl-type proc) - (`lumo inf-clojure-macroexpand-1-form-lumo) - (`planck inf-clojure-macroexpand-1-form-planck) - (`joker inf-clojure-macroexpand-1-form-joker) - (_ inf-clojure-macroexpand-1-form)))) - -(define-obsolete-variable-alias 'inf-clojure-macroexpand-1-command 'inf-clojure-macroexpand-1-form "2.0.0") ;;; Ancillary functions ;;; =================== @@ -1284,22 +979,24 @@ The value is nil if it can't find one." See function `inf-clojure-var-doc-form'. When invoked with a prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name." (interactive "P") - (let ((proc (inf-clojure-proc)) - (var (if prompt-for-symbol - (car (inf-clojure-symprompt "Var doc" (inf-clojure-symbol-at-point))) - (inf-clojure-symbol-at-point)))) - (inf-clojure--send-string proc (format (inf-clojure-var-doc-form proc) var)))) + (let* ((proc (inf-clojure-proc)) + (var (if prompt-for-symbol + (car (inf-clojure-symprompt "Var doc" (inf-clojure-symbol-at-point))) + (inf-clojure-symbol-at-point))) + (doc-form (inf-clojure-get-feature proc 'doc))) + (inf-clojure--send-string proc (format doc-form var)))) (defun inf-clojure-show-var-source (prompt-for-symbol) "Send a command to the inferior Clojure to give source for VAR. See variable `inf-clojure-var-source-form'. When invoked with a prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name." (interactive "P") - (let ((proc (inf-clojure-proc)) - (var (if prompt-for-symbol - (car (inf-clojure-symprompt "Var source" (inf-clojure-symbol-at-point))) - (inf-clojure-symbol-at-point)))) - (inf-clojure--send-string proc (format (inf-clojure-var-source-form proc) var)))) + (let* ((proc (inf-clojure-proc)) + (var (if prompt-for-symbol + (car (inf-clojure-symprompt "Var source" (inf-clojure-symbol-at-point))) + (inf-clojure-symbol-at-point))) + (source-form (inf-clojure-get-feature proc 'source))) + (inf-clojure--send-string proc (format source-form var)))) ;;;; Response parsing ;;;; ================ @@ -1391,7 +1088,7 @@ output from and including the `inf-clojure-prompt`." response-string))))) (defun inf-clojure--nil-string-match-p (string) - "Return true iff STRING is not nil. + "Return non-nil iff STRING is not nil. This function also takes into consideration weird escape character and matches if nil is anywhere within the input string." @@ -1426,7 +1123,7 @@ for evaluation, therefore FORM should not include it." (when response (funcall match-p response)))) (defun inf-clojure--some-response-p (proc form) - "Return true iff PROC's response after evaluating FORM is not nil." + "Return non-nil iff PROC's response after evaluating FORM is not nil." (inf-clojure--process-response-match-p (lambda (string) (not (inf-clojure--nil-string-match-p (string-trim string)))) @@ -1439,10 +1136,10 @@ for evaluation, therefore FORM should not include it." "Send a query to the inferior Clojure for the arglists for function FN. See variable `inf-clojure-arglists-form'." (when-let ((proc (inf-clojure-proc 'no-error))) - (thread-first - (format (inf-clojure-arglists-form proc) fn) - (inf-clojure--process-response proc "(" ")") - (inf-clojure--some)))) + (when-let ((arglists-form (inf-clojure-get-feature proc 'arglists))) + (thread-first (format arglists-form fn) + (inf-clojure--process-response proc "(" ")") + (inf-clojure--some))))) (defun inf-clojure-show-arglists (prompt-for-symbol) "Show the arglists for function FN in the mini-buffer. @@ -1453,19 +1150,21 @@ prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name." (car (inf-clojure-symprompt "Arglists" (inf-clojure-fn-called-at-pt))) (inf-clojure-fn-called-at-pt))) (eldoc (inf-clojure-arglists fn))) - (when eldoc - (message "%s: %s" fn eldoc)))) + (if eldoc + (message "%s: %s" fn eldoc) + (message "Arglists not supported for this repl")))) (defun inf-clojure-show-ns-vars (prompt-for-ns) "Send a query to the inferior Clojure for the public vars in NS. See variable `inf-clojure-ns-vars-form'. When invoked with a prefix argument PROMPT-FOR-NS, it prompts for a namespace name." (interactive "P") - (let ((proc (inf-clojure-proc)) - (ns (if prompt-for-ns - (car (inf-clojure-symprompt "Ns vars" (clojure-find-ns))) - (clojure-find-ns)))) - (inf-clojure--send-string proc (format (inf-clojure-ns-vars-form proc) ns)))) + (let* ((proc (inf-clojure-proc)) + (ns (if prompt-for-ns + (car (inf-clojure-symprompt "Ns vars" (clojure-find-ns))) + (clojure-find-ns))) + (ns-vars-form (inf-clojure-get-feature proc 'ns-vars))) + (inf-clojure--send-string proc (format ns-vars-form ns)))) (defun inf-clojure-set-ns (prompt-for-ns) "Set the ns of the inferior Clojure process to NS. @@ -1473,45 +1172,38 @@ 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") - (let ((proc (inf-clojure-proc)) - (ns (if prompt-for-ns - (car (inf-clojure-symprompt "Set ns to" (clojure-find-ns))) - (clojure-find-ns)))) + (let* ((proc (inf-clojure-proc)) + (ns (if prompt-for-ns + (car (inf-clojure-symprompt "Set ns to" (clojure-find-ns))) + (clojure-find-ns))) + (set-ns-form (inf-clojure-get-feature proc 'set-ns))) (when (or (not ns) (equal ns "")) (user-error "No namespace selected")) - (inf-clojure--send-string proc (format (inf-clojure-set-ns-form proc) ns)))) + (inf-clojure--send-string proc (format set-ns-form ns)))) (defun inf-clojure-apropos (expr) "Send an expression to the inferior Clojure for apropos. EXPR can be either a regular expression or a stringable thing. See variable `inf-clojure-apropos-form'." (interactive (inf-clojure-symprompt "Var apropos" (inf-clojure-symbol-at-point))) - (let ((proc (inf-clojure-proc))) - (inf-clojure--send-string proc (format (inf-clojure-apropos-form proc) expr)))) + (let* ((proc (inf-clojure-proc)) + (apropos-form (inf-clojure-get-feature proc 'apropos))) + (inf-clojure--send-string proc (format apropos-form expr)))) (defun inf-clojure-macroexpand (&optional macro-1) "Send a form to the inferior Clojure for macro expansion. See variable `inf-clojure-macroexpand-form'. With a prefix arg MACRO-1 uses function `inf-clojure-macroexpand-1-form'." (interactive "P") - (let ((proc (inf-clojure-proc)) - (last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point)))) + (let* ((proc (inf-clojure-proc)) + (last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point))) + (macroexpand-form (inf-clojure-get-feature proc + (if macro-1 + 'macroexpand-1 + 'macroexpand)))) (inf-clojure--send-string proc - (format (if macro-1 - (inf-clojure-macroexpand-1-form proc) - (inf-clojure-macroexpand-form proc)) - last-sexp)))) - -(defun inf-clojure-proc (&optional no-error) - "Return the current inferior Clojure process. -When NO-ERROR is non-nil, don't throw an error when no connection -has been found. See also variable `inf-clojure-buffer'." - (or (get-buffer-process (if (derived-mode-p 'inf-clojure-mode) - (current-buffer) - inf-clojure-buffer)) - (unless no-error - (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) + (format macroexpand-form last-sexp)))) (defun inf-clojure--list-or-nil (data) "Return DATA if and only if it is a list." @@ -1533,11 +1225,12 @@ every other EXPR will be discarded and nil will be returned." Under the hood it calls the function \\[inf-clojure-completions-fn] passing in the result of evaluating \\[inf-clojure-completion-form] at the REPL." - (let ((proc (inf-clojure-proc 'no-error))) - (when (and proc (not (string-blank-p expr))) - (let ((completion-form (format (inf-clojure-completion-form proc) (substring-no-properties expr)))) + (let* ((proc (inf-clojure-proc 'no-error)) + (completion-form (inf-clojure-get-feature proc 'completion t))) + (when (and proc completion-form (not (string-blank-p expr))) + (let ((completion-expr (format completion-form (substring-no-properties expr)))) (funcall inf-clojure-completions-fn - (inf-clojure--process-response completion-form proc "(" ")")))))) + (inf-clojure--process-response completion-expr proc "(" ")")))))) (defcustom inf-clojure-completions-fn 'inf-clojure-list-completions "The function that parses completion results. diff --git a/todo.org b/todo.org new file mode 100644 index 0000000..6b3e922 --- /dev/null +++ b/todo.org @@ -0,0 +1,58 @@ +* Core + +** TODO set repl type on connection not first command +For some reason ~inf-clojure--set-repl-type~ is called in: +1. inf-clojure--send-string +2. inf-clojure-reload-form +3. inf-clojure-reload-all-form + +Seems better to do this on the two different connection methods and then be done with it? + +** 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. + +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 +Right now the functions are kinda clunky cond statements: +#+BEGIN_SRC emacs-lisp + (defun inf-clojure-cljs-features-dispatch (feature) + (case feature + ;; ((load) "(cljs.core/load-file \"%s\")") + ((doc) "(cljs.repl/doc %s)") + ((source) "(cljs.repl/source %s)") + ((arglists) "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") + ((apropos) "(cljs.repl/apropos \"%s\")") + ((ns-vars) "(cljs.repl/dir %s)") + ((set-ns) "(cljs.core/in-ns '%s)") + ((macroexpand) "(cljs.core/macroexpand '%s)") + ((macroexpand-1) "(cljs.core/macroexpand-1 '%s)") + ;; ((completion) inf-clojure-completion-form-lumo) + )) +#+END_SRC + +I really want something similar to ~(defprotocol Inf-clojure-REPL (doc ...)(source ...))~ rather than just this super open ended dispatch on symbols. I just don't know enough elisp at the moment. Also, the current function version prevents introspection and providing a way of listing the repl's capabilities without duplicating the keys. Or maybe a hack of sending all of the known keys in and seeing which return strings. Still not great. + +** TODO Nicer interface to create a command +Right now everything is just a format string with a _single_ ~%s~ in it and that's called with ~(format feature-form e)~ where ~e~ is a symbol, or a form, or a whatever makes sense for that type of feature. This isn't super elegant although it does keep inf-clojure honest in that _all_ it does it format commands to ask a simple repl. But there could probably be a better way. + +** 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 Multiple connections +As proven by CIDER, multiple connections are just a pain. Scoping, navigating into dependencies, etc. This is a monster lurking + +** TODO navigation to source +The source primitive is quite nice but we most likely need a way to navigate to source. Possibly punt on this and just suggest people use with clojure-lsp? + +** TODO PREPL +Be nice to implement this now that we have parseedn in elisp to understand edn. +* Nice-to-haves + +** TODO Better handling of cyclic dependencies +In inf-clojure.el I load the implementation specific files for lumo, planck, etc _after_ defining the register function. I would much prefer a way to do this without being so fragile. + +** TODO Put repl type in modeline +Rather than just ~*inf-clojure*~ we could put the repl type. Make it easy to follow and makes it easy to see when it gets it wrong. From c590c65d8f7b702f642b97548aa28ac91fb2e857 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Wed, 15 Apr 2020 21:35:56 -0500 Subject: [PATCH 056/189] Remove projects from inf-clojure except to serve as project root No inferring of build commands. Just a simple api: - `m-x inf-clojure` and select or type a clojure startup command - `m-x inf-clojure-connect` and enter host and port These days clojure commands are incredibly simple and tooling gets in the way. Inf clojure just interacts with a repl process so you can follow tutorials and just type what the tutorial types in. Seems just as simple to define your own project functions as to develop a good override api and defcustoms. Update todo with removing CIDER hooks --- inf-clojure.el | 138 +++++++++++++++---------------------------------- todo.org | 14 +++-- 2 files changed, 51 insertions(+), 101 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 1545e14..9149212 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -408,45 +408,6 @@ If this is `nil`, the project will be automatically detected." :safe #'stringp :package-version '(inf-clojure . "2.1.0")) -(defcustom inf-clojure-lein-cmd "lein repl" - "The command used to start a Clojure REPL for Leiningen projects. - -Alternatively you can specify a TCP connection cons pair, instead -of command, consisting of a host and port -number (e.g. (\"localhost\" . 5555)). That's useful if you're -often connecting to a remote REPL process." - :type '(choice (string) - (cons string integer)) - :risky #'stringp - :safe #'inf-clojure--endpoint-p - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-boot-cmd "boot repl -C" - "The command used to start a Clojure REPL for Boot projects. - -Alternatively you can specify a TCP connection cons pair, instead -of command, consisting of a host and port -number (e.g. (\"localhost\" . 5555)). That's useful if you're -often connecting to a remote REPL process." - :type '(choice (string) - (cons string integer)) - :risky #'stringp - :safe #'inf-clojure--endpoint-p - :package-version '(inf-clojure . "2.0.0")) - -(defcustom inf-clojure-tools-deps-cmd "clojure" - "The command used to start a Clojure REPL for tools.deps projects. - -Alternatively you can specify a TCP connection cons pair, instead -of command, consisting of a host and port -number (e.g. (\"localhost\" . 5555)). That's useful if you're -often connecting to a remote REPL process." - :type '(choice (string) - (cons string integer)) - :risky #'stringp - :safe #'inf-clojure--endpoint-p - :package-version '(inf-clojure . "2.1.0")) - (defcustom inf-clojure-generic-cmd "lein repl" "The command used to start a Clojure REPL outside Lein/Boot projects. @@ -688,7 +649,7 @@ to continue it." (t str))) (defvar inf-clojure-project-root-files - '("project.clj" "build.boot" "deps.edn") + '("project.clj" "build.boot" "deps.edn" "shadow-cljs.edn") "A list of files that can be considered project markers.") (defun inf-clojure-project-root () @@ -702,29 +663,52 @@ Fallback to `default-directory.' if not within a project." inf-clojure-project-root-files))) default-directory)) -(defun inf-clojure-project-type () - "Determine the type, either leiningen or boot of the current project." - (or inf-clojure-project-type - (let ((default-directory (inf-clojure-project-root))) - (cond ((file-exists-p "project.clj") "lein") - ((file-exists-p "build.boot") "boot") - ((file-exists-p "deps.edn") "tools.deps") - (t "generic"))))) - -(defun inf-clojure-cmd (project-type) - "Determine the command `inf-clojure' needs to invoke for the PROJECT-TYPE." - (pcase project-type - ("lein" inf-clojure-lein-cmd) - ("boot" inf-clojure-boot-cmd) - ("tools.deps" inf-clojure-tools-deps-cmd) - (_ inf-clojure-generic-cmd))) - (defun inf-clojure-clear-repl-buffer () "Clear the REPL buffer." (interactive) (let ((comint-buffer-maximum-size 0)) (comint-truncate-buffer))) +(defun inf-clojure-switch-to-repl (eob-p) + "Switch to the inferior Clojure process buffer. +With prefix argument EOB-P, positions cursor at end of buffer." + (interactive "P") + (if (get-buffer-process inf-clojure-buffer) + (let ((pop-up-frames + ;; Be willing to use another frame + ;; that already has the window in it. + (or pop-up-frames + (get-buffer-window inf-clojure-buffer t)))) + (pop-to-buffer inf-clojure-buffer)) + (call-interactively #'inf-clojure)) + (when eob-p + (push-mark) + (goto-char (point-max)))) + +(defun inf-clojure-quit (&optional buffer) + "Kill the REPL buffer and its underlying process. + +You can pass the target BUFFER as an optional parameter +to suppress the usage of the target buffer discovery logic." + (interactive) + (let ((target-buffer (or buffer (inf-clojure-select-target-repl)))) + (when (get-buffer-process target-buffer) + (delete-process target-buffer)) + (kill-buffer target-buffer))) + +(defun inf-clojure-restart (&optional buffer) + "Restart the REPL buffer and its underlying process. + +You can pass the target BUFFER as an optional parameter +to suppress the usage of the target buffer discovery logic." + (interactive) + (let* ((target-buffer (or buffer (inf-clojure-select-target-repl))) + (target-buffer-name (buffer-name target-buffer))) + ;; TODO: Try to recycle the old buffer instead of killing and recreating it + (inf-clojure-quit target-buffer) + (call-interactively #'inf-clojure) + (rename-buffer target-buffer-name))) + ;;;###autoload (defun inf-clojure (cmd) "Run an inferior Clojure process, input and output via buffer `*inf-clojure*'. @@ -821,22 +805,6 @@ Prefix argument AND-GO means switch to the Clojure buffer afterwards." (inf-clojure-eval-last-sexp) (forward-sexp)) -(defun inf-clojure-switch-to-repl (eob-p) - "Switch to the inferior Clojure process buffer. -With prefix argument EOB-P, positions cursor at end of buffer." - (interactive "P") - (if (get-buffer-process inf-clojure-buffer) - (let ((pop-up-frames - ;; Be willing to use another frame - ;; that already has the window in it. - (or pop-up-frames - (get-buffer-window inf-clojure-buffer t)))) - (pop-to-buffer inf-clojure-buffer)) - (inf-clojure (inf-clojure-cmd (inf-clojure-project-type)))) - (when eob-p - (push-mark) - (goto-char (point-max)))) - (defun inf-clojure-insert-and-eval (form) "Insert FORM into process and evaluate. Indent FORM. FORM is expected to have been trimmed." @@ -1411,30 +1379,6 @@ Useful for commands that can invoked outside of an ‘inf-clojure’ buffer (t (get-buffer (completing-read "Select target inf-clojure buffer: " (mapcar #'buffer-name repl-buffers)))))))) -(defun inf-clojure-quit (&optional buffer) - "Kill the REPL buffer and its underlying process. - -You can pass the target BUFFER as an optional parameter -to suppress the usage of the target buffer discovery logic." - (interactive) - (let ((target-buffer (or buffer (inf-clojure-select-target-repl)))) - (when (get-buffer-process target-buffer) - (delete-process target-buffer)) - (kill-buffer target-buffer))) - -(defun inf-clojure-restart (&optional buffer) - "Restart the REPL buffer and its underlying process. - -You can pass the target BUFFER as an optional parameter -to suppress the usage of the target buffer discovery logic." - (interactive) - (let* ((target-buffer (or buffer (inf-clojure-select-target-repl))) - (target-buffer-name (buffer-name target-buffer))) - ;; TODO: Try to recycle the old buffer instead of killing and recreating it - (inf-clojure-quit target-buffer) - (inf-clojure (inf-clojure-cmd (inf-clojure-project-type))) - (rename-buffer target-buffer-name))) - (defun inf-clojure--response-match-p (form match-p proc) "Send FORM and apply MATCH-P on the result of sending it to PROC. Note that this function will add a \n to the end of the string diff --git a/todo.org b/todo.org index 6b3e922..e42524f 100644 --- a/todo.org +++ b/todo.org @@ -50,9 +50,15 @@ The source primitive is quite nice but we most likely need a way to navigate to ** TODO PREPL Be nice to implement this now that we have parseedn in elisp to understand edn. * Nice-to-haves - -** TODO Better handling of cyclic dependencies -In inf-clojure.el I load the implementation specific files for lumo, planck, etc _after_ defining the register function. I would much prefer a way to do this without being so fragile. - ** TODO Put repl type in modeline Rather than just ~*inf-clojure*~ we could put the repl type. Make it easy to follow and makes it easy to see when it gets it wrong. + +** TODO How do CIDER and inf-clojure play nice on the same emacs? +inf-clojure and CIDER are fighting over the keymappings. I've been doing a bit of a kludge to remove CIDER's tentacles from my clojure files for developing: +#+BEGIN_SRC emacs-lisp + (seq-doseq (buffer (buffer-list)) + (with-current-buffer buffer + (cider-mode -1)) + (remove-hook 'clojure-mode-hook #'cider-mode)) +#+END_SRC +Seems a bit heavy handed but its working for me so far. From ac40726b09b403bd61870425c5d627635512ca02 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Wed, 15 Apr 2020 22:35:34 -0500 Subject: [PATCH 057/189] Move all repl stuff into single nested alist pulled the inf-clojure-get-feature up to the top so its near the datastructure it accesses. Everything is now a nested alist. --- inf-clojure.el | 229 +++++++++++++++++++------------------------------ 1 file changed, 87 insertions(+), 142 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 9149212..313d823 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -71,134 +71,91 @@ (require 'subr-x) (require 'seq) -(defvar inf-clojure-implementations (make-hash-table :size 6)) -(defvar inf-clojure-recognize-alist '()) -(defvar inf-clojure-startup-forms '()) - -(defun inf-clojure-register-implementation - (repl-type implementation &optional recognize default-startup) - "Register a REPL-TYPE for `inf-clojure'. -REPL-TYPE is a symbol of the repl type (lumo, planck, etc) - -IMPLEMENTATION is a function from feature-symbol to format -string. For instance, (implementation 'doc) > (cljs.repl/doc -\"%s\"). The full list of feature symbols is: load, doc, source, -arglists, apropos, ns-vars, set-ns, macroexpand, macroexpand-1, -and completion. - -RECOGNIZE is a namespace that, if present, will indicate that the -currently connected repl is a repl of this type. - -DEFAULT-STARTUP is a command to start a repl of this type from -the repl" - (puthash repl-type implementation inf-clojure-implementations) - (when recognize - (add-to-list 'inf-clojure-recognize-alist (cons repl-type recognize))) - (when default-startup - (add-to-list 'inf-clojure-startup-forms (cons repl-type default-startup)))) - -(defun inf-clojure-cljs-features-dispatch (feature) - (case feature - ;; ((load) "(cljs.core/load-file \"%s\")") - ((doc) "(cljs.repl/doc %s)") - ((source) "(cljs.repl/source %s)") - ((arglists) "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") - ((apropos) "(cljs.repl/apropos \"%s\")") - ((ns-vars) "(cljs.repl/dir %s)") - ((set-ns) "(in-ns '%s)") - ((macroexpand) "(cljs.core/macroexpand '%s)") - ((macroexpand-1) "(cljs.core/macroexpand-1 '%s)") - ;; ((completion) inf-clojure-completion-form-lumo) - )) - -(inf-clojure-register-implementation - 'cljs #'inf-clojure-cljs-features-dispatch "cljs.repl" "clojure -m cljs.main -r") - -(defun inf-clojure-lumo-features-dispatch (feature) - (case feature - ((load) "(clojure.core/load-file \"%s\")") - ((doc) "(lumo.repl/doc %s)") - ((source) "(lumo.repl/source %s)") - ((arglists) - "(let [old-value lumo.repl/*pprint-results*] - (set! lumo.repl/*pprint-results* false) - (js/setTimeout #(set! lumo.repl/*pprint-results* old-value) 0) - (lumo.repl/get-arglists \"%s\"))") - ((apropos) "(lumo.repl/apropos \"%s\")") - ((ns-vars) "(lumo.repl/dir %s)") - ((set-ns) "(in-ns '%s)") - ((macroexpand) "(macroexpand-1 '%s)") - ((macroexpand-1) "(macroexpand-1 '%s)") - ((completion) - "(let [ret (atom nil)] - (lumo.repl/get-completions \"%s\" (fn [res] (reset! ret (map str res)))) - @ret)")) ) - -(inf-clojure-register-implementation - 'lumo #'inf-clojure-lumo-features-dispatch "lumo.repl" "lumo") - -(defun inf-clojure-planck-features-dispatch (feature) - (case feature - ((load) "(load-file \"%s\")") - ((doc) "(planck.repl/doc %s)") - ((source) "(planck.repl/source %s)") - ((arglists) "(planck.repl/get-arglists \"%s\")") - ((apropos) "(doseq [var (sort (planck.repl/apropos \"%s\"))] (println (str var)))") - ((ns-vars) "(planck.repl/dir %s)") - ((set-ns) "(in-ns '%s)") - ((macroexpand) "(macroexpand '%s)") - ((macroexpand-1) "(macroexpand-1 '%s)") - ;; ((completion) inf-clojure-completion-form-planck ) - )) - -(inf-clojure-register-implementation - 'planck #'inf-clojure-planck-features-dispatch "planck.repl" "planck") - -(defun inf-clojure-joker-features-dispatch (feature) - (case feature - ((load) "(load-file \"%s\")") - ((doc) "(joker.repl/doc %s)") - ;; ((source) "") - ((arglists) - "(try - (:arglists - (joker.core/meta - (joker.core/resolve - (joker.core/read-string \"%s\")))) - (catch Error _ nil))") - ;; ((apropos) "") - ;; ((ns-vars) "") - ((set-ns) "(in-ns '%s)") - ((macroexpand) "(macroexpand '%s)") - ((macroexpand-1) "(macroexpand-1 '%s)") - ;; ((completion) "") - )) - -(inf-clojure-register-implementation - 'joker #'inf-clojure-joker-features-dispatch "joker.repl" "joker") - -(defun inf-clojure-clojure-features-dispatch (feature) - (case feature - ((load) "(clojure.core/load-file \"%s\")") - ((doc) "(clojure.repl/doc %s)") - ((source) "(clojure.repl/source %s)") - ((arglists) - "(try - (:arglists - (clojure.core/meta - (clojure.core/resolve - (clojure.core/read-string \"%s\")))) -(catch #?(:clj Throwable :cljr Exception) e nil))") - ((apropos) "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))") - ((ns-vars) "(clojure.repl/dir %s)") - ((set-ns) "(clojure.core/in-ns '%s)") - ((macroexpand) "(clojure.core/macroexpand '%s)") - ((macroexpand-1) "(clojure.core/macroexpand-1 '%s)") - ;; ((completion) nil) - )) - -(inf-clojure-register-implementation - 'clojure #'inf-clojure-clojure-features-dispatch "clojure.core.server" "clojure") +(defvar inf-clojure-recognize-alist '((lumo . "lumo.repl") + (planck . "planck.repl") + ;; cljs goes after the selfhosts + (cljs . "cljs.repl") + (joker . "joker.repl") + (clojure . "clojure.core.server"))) +(defvar inf-clojure-startup-forms '((clojure . "clojure") + (cljs . "clojure -m cljs.main -r") + (planck . "planck") + (lumo . "lumo") + (joker . "joker"))) + +(defvar inf-clojure-repl-features + '((cljs . ((doc . "(cljs.repl/doc %s)") + (source . "(cljs.repl/source %s)") + (arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") + (apropos . "(cljs.repl/apropos \"%s\")") + (ns-vars . "(cljs.repl/dir %s)") + (set-ns . "(in-ns '%s)") + (macroexpand . "(cljs.core/macroexpand '%s)") + (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)"))) + (lumo . ((load . "(clojure.core/load-file \"%s\")") + (doc . "(lumo.repl/doc %s)") + (source . "(lumo.repl/source %s)") + (arglists . + "(let [old-value lumo.repl/*pprint-results*] + (set! lumo.repl/*pprint-results* false) + (js/setTimeout #(set! lumo.repl/*pprint-results* old-value) 0) + (lumo.repl/get-arglists \"%s\"))") + (apropos . "(lumo.repl/apropos \"%s\")") + (ns-vars . "(lumo.repl/dir %s)") + (set-ns . "(in-ns '%s)") + (macroexpand . "(macroexpand-1 '%s)") + (macroexpand-1 . "(macroexpand-1 '%s)") + (completion . + "(let [ret (atom nil)] + (lumo.repl/get-completions \"%s\" (fn [res] (reset! ret (map str res)))) + @ret)"))) + (planck . ((load . "(load-file \"%s\")") + (doc . "(planck.repl/doc %s)") + (source . "(planck.repl/source %s)") + (arglists . "(planck.repl/get-arglists \"%s\")") + (apropos . "(doseq [var (sort (planck.repl/apropos \"%s\"))] (println (str var)))") + (ns-vars . "(planck.repl/dir %s)") + (set-ns . "(in-ns '%s)") + (macroexpand . "(macroexpand '%s)") + (macroexpand-1 . "(macroexpand-1 '%s)"))) + (joker . ((load . "(load-file \"%s\")") + (doc . "(joker.repl/doc %s)") + (arglists . + "(try + (:arglists + (joker.core/meta + (joker.core/resolve + (joker.core/read-string \"%s\")))) + (catch Error _ nil))") + (set-ns . "(in-ns '%s)") + (macroexpand . "(macroexpand '%s)") + (macroexpand-1 . "(macroexpand-1 '%s)"))) + (clojure . ((load . "(clojure.core/load-file \"%s\")") + (doc . "(clojure.repl/doc %s)") + (source . "(clojure.repl/source %s)") + (arglists . + "(try + (:arglists + (clojure.core/meta + (clojure.core/resolve + (clojure.core/read-string \"%s\")))) + (catch #?(:clj Throwable :cljr Exception) e nil))") + (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))") + (ns-vars . "(clojure.repl/dir %s)") + (set-ns . "(clojure.core/in-ns '%s)") + (macroexpand . "(clojure.core/macroexpand '%s)") + (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))))) + +(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) + inf-clojure-repl-type) + (error "Repl type is not known"))) + (feature-form (alist-get feature (alist-get repl-type inf-clojure-repl-features)))) + (cond (feature-form feature-form) + (no-error nil) + (t (error "%s not configured for %s" feature repl-type))))) (defun inf-clojure-proc (&optional no-error) "Return the current inferior Clojure process. @@ -234,11 +191,11 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte "Set the REPL type to one of the available implementations." (interactive) (let* ((proc (inf-clojure-proc)) - (types (hash-table-keys inf-clojure-implementations)) + (types (mapcar #'car inf-clojure-repl-features)) (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) + (setq-local inf-clojure-repl-type type-to-set) (with-current-buffer (process-buffer proc) (setq-local inf-clojure-repl-type type-to-set)))) @@ -254,18 +211,6 @@ It requires a REPL PROC for inspecting the correct type." (setq-local inf-clojure-repl-type repl-type)) inf-clojure-repl-type)) -(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) - inf-clojure-repl-type) - (error "Repl type is not known"))) - (implementation (gethash repl-type inf-clojure-implementations)) - (feature-form (and implementation (funcall implementation feature)))) - (cond (feature-form feature-form) - (no-error nil) - (t (error "%s not configured for %s" feature repl-type))))) - (defgroup inf-clojure nil "Run an external Clojure process (REPL) in an Emacs buffer." :prefix "inf-clojure-" From 30638a055c51025c835cd548fa3ea15d2d2eb847 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Thu, 16 Apr 2020 00:04:49 -0500 Subject: [PATCH 058/189] Remove old defcustomed defcustom `inf-clojure-custom-startup` startup string or (host . port) --- inf-clojure.el | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 313d823..71d6355 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -345,26 +345,12 @@ number (e.g. (\"localhost\" . 5555))." (stringp (car x)) (numberp (cdr x)))) -(defcustom inf-clojure-project-type nil - "Defines the project type. - -If this is `nil`, the project will be automatically detected." - :type 'string - :safe #'stringp - :package-version '(inf-clojure . "2.1.0")) - -(defcustom inf-clojure-generic-cmd "lein repl" - "The command used to start a Clojure REPL outside Lein/Boot projects. - -Alternatively you can specify a TCP connection cons pair, instead -of command, consisting of a host and port -number (e.g. (\"localhost\" . 5555)). That's useful if you're -often connecting to a remote REPL process." - :type '(choice (string) - (cons string integer)) - :risky #'stringp - :safe #'inf-clojure--endpoint-p - :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-custom-startup + nil + "Form to be used to start inf-clojure. +Can be a cons pair of (host . port) where host is a string and +port is an integer, or a string to startup an interpreter like +\"planck\".") (defun inf-clojure--whole-comment-line-p (string) "Return non-nil iff STRING is a whole line semicolon comment." @@ -664,10 +650,11 @@ it (default is value of `inf-clojure-*-cmd'). Runs the hooks from `inf-clojure-mode-hook' (after the `comint-mode-hook' is run). \(Type \\[describe-mode] in the process buffer for a list of commands.)" - (interactive (list (completing-read "Clojure startup command: " - (mapcar #'cdr inf-clojure-startup-forms) - nil - 'confirm-after-completion))) + (interactive (list (or inf-clojure-custom-startup + (completing-read "Clojure startup command: " + (mapcar #'cdr inf-clojure-startup-forms) + nil + 'confirm-after-completion)))) (if (not (comint-check-proc "*inf-clojure*")) ;; run the new process in the project's root when in a project folder (let ((default-directory (inf-clojure-project-root)) From e33a546305819dc385e575028bc5636cfc7009f0 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Thu, 16 Apr 2020 00:09:35 -0500 Subject: [PATCH 059/189] 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 From 80cefbb6c10d641d8e0faa745a31275deff38ab6 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 18 Apr 2020 11:12:33 -0500 Subject: [PATCH 060/189] API to update repl-features --- README.md | 48 +++++++++++++++++++++++++++++---------- inf-clojure.el | 35 ++++++++++++++++++++++++---- test/inf-clojure-tests.el | 10 ++++++++ 3 files changed, 76 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f1aac4b..bb3b1d6 100644 --- a/README.md +++ b/README.md @@ -243,22 +243,46 @@ configurable. You can see all the configuration options available using the command `M-x customize-group RET inf-clojure`. +The supported repl-features are in an alist called +`inc-clojure-repl-features` and it has the following shape: + +```emacs-lisp +'((cljs . ((doc . "(cljs.repl/doc %s)") + (source . "(cljs.repl/source %s)") + (arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") + (apropos . "(cljs.repl/apropos \"%s\")") + (ns-vars . "(cljs.repl/dir %s)") + (set-ns . "(in-ns '%s)") + (macroexpand . "(cljs.core/macroexpand '%s)") + (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)")))) +``` + +If you want to add a new repl type, just `(add-to-list +'inf-clojure-repl-features (cons new-repl-type '((doc +. "(myrepl/doc-command %s") ...)))` + +If you want to update a specific form there is a function +`inf-clojure-update-repl-feature` which can be used like so: + +```emacs-lisp +(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")") +``` + #### REPL Type -An `inf-clojure` REPL can be of different types: Clojure, ClojureScript, Lumo -and Planck are all potentially valid options. +An `inf-clojure` REPL can be of different types: Clojure, +ClojureScript, Lumo and Planck are all potentially valid options. -At the moment, the default Clojure REPL, the Lumo REPL, the Planck REPL and the -Joker REPL are supported (standard ClojureScript is lacking mostly because some -features require to access the compiler state, -[cljs-tooling](https://github.com/clojure-emacs/cljs-tooling) is a good -candidate for enabling support). +At the moment, the default Clojure REPL, the Lumo REPL, the Planck +REPL and the Joker REPL are supported. -What does it mean that a REPL type is supported - well it means that `inf-clojure` -would use the proper code internally to power commands like definition lookup and friends. -Those differ from REPL to REPL and can't be implemented in a REPL-independent way. At -boot type `inf-clojure` tries to detect the type of the REPL that was started and uses -this type to dispatch the proper code for the respective REPL type. +What does it mean that a REPL type is supported - well it means that +`inf-clojure` would use the proper code internally to power commands +like definition lookup and friends. Those differ from REPL to REPL +and can't be implemented in a REPL-independent way. At startup +`inf-clojure` tries to detect the type of the REPL that was started +and uses this type to dispatch the proper code for the respective REPL +type. By default `inf-clojure` would start a standard Clojure REPL using `lein` or `boot` but you can easily change this. To boot some other REPL just use the diff --git a/inf-clojure.el b/inf-clojure.el index 008c6a1..e9cb89f 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -146,15 +146,40 @@ (macroexpand . "(clojure.core/macroexpand '%s)") (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))))) +(defun inf-clojure--get-feature (repl-type feature no-error) + "Get FEATURE for REPL-TYPE from repl-features. +If no-error is truthy don't error if feature is not present." + (let ((feature-form (alist-get feature (alist-get repl-type inf-clojure-repl-features)))) + (cond (feature-form feature-form) + (no-error nil) + (t (error "%s not configured for %s" feature repl-type))))) + (defun inf-clojure-get-feature (proc feature &optional no-error) "Get FEATURE based on repl type for 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)))) - (cond (feature-form feature-form) - (no-error nil) - (t (error "%s not configured for %s" feature repl-type))))) + (error "Repl type is not known")))) + (inf-clojure--get-feature repl-type feature no-error))) + +(defun inf-clojure--update-feature (repl-type feature form) + "Return a copy of the datastructure containing the repl features. +Given a REPL-TYPE ('clojure, 'lumo, ...) and a FEATURE ('doc, +'apropos, ...) and a FORM this will return a new datastructure +that can be set as `inf-clojure-repl-features'." + (let ((original (alist-get repl-type inf-clojure-repl-features))) + (if original + (cons (cons repl-type (cons (cons feature form) (assoc-delete-all feature original))) + (assoc-delete-all repl-type inf-clojure-repl-features)) + (error "Attempted to update %s form of unknown repl type %s" + (symbol-name feature) + (symbol-name repl-type))))) + +(defun inf-clojure-update-feature (repl-type feature form) + "Mutate the repl features to the new FORM. +Given a REPL-TYPE ('clojure, 'lumo, ...) and a FEATURE ('doc, +'apropos, ...) and a FORM this will set +`inf-clojure-repl-features' with these new values." + (setq inf-clojure-repl-features (inf-clojure--update-feature repl-type feature form))) (defun inf-clojure-proc (&optional no-error) "Return the current inferior Clojure process. diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 09b224e..bf49c30 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -139,4 +139,14 @@ (it "returns empty string when the command is empty" (expect (inf-clojure--sanitize-command " ") :to-equal ""))) +(describe "inf-clojure--update-feature" + (it "updates new forms correctly" + (let ((inf-clojure-repl-features (inf-clojure--update-feature 'cljs 'doc "new doc"))) + (expect (inf-clojure--get-feature 'cljs 'doc nil) + :to-equal "new doc"))) + (describe "if the repl type is unknown" + (it "signals an error" + (expect (inf-clojure--update-feature 'not-found 'doc "new doc") + :to-throw)))) + ;;; inf-clojure-tests.el ends here From a7f07a0add4aa20ebb974890c9c7a5ab1dd78433 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 18 Apr 2020 14:11:10 -0500 Subject: [PATCH 061/189] Set artificial to true on comint-send-input From comint-send-input: > After the input has been sent, if `comint-process-echoes' is non-nil, then `comint-send-input' waits to see if the process outputs a string matching the input, and if so, deletes that part of the output. If ARTIFICIAL is non-nil, it inhibits such deletion. Callers sending input not from the user should use ARTIFICIAL = t. Seems to mess up a buffer somewhere and output isn't flushed. Extremely important --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index e9cb89f..ea25492 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -769,7 +769,7 @@ Indent FORM. FORM is expected to have been trimmed." (let ((end (point))) (goto-char beginning) (indent-sexp end))) - (comint-send-input t)))) + (comint-send-input t t)))) (defun inf-clojure-insert-defun () "Send current defun to process." From 24121e581af629766de7fee5411b611a65950beb Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 18 Apr 2020 16:21:53 -0500 Subject: [PATCH 062/189] Add babashka repl and readme cleanups Correct bb arglists form missing a trailing ')' and also didnt' include a :bb branch for the exception type Completion for planck Lumo dumb terminal option --- README.md | 251 ++++++++++++++++++++++++++----------------------- inf-clojure.el | 21 ++++- todo.org | 7 +- 3 files changed, 156 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index bb3b1d6..8518f9c 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,21 @@ This package provides basic interaction with a Clojure subprocess (REPL). It's based on ideas from the popular `inferior-lisp` package. -`inf-clojure` has two components - a nice Clojure REPL with -auto-completion and a minor mode (`inf-clojure-minor-mode`), which -extends `clojure-mode` with commands to evaluate forms directly in the -REPL. +`inf-clojure` aims to expose the extensive self-documenting features +of Clojure repls into an emacs package. Inf-clojure does not require +middleware or special tooling. Inf-clojure supports the following +repls: + +- Clojure +- ClojureScript +- planck +- lumo +- joker +- babashka + +`inf-clojure` has two components - a nice REPL buffer (`inf-clojure`) +(`inf-clojure-minor-mode`), which extends `clojure-mode` with commands +to evaluate forms directly in the REPL. `inf-clojure` provides a set of essential features for interactive Clojure(Script) development: @@ -83,7 +94,7 @@ Add the following to your Emacs config to enable have overlapping functionality and keybindings and the result will be nothing short of havoc.** -## Usage +## Basic Usage 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 @@ -94,10 +105,6 @@ and you can start interacting with it. 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. - Inf-clojure aims to be very simple and offer tooling that the repl itself exposes. A few commands are: @@ -107,11 +114,77 @@ itself exposes. A few commands are: - show source `C-c C-s` - insert top level form into repl `C-c C-j d` +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. + Many `inf-clojure-minor-mode` commands by default act on the symbol at point. You can, however, change this behaviour by invoking such commands with a prefix argument. For instance: `C-u C-c C-v` will ask for the symbol you want to show the docstring for. +## Configuration options + +In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely +configurable. + +You can 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) +or by setting them in in your init file. + +You can see all the configuration options available using the command +`M-x customize-group RET inf-clojure`. + +The supported repl-features are in an alist called +`inc-clojure-repl-features` and it has the following shape: + +```emacs-lisp +'((cljs . ((doc . "(cljs.repl/doc %s)") + (source . "(cljs.repl/source %s)") + (arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") + (apropos . "(cljs.repl/apropos \"%s\")") + (ns-vars . "(cljs.repl/dir %s)") + (set-ns . "(in-ns '%s)") + (macroexpand . "(cljs.core/macroexpand '%s)") + (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)")))) +``` + +If you want to add a new repl type, just `(add-to-list +'inf-clojure-repl-features (cons new-repl-type '((doc +. "(myrepl/doc-command %s") ...)))` since the datastructure is just an +alist of alists. + +If you want to update a specific form there is a function +`inf-clojure-update-repl-feature` which can be used like so: + +```emacs-lisp +(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")") +``` + +#### Caveats + +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. If you use the +same project often, make a dir-locals file with this information in `inf-clojure-custom-startup`. + +Note that if you decide _NOT_ to use the socket repl, it is highly recommended +you disable output coloring and/or readline facilities: `inf-clojure` does not +filter out ASCII escape characters at the moment and will not behave correctly. + +For leiningen, there are no command line switches and you need to add +a custom [`project.clj` +option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj): + +```clojure +... + :repl-options {:color false} +... +``` + + #### Clojure Command Line Socket REPL If you have the new [Clojure CLI tools][] installed you can use the `clojure` command: @@ -125,15 +198,8 @@ 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`: ```emacs-lisp -((nil . ((inf-clojure-tools-deps-cmd . ("localhost" . 5555))))) +((nil . ((inf-clojure-custom-startup . ("localhost" . 5555))))) ``` - -or the following to your [Emacs init file][]: - -```emacs-lisp -(setf inf-clojure-tools-deps-cmd '("localhost" . 5555)): -``` - #### Leiningen Socket REPL For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `project.clj`: @@ -160,43 +226,6 @@ 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`: -```emacs-lisp -((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555))))) -``` - -or the following to your [Emacs init file][]: - -```emacs-lisp -(setf inf-clojure-lein-cmd '("localhost" . 5555)) -``` - -Project detection can be completely skipped and the `generic` project type can be used instead: - -```emacs-lisp -(setf inf-clojure-project-type . "generic") -(setf inf-clojure-generic-cmd '("localhost" 5555)) -``` - -#### Caveats - -Note that if you decide _NOT_ to use the socket repl, it is highly recommended -you disable output coloring and/or readline facilities: `inf-clojure` does not -filter out ASCII escape characters at the moment and will not behave correctly. - -You can disable coloring the following way for `boot`: - -```emacs-lisp -((nil . ((inf-clojure-boot-cmd . "boot repl -C")))) -``` - -For leiningen, there are no command line switches and you need to add a custom [`project.clj` option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj): - -```clojure -... - :repl-options {:color false} -... -``` - #### Multiple Process Support To run multiple Clojure processes, you start the first up @@ -235,46 +264,11 @@ one process, this does the right thing. If you run multiple processes, you might need to change `inf-clojure-buffer` to whichever process buffer you want to use. -## Configuration options - -In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely -configurable. - -You can see all the configuration options available using the command -`M-x customize-group RET inf-clojure`. - -The supported repl-features are in an alist called -`inc-clojure-repl-features` and it has the following shape: - -```emacs-lisp -'((cljs . ((doc . "(cljs.repl/doc %s)") - (source . "(cljs.repl/source %s)") - (arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))") - (apropos . "(cljs.repl/apropos \"%s\")") - (ns-vars . "(cljs.repl/dir %s)") - (set-ns . "(in-ns '%s)") - (macroexpand . "(cljs.core/macroexpand '%s)") - (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)")))) -``` - -If you want to add a new repl type, just `(add-to-list -'inf-clojure-repl-features (cons new-repl-type '((doc -. "(myrepl/doc-command %s") ...)))` - -If you want to update a specific form there is a function -`inf-clojure-update-repl-feature` which can be used like so: - -```emacs-lisp -(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")") -``` - #### REPL Type -An `inf-clojure` REPL can be of different types: Clojure, -ClojureScript, Lumo and Planck are all potentially valid options. - -At the moment, the default Clojure REPL, the Lumo REPL, the Planck -REPL and the Joker REPL are supported. +An `inf-clojure` REPL has an associated type. The available types are +`(mapcar 'car inf-clojure-repl-features) ->> (cljs lumo planck joker +clojure babashka)` What does it mean that a REPL type is supported - well it means that `inf-clojure` would use the proper code internally to power commands @@ -284,15 +278,6 @@ and can't be implemented in a REPL-independent way. At startup and uses this type to dispatch the proper code for the respective REPL type. -By default `inf-clojure` would start a standard Clojure REPL using -`lein` or `boot` but you can easily change this. To boot some other REPL just use the -right launch command (or connect to the REPL via a socket). For example, for -Lumo just add the following in your `.dir-locals.el`: - -```emacs-lisp -((nil . ((inf-clojure-boot-cmd . "lumo -d")))) ;; inf-clojure-lein-cmd if you are using Leiningen -``` - #### ElDoc `eldoc-mode` is supported in Clojure source buffers and `*inferior-clojure*` @@ -315,16 +300,54 @@ 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`, `inf-clojure-completion-form-planck` and -`inf-clojure-completion-form-joker` - 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 +Code completion is a tricky aspect if you are trying to be as close to +a generic repl as possible. Planck and lumo repl implementations +explicitly provide completion functions in their repl namespaces. For +clojure, you will need to have a library on your classpath. If you are +using lein, you already have +[clojure-complete](https://github.com/ninjudd/clojure-complete). You +could alternatively use `compliment {:mvn/version "0.3.10"}`. + +```emacs-lisp +;; for clojure-complete +(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")") + +;; or +;; for compliment +(inf-clojure-update-feature 'clojure 'completion "(compliment.core/completions \"%s\")") + +``` + +If you give a form for the completion form, it is your responsibility +to ensure that this namespace is on the classpath and required. If +using lein, this is done for you with clojure-complete. If adding +compliment, the following sample deps.edn can conveniently add the dep +to your program. + +Sample deps.edn: + +```clojure +{:aliases {:compliment {:extra-deps {compliment {:mvn/version "0.3.10"}}}}} +``` + + +Use the startup command: `clojure -A:compliment`. Then require the ns +once so that the completion machinery will work: `(require +'compliment.core)`. Now tab completion should work. + +For more advanced customization, code completion is particularly open +to customization. Not only you can `setq` the customary +`inf-clojure-completion-form`, `inf-clojure-completion-form-lumo`, +`inf-clojure-completion-form-planck` and +`inf-clojure-completion-form-joker` - 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). +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 @@ -332,14 +355,6 @@ For an optimal Lumo experience the `-d` needs to be passed to Lumo when launched from the command line. This disable `readline` support 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`: - -```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 diff --git a/inf-clojure.el b/inf-clojure.el index ea25492..40aec1b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -76,11 +76,13 @@ ;; cljs goes after the selfhosts (cljs . "cljs.repl") (joker . "joker.repl") + (babashka . "babashka.classpath") (clojure . "clojure.core.server"))) (defvar inf-clojure-startup-forms '((clojure . "clojure") (cljs . "clojure -m cljs.main -r") - (planck . "planck") - (lumo . "lumo") + (planck . "planck -d") + (babashka . "bb") + (lumo . "lumo -d") (joker . "joker"))) (defvar inf-clojure-repl-features @@ -117,7 +119,8 @@ (ns-vars . "(planck.repl/dir %s)") (set-ns . "(in-ns '%s)") (macroexpand . "(macroexpand '%s)") - (macroexpand-1 . "(macroexpand-1 '%s)"))) + (macroexpand-1 . "(macroexpand-1 '%s)") + (completion . "(seq (js->clj (#'planck.repl/get-completions \"%s\")))"))) (joker . ((load . "(load-file \"%s\")") (doc . "(joker.repl/doc %s)") (arglists . @@ -130,6 +133,17 @@ (set-ns . "(in-ns '%s)") (macroexpand . "(macroexpand '%s)") (macroexpand-1 . "(macroexpand-1 '%s)"))) + (babashka . ((load . "(clojure.core/load-file \"%s\")") + (doc . "(clojure.repl/doc %s)") + (source . "(clojure.repl/source %s)") + (arglists . + "(try (-> '%s clojure.core/resolve clojure.core/meta :arglists) + (catch Throwable e nil))") + (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))") + (ns-vars . "(clojure.repl/dir %s)") + (set-ns . "(clojure.core/in-ns '%s)") + (macroexpand . "(clojure.core/macroexpand '%s)") + (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))) (clojure . ((load . "(clojure.core/load-file \"%s\")") (doc . "(clojure.repl/doc %s)") (source . "(clojure.repl/source %s)") @@ -1292,6 +1306,7 @@ Return the number of nested sexp the point was over or after." (defun inf-clojure-eldoc () "Backend function for eldoc to show argument list in the echo area." + ;; todo: this never gets unset once connected and is a lie (when (and (inf-clojure-connected-p) ;; don't clobber an error message in the minibuffer (not (member last-command '(next-error previous-error)))) diff --git a/todo.org b/todo.org index fd6052f..1495a54 100644 --- a/todo.org +++ b/todo.org @@ -41,10 +41,10 @@ I really want something similar to ~(defprotocol Inf-clojure-REPL (doc ...)(sour ** TODO Nicer interface to create a command Right now everything is just a format string with a _single_ ~%s~ in it and that's called with ~(format feature-form e)~ where ~e~ is a symbol, or a form, or a whatever makes sense for that type of feature. This isn't super elegant although it does keep inf-clojure honest in that _all_ it does it format commands to ask a simple repl. But there could probably be a better way. -** TODO Simpler way to define an implementation +** DONE 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 +** DONE 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? @@ -78,3 +78,6 @@ inf-clojure and CIDER are fighting over the keymappings. I've been doing a bit o (remove-hook 'clojure-mode-hook #'cider-mode)) #+END_SRC Seems a bit heavy handed but its working for me so far. + +** TODO is disabling color still required? + in the readme it mentions that color should be turned off. in my usage I haven't run into this problem at all. perhaps no longer true? From 1c8429a9563a9e09028be1936ee7cf94cf75dfd0 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 19 Apr 2020 19:16:32 +0300 Subject: [PATCH 063/189] Bump the development version --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 40aec1b..35f8b74 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 2.3.0-snapshot +;; Version: 3.0.0-snapshot ;; Package-Requires: ((emacs "24.4") (clojure-mode "5.11")) ;; This file is part of GNU Emacs. From 3e7ca33cd68ac4a09e459e878b6fb65781c994d9 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 19 Apr 2020 19:42:47 +0300 Subject: [PATCH 064/189] Add lein and boot to the startup-forms --- inf-clojure.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 35f8b74..fe98943 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -78,7 +78,10 @@ (joker . "joker.repl") (babashka . "babashka.classpath") (clojure . "clojure.core.server"))) -(defvar inf-clojure-startup-forms '((clojure . "clojure") + +(defvar inf-clojure-startup-forms '((lein . "lein repl") + (boot . "boot repl") + (clojure . "clojure") (cljs . "clojure -m cljs.main -r") (planck . "planck -d") (babashka . "bb") From 1bac8febe3665f07cbc1dbe30f72390c78b76867 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 19 Apr 2020 19:45:27 +0300 Subject: [PATCH 065/189] Tweak some messages --- inf-clojure.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index fe98943..85146dd 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -175,7 +175,7 @@ If no-error is truthy don't error if feature is not present." "Get FEATURE based on repl type for PROC." (let* ((repl-type (or (with-current-buffer (process-buffer proc) inf-clojure-repl-type) - (error "Repl type is not known")))) + (error "REPL type is not known")))) (inf-clojure--get-feature repl-type feature no-error))) (defun inf-clojure--update-feature (repl-type feature form) @@ -187,7 +187,7 @@ that can be set as `inf-clojure-repl-features'." (if original (cons (cons repl-type (cons (cons feature form) (assoc-delete-all feature original))) (assoc-delete-all repl-type inf-clojure-repl-features)) - (error "Attempted to update %s form of unknown repl type %s" + (error "Attempted to update %s form of unknown REPL type %s" (symbol-name feature) (symbol-name repl-type))))) @@ -234,7 +234,7 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte (let* ((proc (inf-clojure-proc)) (types (mapcar #'car inf-clojure-repl-features)) (type-to-set (intern - (completing-read "Set repl type:" + (completing-read "Set REPL type:" (sort (mapcar #'symbol-name types) #'string-lessp))))) (with-current-buffer (process-buffer proc) (setq-local inf-clojure-repl-type type-to-set)))) @@ -689,7 +689,7 @@ from `inf-clojure-mode-hook' (after the `comint-mode-hook' is run). \(Type \\[describe-mode] in the process buffer for a list of commands.)" (interactive (list (or inf-clojure-custom-startup - (completing-read "Clojure startup command: " + (completing-read "Select Clojure REPL startup command: " (mapcar #'cdr inf-clojure-startup-forms) nil 'confirm-after-completion)))) From 799d93788cc1cbe4c9924e216a7e6ce9cf389376 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 20 Apr 2020 20:09:48 +0300 Subject: [PATCH 066/189] Improve the README a bit --- README.md | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 8518f9c..ef82e4a 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,21 @@ This package provides basic interaction with a Clojure subprocess (REPL). It's based on ideas from the popular `inferior-lisp` package. -`inf-clojure` aims to expose the extensive self-documenting features -of Clojure repls into an emacs package. Inf-clojure does not require -middleware or special tooling. Inf-clojure supports the following -repls: - -- Clojure -- ClojureScript -- planck -- lumo -- joker -- babashka - `inf-clojure` has two components - a nice REPL buffer (`inf-clojure`) (`inf-clojure-minor-mode`), which extends `clojure-mode` with commands to evaluate forms directly in the REPL. +`inf-clojure` aims to expose the extensive self-documenting features of Clojure +REPLs via an Emacs package. `inf-clojure` is extremely simple and does not require special tooling. +It supports the following REPLs: + +- Clojure +- ClojureScript +- [Planck](http://planck-repl.org/) +- [Lumo](https://github.com/anmonteiro/lumo) +- [Joker](https://joker-lang.org/) +- [babashka](https://github.com/borkdude/babashka) + `inf-clojure` provides a set of essential features for interactive Clojure(Script) development: @@ -38,12 +37,6 @@ Clojure(Script) development: * Require `:reload`/`:reload-all` * Support connecting to socket REPLs -In addition to the standard Clojure and ClojureScript REPLs, `inf-clojure` supports also: - -* [Lumo](https://github.com/anmonteiro/lumo) -* [Planck](http://planck-repl.org/) -* [Joker](https://joker-lang.org/) - For a more powerful/full-featured solution see [CIDER](https://github.com/clojure-emacs/cider). ## Rationale @@ -97,15 +90,15 @@ short of havoc.** ## Basic Usage 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 +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. -If you've already started a socket repl, use `M-x inf-clojure-connect` -and enter the host and port numbers. +If you've already started a socket REPL server, use `M-x inf-clojure-connect` +and enter its host and port numbers. -Inf-clojure aims to be very simple and offer tooling that the repl +Inf-clojure aims to be very simple and offer tooling that the REPL itself exposes. A few commands are: - eval last sexp `C-x C-e` From bcd806a83740c7a0ed094ca295071f0dea1021b4 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 22 Apr 2020 09:10:09 +0300 Subject: [PATCH 067/189] Unify references to the term REPL --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ef82e4a..8f5cdac 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ itself exposes. A few commands are: - 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` +- insert top level form into REPL `C-c C-j d` 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 @@ -130,7 +130,7 @@ or by setting them in in your init file. You can see all the configuration options available using the command `M-x customize-group RET inf-clojure`. -The supported repl-features are in an alist called +The supported REPL-features are in an alist called `inc-clojure-repl-features` and it has the following shape: ```emacs-lisp @@ -144,7 +144,7 @@ The supported repl-features are in an alist called (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)")))) ``` -If you want to add a new repl type, just `(add-to-list +If you want to add a new REPL type, just `(add-to-list 'inf-clojure-repl-features (cons new-repl-type '((doc . "(myrepl/doc-command %s") ...)))` since the datastructure is just an alist of alists. @@ -163,7 +163,7 @@ connect to a socket REPL, terminal REPLs are inherently hard to work with and support will be deprecated in the foreseeable future. If you use the same project often, make a dir-locals file with this information in `inf-clojure-custom-startup`. -Note that if you decide _NOT_ to use the socket repl, it is highly recommended +Note that if you decide _NOT_ to use the socket REPL, it is highly recommended you disable output coloring and/or readline facilities: `inf-clojure` does not filter out ASCII escape characters at the moment and will not behave correctly. @@ -294,8 +294,8 @@ You can leave it enabled, it just won't show anything in the echo area. #### Code Completion Code completion is a tricky aspect if you are trying to be as close to -a generic repl as possible. Planck and lumo repl implementations -explicitly provide completion functions in their repl namespaces. For +a generic REPL as possible. Planck and lumo REPL implementations +explicitly provide completion functions in their REPL namespaces. For clojure, you will need to have a library on your classpath. If you are using lein, you already have [clojure-complete](https://github.com/ninjudd/clojure-complete). You @@ -353,13 +353,13 @@ in order to play nicely with emacs. ### 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 +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 +`(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 +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. From f63c60961bec154b21b6de3d8e0af82e61c91b23 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 22 Apr 2020 09:11:32 +0300 Subject: [PATCH 068/189] Fix a typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f5cdac..7ad6334 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ The supported REPL-features are in an alist called If you want to add a new REPL type, just `(add-to-list 'inf-clojure-repl-features (cons new-repl-type '((doc -. "(myrepl/doc-command %s") ...)))` since the datastructure is just an +. "(myrepl/doc-command %s") ...)))` since the data structure is just an alist of alists. If you want to update a specific form there is a function From fe22ce2bd6848e9ed69e8349c518f90a79a5c101 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 22 Apr 2020 09:45:53 +0300 Subject: [PATCH 069/189] Add a couple of disclaimers and a basic TOC --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ad6334..83fcbe1 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,23 @@ It's based on ideas from the popular `inferior-lisp` package. (`inf-clojure-minor-mode`), which extends `clojure-mode` with commands to evaluate forms directly in the REPL. +**This documentation tracks the `master` branch of `inf-clojure`. Some of +the features and settings discussed here might not be available in +older releases (including the current stable release). Please, consult +the relevant git tag (e.g. 2.2.0) if you need documentation for a +specific `inf-clojure` release.** +*** + +- [Overview](#overview) +- [Rationale](#rationale) +- [Installation](#installation) +- [Basic Usage](#basic-usage) +- [Configuration](#configuration) +- [Troubleshooting](#troubleshooting) +- [License](#license) + +## Overview + `inf-clojure` aims to expose the extensive self-documenting features of Clojure REPLs via an Emacs package. `inf-clojure` is extremely simple and does not require special tooling. It supports the following REPLs: @@ -117,7 +134,9 @@ point. You can, however, change this behaviour by invoking such commands with a prefix argument. For instance: `C-u C-c C-v` will ask for the symbol you want to show the docstring for. -## Configuration options +## Configuration + +**Note:** The configuration options were changed massively in `inf-clojure` 3.0. In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely configurable. From 8fb19294207e0a6fd294a4e9c85b9d1b58ab9c15 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 25 Apr 2020 00:54:50 -0500 Subject: [PATCH 070/189] Set REPL type from startup form, prompt, or defcustom at startup also prevent these when `inf-clojure` is invoked with a prefix arg --- CHANGELOG.md | 5 +++ README.md | 21 ++++++++++++ inf-clojure.el | 90 +++++++++++++++++++++++--------------------------- todo.org | 18 +++++----- 4 files changed, 77 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe24b9..3c5b3ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## master (unreleased) +### New features + +* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom +* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Prefix on `inf-clojure` to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type. + ## 2.2.0 (2020-04-15) ### New features diff --git a/README.md b/README.md index 83fcbe1..d1ddc19 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,27 @@ for the symbol you want to show the docstring for. ## Configuration +## Most Common Configuration + +Most likely you will want to set the startup command and the repl +type. This is most easily set with the follow dir-locals + +```emacs-lisp +((nil + (inf-clojure-custom-startup . "clojure -A:compliment") + (inf-clojure-custom-repl-type . clojure))) +``` + +There are two important commands here: +1. `inf-clojure-custom-startup`: Which startup command to use so + inf-clojure can run the inferior process and +2. `inf-clojure-custom-repl-type`: Which repl type it is so + inf-clojure knows how to format commands to the repl + +If these are set and you wish to prevent inf-clojure from using them, +use a prefix arg when invoking `inf-clojure`. + +### All Configuration **Note:** The configuration options were changed massively in `inf-clojure` 3.0. In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely diff --git a/inf-clojure.el b/inf-clojure.el index 85146dd..7399cc0 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -71,14 +71,6 @@ (require 'subr-x) (require 'seq) -(defvar inf-clojure-recognize-alist '((lumo . "lumo.repl") - (planck . "planck.repl") - ;; cljs goes after the selfhosts - (cljs . "cljs.repl") - (joker . "joker.repl") - (babashka . "babashka.classpath") - (clojure . "clojure.core.server"))) - (defvar inf-clojure-startup-forms '((lein . "lein repl") (boot . "boot repl") (clojure . "clojure") @@ -217,37 +209,13 @@ either `setq-local` or an entry in `.dir-locals.el`." ) "Global lock for protecting against proc filter race conditions. See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filter.html") -(defun inf-clojure--detect-repl-type (proc) - "Identifies the current REPL type for PROC." - (when (not inf-clojure--repl-type-lock) - (let ((inf-clojure--repl-type-lock t)) - (or (seq-some (lambda (r) - (when (inf-clojure--some-response-p - proc (format "(find-ns '%s)" (cdr r))) - (car r))) - inf-clojure-recognize-alist) - 'clojure)))) - -(defun inf-clojure-set-repl-type () +(defun inf-clojure--prompt-repl-type () "Set the REPL type to one of the available implementations." (interactive) - (let* ((proc (inf-clojure-proc)) - (types (mapcar #'car inf-clojure-repl-features)) - (type-to-set (intern - (completing-read "Set REPL type:" - (sort (mapcar #'symbol-name types) #'string-lessp))))) - (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." - ;; 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)) - inf-clojure-repl-type))) + (let ((types (mapcar #'car inf-clojure-repl-features))) + (intern + (completing-read "Set REPL type:" + (sort (mapcar #'symbol-name types) #'string-lessp))))) (defgroup inf-clojure nil "Run an external Clojure process (REPL) in an Emacs buffer." @@ -390,6 +358,19 @@ Can be a cons pair of (host . port) where host is a string and port is an integer, or a string to startup an interpreter like \"planck\".") +(defcustom inf-clojure-custom-repl-type + nil + "REPL type to use for inf-clojure process buffer. +Should be a symbol that is a key in `inf-clojure-repl-features'." + :package-version '(inf-clojure . "3.0.0") + :type '(choice (const :tag "clojure" clojure) + (const :tag "cljs" cljs) + (const :tag "lumo" lumo) + (const :tag "planck" planck) + (const :tag "joker" joker) + (const :tag "babashka" babashka) + (const :tag "determine at startup" nil))) + (defun inf-clojure--whole-comment-line-p (string) "Return non-nil iff STRING is a whole line semicolon comment." (string-match-p "^\s*;" string)) @@ -424,7 +405,6 @@ always be preferred over `comint-send-string`. It delegates to `comint-simple-send` so it always appends a newline at the end of the string for evaluation. Refer to `comint-simple-send` for customizations." - (inf-clojure--set-repl-type proc) (let ((sanitized (inf-clojure--sanitize-command string))) (inf-clojure--log-string sanitized "----CMD->") (comint-send-string proc sanitized))) @@ -449,7 +429,6 @@ Clojure to load that file." "Return the form to query the Inf-Clojure PROC for reloading a namespace. If you are using REPL types, it will pickup the most appropriate `inf-clojure-reload-form` variant." - (inf-clojure--set-repl-type proc) inf-clojure-reload-form) (defcustom inf-clojure-reload-all-form "(require '%s :reload-all)" @@ -468,7 +447,6 @@ Clojure to load that file." "Return the form to query the Inf-Clojure PROC for :reload-all of a namespace. If you are using REPL types, it will pickup the most appropriate `inf-clojure-reload-all-form` variant." - (inf-clojure--set-repl-type proc) inf-clojure-reload-all-form) (defcustom inf-clojure-prompt "^[^=> \n]+=> *" @@ -681,14 +659,23 @@ to suppress the usage of the target buffer discovery logic." ;;;###autoload (defun inf-clojure (cmd) "Run an inferior Clojure process, input and output via buffer `*inf-clojure*'. -If there is a process already running in `*inf-clojure*', just switch -to that buffer. -With argument, allows you to edit the CMD used to launch -it (default is value of `inf-clojure-*-cmd'). Runs the hooks -from `inf-clojure-mode-hook' (after the `comint-mode-hook' is -run). -\(Type \\[describe-mode] in the process buffer for a list of commands.)" - (interactive (list (or inf-clojure-custom-startup +If there is a process already running in `*inf-clojure*', just +switch to that buffer. + +CMD is a string which serves as the startup command or a cons of +host and port. + + Prompts user for repl startup command and repl type if not +inferrable from startup command. Uses +`inf-clojure-custom-repl-type' and `inf-clojure-custom-startup' +if those are set. Use a prefix to prevent using these when they +are set. + + Runs the hooks from `inf-clojure-mode-hook' (after the +`comint-mode-hook' is run). \(Type \\[describe-mode] in the +process buffer for a list of commands.)" + (interactive (list (or (unless current-prefix-arg + inf-clojure-custom-startup) (completing-read "Select Clojure REPL startup command: " (mapcar #'cdr inf-clojure-startup-forms) nil @@ -698,11 +685,16 @@ run). (let ((default-directory (inf-clojure-project-root)) (cmdlist (if (consp cmd) (list cmd) - (split-string cmd)))) + (split-string cmd))) + (repl-type (or (unless prefix-arg + inf-clojure-custom-repl-type) + (car (rassoc cmd inf-clojure-startup-forms)) + (inf-clojure--prompt-repl-type)))) (message "Starting Clojure REPL via `%s'..." cmd) (with-current-buffer (apply #'make-comint "inf-clojure" (car cmdlist) nil (cdr cmdlist)) (inf-clojure-mode) + (setq-local inf-clojure-repl-type repl-type) (hack-dir-local-variables-non-file-buffer)))) (setq inf-clojure-buffer "*inf-clojure*") (if inf-clojure-repl-use-same-window diff --git a/todo.org b/todo.org index 1495a54..811c287 100644 --- a/todo.org +++ b/todo.org @@ -1,6 +1,6 @@ * Core -** TODO set repl type on connection not first command +** DONE set repl type on connection not first command For some reason ~inf-clojure--set-repl-type~ is called in: 1. inf-clojure--send-string 2. inf-clojure-reload-form @@ -11,13 +11,6 @@ Seems better to do this on the two different connection methods and then be done ** 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. - -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? - ** DONE Better dispatch for the implementations Right now the functions are kinda clunky cond statements: #+BEGIN_SRC emacs-lisp @@ -65,6 +58,9 @@ The source primitive is quite nice but we most likely need a way to navigate to ** TODO PREPL Be nice to implement this now that we have parseedn in elisp to understand edn. + +** DONE inhibit custom repl-type and startup form +its nice to have these in dir-locals to just start up. but if you normally have ~clojure -m cljs.main -r~ as the startup command but you want to crank up a clj repl there's no way without removing those dir locals. * Nice-to-haves ** TODO Put repl type in modeline Rather than just ~*inf-clojure*~ we could put the repl type. Make it easy to follow and makes it easy to see when it gets it wrong. @@ -81,3 +77,9 @@ Seems a bit heavy handed but its working for me so far. ** TODO is disabling color still required? in the readme it mentions that color should be turned off. in my usage I haven't run into this problem at all. perhaps no longer true? +** 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. + +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? From 1ba64169a85906ad7973d7081112859ca21b3cdb Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 25 Apr 2020 10:50:41 +0300 Subject: [PATCH 071/189] Tweak the changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c5b3ed..decc2f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ ### New features -* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom -* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Prefix on `inf-clojure` to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type. +* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom. +* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type. ## 2.2.0 (2020-04-15) From 58150d702a46f65386775cbf37f0962ce7581da4 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 25 Apr 2020 11:27:59 +0300 Subject: [PATCH 072/189] Improve some wording in the README --- README.md | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d1ddc19..8f05c00 100644 --- a/README.md +++ b/README.md @@ -136,10 +136,23 @@ for the symbol you want to show the docstring for. ## Configuration -## Most Common Configuration +**Note:** The configuration options were changed massively in `inf-clojure` 3.0. + +In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely +configurable. + +You can 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) +or by setting them in in your init file. + +You can see all the configuration options available using the command +`M-x customize-group RET inf-clojure`. + +### Startup Most likely you will want to set the startup command and the repl -type. This is most easily set with the follow dir-locals +type. This is most easily set with the following `dir-locals.el`: ```emacs-lisp ((nil @@ -147,28 +160,18 @@ type. This is most easily set with the follow dir-locals (inf-clojure-custom-repl-type . clojure))) ``` -There are two important commands here: -1. `inf-clojure-custom-startup`: Which startup command to use so - inf-clojure can run the inferior process and -2. `inf-clojure-custom-repl-type`: Which repl type it is so - inf-clojure knows how to format commands to the repl +**Note:** This file has to be in the directory in which you're invoking `inf-clojure`. -If these are set and you wish to prevent inf-clojure from using them, -use a prefix arg when invoking `inf-clojure`. - -### All Configuration -**Note:** The configuration options were changed massively in `inf-clojure` 3.0. +There are two important configuration variables here: -In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely -configurable. +1. `inf-clojure-custom-startup`: Which startup command to use so + inf-clojure can run the inferior Clojure process (REPL). +2. `inf-clojure-custom-repl-type`: The type of the REPL started by the above command (e.g. `lumo`). -You can 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) -or by setting them in in your init file. +If these are set and you wish to prevent inf-clojure from using them, +use a prefix arg when invoking `inf-clojure` (`C-u M-x inf-clojure`). -You can see all the configuration options available using the command -`M-x customize-group RET inf-clojure`. +### REPL Features The supported REPL-features are in an alist called `inc-clojure-repl-features` and it has the following shape: From c9681d0f5abf4103fbb4853013ba45dad78860f1 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 25 Apr 2020 17:56:27 +0300 Subject: [PATCH 073/189] Tweak some wording --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8f05c00..663ded9 100644 --- a/README.md +++ b/README.md @@ -151,8 +151,10 @@ You can see all the configuration options available using the command ### Startup -Most likely you will want to set the startup command and the repl -type. This is most easily set with the following `dir-locals.el`: +While `inf-clojure` is capable of starting many common REPLs out of the box it's +fairly likely you will want to set some custom REPL startup command +(e.g. because you need to include some `tools.deps` profile) and the REPL type +that goes with it. This is most easily achieved with the following `dir-locals.el`: ```emacs-lisp ((nil @@ -220,7 +222,6 @@ option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj) ... ``` - #### Clojure Command Line Socket REPL If you have the new [Clojure CLI tools][] installed you can use the `clojure` command: From 977e176c3392fcc70b1eedce843b3251468771eb Mon Sep 17 00:00:00 2001 From: dpsutton Date: Sat, 25 Apr 2020 11:18:55 -0500 Subject: [PATCH 074/189] Mark this package as not part of Emacs --- inf-clojure.el | 2 +- test/inf-clojure-tests.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 7399cc0..fed299b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -9,7 +9,7 @@ ;; Version: 3.0.0-snapshot ;; Package-Requires: ((emacs "24.4") (clojure-mode "5.11")) -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index bf49c30..7821c06 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -8,7 +8,7 @@ ;; Keywords: processes, clojure ;; Package-Requires: ((emacs "24.4") (clojure-mode "5.3")) -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by From f29861204ddbb032b425c7d693e8c006b7b027c6 Mon Sep 17 00:00:00 2001 From: dpsutton Date: Sat, 25 Apr 2020 11:48:38 -0500 Subject: [PATCH 075/189] [Fix #173] Use clojure-mode project detection (#176) We also get as an extra benefit project type caching and all of the project types supported by clojure-mode. --- CHANGELOG.md | 1 + inf-clojure.el | 19 ++----------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index decc2f5..0c85fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### New features +* [#173](https://github.com/clojure-emacs/inf-clojure/issues/173): Use clojure-mode project detection instead of duplicate version in inf-clojure * [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom. * [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type. diff --git a/inf-clojure.el b/inf-clojure.el index fed299b..a78774a 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -595,21 +595,6 @@ to continue it." (inf-clojure-chomp (concat "\n" (inf-clojure-remove-subprompts str)))) (t str))) -(defvar inf-clojure-project-root-files - '("project.clj" "build.boot" "deps.edn" "shadow-cljs.edn") - "A list of files that can be considered project markers.") - -(defun inf-clojure-project-root () - "Retrieve the root directory of a project if available. - -Fallback to `default-directory.' if not within a project." - (or (car (remove nil - (mapcar (lambda - (file) - (locate-dominating-file default-directory file)) - inf-clojure-project-root-files))) - default-directory)) - (defun inf-clojure-clear-repl-buffer () "Clear the REPL buffer." (interactive) @@ -682,7 +667,7 @@ process buffer for a list of commands.)" 'confirm-after-completion)))) (if (not (comint-check-proc "*inf-clojure*")) ;; run the new process in the project's root when in a project folder - (let ((default-directory (inf-clojure-project-root)) + (let ((default-directory (clojure-project-dir)) (cmdlist (if (consp cmd) (list cmd) (split-string cmd))) @@ -957,7 +942,7 @@ STRING if present." (prin1-to-string (substring-no-properties string)))) nil (expand-file-name inf-clojure--log-file-name - (inf-clojure-project-root)) + (clojure-project-dir)) 'append 'no-annoying-write-file-in-minibuffer))) From b88de63947564cd52eaf7bac20cdf7b8230ea2c8 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 22 May 2020 20:37:30 +0300 Subject: [PATCH 076/189] Tweak a docstring --- inf-clojure.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index a78774a..b0570a0 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -651,9 +651,9 @@ CMD is a string which serves as the startup command or a cons of host and port. Prompts user for repl startup command and repl type if not -inferrable from startup command. Uses -`inf-clojure-custom-repl-type' and `inf-clojure-custom-startup' -if those are set. Use a prefix to prevent using these when they +inferrable from startup command. Uses `inf-clojure-custom-repl-type' +and `inf-clojure-custom-startup' if those are set. +Use a prefix to prevent using these when they are set. Runs the hooks from `inf-clojure-mode-hook' (after the From f1c8323de7380e2f810017596a361b72c156bccf Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 22 May 2020 20:37:46 +0300 Subject: [PATCH 077/189] Fix some wording --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 663ded9..ff6ef6e 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ This package provides basic interaction with a Clojure subprocess (REPL). It's based on ideas from the popular `inferior-lisp` package. -`inf-clojure` has two components - a nice REPL buffer (`inf-clojure`) -(`inf-clojure-minor-mode`), which extends `clojure-mode` with commands -to evaluate forms directly in the REPL. +`inf-clojure` has two components - a nice REPL buffer (`inf-clojure`) and a REPL +interaction minor mode (`inf-clojure-minor-mode`), which extends `clojure-mode` +with commands to evaluate forms directly in the REPL. **This documentation tracks the `master` branch of `inf-clojure`. Some of the features and settings discussed here might not be available in From 5abac0b0f4f88ab0fac6884f11e28a6d0e1590af Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 22 May 2020 20:43:00 +0300 Subject: [PATCH 078/189] Tweak the REPL type documentation --- README.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ff6ef6e..8b49c2d 100644 --- a/README.md +++ b/README.md @@ -303,17 +303,21 @@ whichever process buffer you want to use. #### REPL Type -An `inf-clojure` REPL has an associated type. The available types are -`(mapcar 'car inf-clojure-repl-features) ->> (cljs lumo planck joker -clojure babashka)` - -What does it mean that a REPL type is supported - well it means that -`inf-clojure` would use the proper code internally to power commands -like definition lookup and friends. Those differ from REPL to REPL -and can't be implemented in a REPL-independent way. At startup -`inf-clojure` tries to detect the type of the REPL that was started -and uses this type to dispatch the proper code for the respective REPL -type. +An `inf-clojure` REPL has an associated type. The available types can be +obtained from `inf-clojure-repl-features`: + +```emacs-lisp +(mapcar 'car inf-clojure-repl-features) + +;; => (cljs lumo planck joker clojure babashka) +``` + +What does it mean that a REPL type is supported? Well, it means that +`inf-clojure` would use the proper Clojure(Script) code internally to power +commands like definition lookup and friends. Those differ from REPL to REPL and +can't be implemented in a REPL-independent way. The REPL type is inferred on +startup when using the `inf-clojure` command or is specified manually when using +`inf-clojure-connect`. #### ElDoc From 23492b5bc7993e577ceb5a2f48805d3a02a1f501 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 22 May 2020 20:43:25 +0300 Subject: [PATCH 079/189] Trim some whitespace --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8b49c2d..a4d34c5 100644 --- a/README.md +++ b/README.md @@ -279,11 +279,11 @@ one Clojure process around. This is determined by the global variable `inf-cloju Suppose you have three inferior Clojures running: ``` - Buffer Process - ------ ------- - foo inf-clojure - bar inf-clojure<2> - *inf-clojure* inf-clojure<3> +Buffer Process +------ ------- +foo inf-clojure +bar inf-clojure<2> +*inf-clojure* inf-clojure<3> ``` If you do a `inf-clojure-eval-defun` command on some Clojure source code, From 787400fea26a813d4a105a26efde14973e6a78fe Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 16 May 2020 11:23:42 -0500 Subject: [PATCH 080/189] [Fix #178] Ensure there is a directory for comint (thanks mcphailm) If there was no containing directory with a project file the default-directory would be nil. This leads to problems in starting up inf-clojure and also annoyingly seems to set an error in a timer: > Error running timer 'auto-revert-buffers (wrong-type-argument string nil) --- CHANGELOG.md | 4 ++++ inf-clojure.el | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c85fa4..181398b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ * [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom. * [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type. +### Bugs fixed + +* [#178](https://github.com/clojure-emacs/inf-clojure/issues/178): Ensure a valid directory is used when starting process. + ## 2.2.0 (2020-04-15) ### New features diff --git a/inf-clojure.el b/inf-clojure.el index b0570a0..a100ed9 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -667,7 +667,7 @@ process buffer for a list of commands.)" 'confirm-after-completion)))) (if (not (comint-check-proc "*inf-clojure*")) ;; run the new process in the project's root when in a project folder - (let ((default-directory (clojure-project-dir)) + (let ((default-directory (or (clojure-project-dir) default-directory)) (cmdlist (if (consp cmd) (list cmd) (split-string cmd))) From c30f90e1e15e13d41bada69e23bbb2354c9a5dd2 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 16 May 2020 11:14:37 -0500 Subject: [PATCH 081/189] Ensure comint-truncate-buffer call is from the repl buffer --- inf-clojure.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index a100ed9..992234f 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -598,8 +598,11 @@ to continue it." (defun inf-clojure-clear-repl-buffer () "Clear the REPL buffer." (interactive) - (let ((comint-buffer-maximum-size 0)) - (comint-truncate-buffer))) + (with-current-buffer (if (derived-mode-p 'inf-clojure-mode) + (current-buffer) + inf-clojure-buffer) + (let ((comint-buffer-maximum-size 0)) + (comint-truncate-buffer)))) (defun inf-clojure-switch-to-repl (eob-p) "Switch to the inferior Clojure process buffer. From b601d48eb24d81fca86afdb92d1520b64af0f41b Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Thu, 16 Jul 2020 10:44:10 +0300 Subject: [PATCH 082/189] Tweak the README a bit --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a4d34c5..73dac8b 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ use a prefix arg when invoking `inf-clojure` (`C-u M-x inf-clojure`). ### REPL Features The supported REPL-features are in an alist called -`inc-clojure-repl-features` and it has the following shape: +`inf-clojure-repl-features` and it has the following shape: ```emacs-lisp '((cljs . ((doc . "(cljs.repl/doc %s)") @@ -189,10 +189,17 @@ The supported REPL-features are in an alist called (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)")))) ``` -If you want to add a new REPL type, just `(add-to-list -'inf-clojure-repl-features (cons new-repl-type '((doc -. "(myrepl/doc-command %s") ...)))` since the data structure is just an -alist of alists. +If you want to add a new REPL type, just do something like: + +``` emacs-lisp +(add-to-list 'inf-clojure-repl-features + (cons new-repl-type '((doc . "(myrepl/doc-command %s") + (source . "...") + ...))) +``` + +The `inf-clojure-repl-features` data structure is just an +alist of alists, so you can manipulate it in numerous ways. If you want to update a specific form there is a function `inf-clojure-update-repl-feature` which can be used like so: From d7eb9ce315e5753e651b539501c65d9c9f425dfb Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Thu, 16 Jul 2020 10:44:24 +0300 Subject: [PATCH 083/189] Update the changelog --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 181398b..9187e62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,14 @@ ### New features -* [#173](https://github.com/clojure-emacs/inf-clojure/issues/173): Use clojure-mode project detection instead of duplicate version in inf-clojure +* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type`. +* Made it possible to add user-defined REPL types (by modifying `inf-clojure-repl-features`). + +### Changes + +* **(Breaking)** Restructure massively the configuration. See `inf-clojure-repl-features` for details. * [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom. -* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type. +* [#173](https://github.com/clojure-emacs/inf-clojure/issues/173): Use clojure-mode's project detection instead of duplicate version in inf-clojure. ### Bugs fixed From 917ee77182870dbb4ebc35ea81fa4330090e95d3 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 18 Jul 2020 23:11:17 +0300 Subject: [PATCH 084/189] Improve the README a bit --- README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 73dac8b..6f85e00 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ You can see all the configuration options available using the command ### Startup -While `inf-clojure` is capable of starting many common REPLs out of the box it's +While `inf-clojure` is capable of starting many common REPLs out of the box, it's fairly likely you will want to set some custom REPL startup command (e.g. because you need to include some `tools.deps` profile) and the REPL type that goes with it. This is most easily achieved with the following `dir-locals.el`: @@ -162,7 +162,8 @@ that goes with it. This is most easily achieved with the following `dir-locals.e (inf-clojure-custom-repl-type . clojure))) ``` -**Note:** This file has to be in the directory in which you're invoking `inf-clojure`. +**Note:** This file has to be in the directory in which you're invoking `inf-clojure` or a parent +directory. There are two important configuration variables here: @@ -235,8 +236,8 @@ If you have the new [Clojure CLI tools][] installed you can use the `clojure` co _do not use `clj` because it adds readline support_ -```shell -clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" +``` shellsession +$ 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`: @@ -260,6 +261,7 @@ information on how connect: ```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 @@ -270,6 +272,10 @@ 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`: +```emacs-lisp +((nil (inf-clojure-custom-startup "localhost" . 5555))) +``` + #### Multiple Process Support To run multiple Clojure processes, you start the first up @@ -328,6 +334,9 @@ startup when using the `inf-clojure` command or is specified manually when using #### ElDoc +**Note:** You can skip this section if you're using Emacs 26.1+, as `eldoc-mode` +is enabled by default there. + `eldoc-mode` is supported in Clojure source buffers and `*inferior-clojure*` buffers which are running a Clojure REPL. From 8be9cecc91b98a0e7047068d1623ec62a67d8bc2 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 18 Jul 2020 23:16:22 +0300 Subject: [PATCH 085/189] Use kbd-style keybindings everywhere --- inf-clojure.el | 52 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 992234f..de656d8 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -245,14 +245,14 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (defvar inf-clojure-mode-map (let ((map (copy-keymap comint-mode-map))) - (define-key map "\C-x\C-e" #'inf-clojure-eval-last-sexp) - (define-key map "\C-c\C-l" #'inf-clojure-load-file) - (define-key map "\C-c\C-a" #'inf-clojure-show-arglists) - (define-key map "\C-c\C-v" #'inf-clojure-show-var-documentation) - (define-key map "\C-c\C-s" #'inf-clojure-show-var-source) + (define-key map (kbd "C-x C-e") #'inf-clojure-eval-last-sexp) + (define-key map (kbd "C-c C-l") #'inf-clojure-load-file) + (define-key map (kbd "C-c C-a") #'inf-clojure-show-arglists) + (define-key map (kbd "C-c C-v") #'inf-clojure-show-var-documentation) + (define-key map (kbd "C-c C-s") #'inf-clojure-show-var-source) (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) - (define-key map "\C-c\M-o" #'inf-clojure-clear-repl-buffer) - (define-key map "\C-c\C-q" #'inf-clojure-quit) + (define-key map (kbd "C-c M-o") #'inf-clojure-clear-repl-buffer) + (define-key map (kbd "C-c C-q") #'inf-clojure-quit) (easy-menu-define inf-clojure-mode-menu map "Inferior Clojure REPL Menu" '("Inf-Clojure REPL" @@ -282,26 +282,26 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (defvar inf-clojure-minor-mode-map (let ((map (make-sparse-keymap))) - (define-key map "\M-\C-x" #'inf-clojure-eval-defun) ; Gnu convention - (define-key map "\C-x\C-e" #'inf-clojure-eval-last-sexp) ; Gnu convention - (define-key map "\C-c\C-e" #'inf-clojure-eval-last-sexp) - (define-key map "\C-c\C-c" #'inf-clojure-eval-defun) ; SLIME/CIDER style - (define-key map "\C-c\C-b" #'inf-clojure-eval-buffer) - (define-key map "\C-c\C-r" #'inf-clojure-eval-region) - (define-key map "\C-c\M-r" #'inf-clojure-reload) - (define-key map "\C-c\C-n" #'inf-clojure-eval-form-and-next) + (define-key map (kbd "C-M-x") #'inf-clojure-eval-defun) ; Gnu convention + (define-key map (kbd "C-x C-e") #'inf-clojure-eval-last-sexp) ; Gnu convention + (define-key map (kbd "C-c C-e") #'inf-clojure-eval-last-sexp) + (define-key map (kbd "C-c C-c") #'inf-clojure-eval-defun) ; SLIME/CIDER style + (define-key map (kbd "C-c C-b") #'inf-clojure-eval-buffer) + (define-key map (kbd "C-c C-r") #'inf-clojure-eval-region) + (define-key map (kbd "C-c M-r") #'inf-clojure-reload) + (define-key map (kbd "C-c C-n") #'inf-clojure-eval-form-and-next) (define-key map (kbd "C-c C-j") 'inf-clojure-insert-commands-map) - (define-key map "\C-c\C-z" #'inf-clojure-switch-to-repl) - (define-key map "\C-c\C-i" #'inf-clojure-show-ns-vars) + (define-key map (kbd "C-c C-z") #'inf-clojure-switch-to-repl) + (define-key map (kbd "C-c C-i") #'inf-clojure-show-ns-vars) (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) - (define-key map "\C-c\C-m" #'inf-clojure-macroexpand) - (define-key map "\C-c\C-l" #'inf-clojure-load-file) - (define-key map "\C-c\C-a" #'inf-clojure-show-arglists) - (define-key map "\C-c\C-v" #'inf-clojure-show-var-documentation) - (define-key map "\C-c\C-s" #'inf-clojure-show-var-source) - (define-key map "\C-c\M-n" #'inf-clojure-set-ns) - (define-key map "\C-c\C-q" #'inf-clojure-quit) - (define-key map "\C-c\M-c" #'inf-clojure-connect) + (define-key map (kbd "C-c C-m") #'inf-clojure-macroexpand) + (define-key map (kbd "C-c C-l") #'inf-clojure-load-file) + (define-key map (kbd "C-c C-a") #'inf-clojure-show-arglists) + (define-key map (kbd "C-c C-v") #'inf-clojure-show-var-documentation) + (define-key map (kbd "C-c C-s") #'inf-clojure-show-var-source) + (define-key map (kbd "C-c M-n") #'inf-clojure-set-ns) + (define-key map (kbd "C-c C-q") #'inf-clojure-quit) + (define-key map (kbd "C-c M-c") #'inf-clojure-connect) (easy-menu-define inf-clojure-minor-mode-menu map "Inferior Clojure Minor Mode Menu" '("Inf-Clojure" @@ -387,7 +387,7 @@ comments." (concat s "\n"))) lines " "))) -(defun inf-clojure--sanitize-command (command) +(defun inf-clojure--sanitinze-command (command) "Sanitize COMMAND for sending it to a process. An example of things that this function does is to add a final newline at the end of the form. Return an empty string if the From 53025bf63d0b8a65cac379e604578513c068f9a8 Mon Sep 17 00:00:00 2001 From: Chad Walstrom Date: Mon, 27 Jul 2020 12:44:26 -0500 Subject: [PATCH 086/189] Correct misspelled function. Fixes #181 --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index de656d8..5d7f71c 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -387,7 +387,7 @@ comments." (concat s "\n"))) lines " "))) -(defun inf-clojure--sanitinze-command (command) +(defun inf-clojure--sanitize-command (command) "Sanitize COMMAND for sending it to a process. An example of things that this function does is to add a final newline at the end of the form. Return an empty string if the From 4af94e66d423a110ca701bcac82aa349168869da Mon Sep 17 00:00:00 2001 From: Chad Walstrom Date: Mon, 27 Jul 2020 12:52:12 -0500 Subject: [PATCH 087/189] Fixed two checkdoc warnings --- inf-clojure.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 5d7f71c..f12d2bd 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -353,14 +353,14 @@ number (e.g. (\"localhost\" . 5555))." (defcustom inf-clojure-custom-startup nil - "Form to be used to start inf-clojure. + "Form to be used to start `inf-clojure'. Can be a cons pair of (host . port) where host is a string and port is an integer, or a string to startup an interpreter like \"planck\".") (defcustom inf-clojure-custom-repl-type nil - "REPL type to use for inf-clojure process buffer. + "REPL type to use for `inf-clojure' process buffer. Should be a symbol that is a key in `inf-clojure-repl-features'." :package-version '(inf-clojure . "3.0.0") :type '(choice (const :tag "clojure" clojure) From 477fd7c03a2d7d1c83628db54abf34f5337bc3db Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 28 Jul 2020 10:26:23 +0300 Subject: [PATCH 088/189] Tweak some wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f85e00..0cfb4dc 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ In Emacs terminology "inferior" process is a subprocess started by Emacs (it bei processes its output. As the Clojure socket REPL works in exactly the same manner `inf-clojure` can also interact with it. Functionality like code completion and eldoc is powered by evaluation of predefined code snippets that provide the necessary results. -As different Clojure REPLs have different capabilities, `inf-clojure` has to determine the type of a REPL and invoke +As different Clojure REPLs have different capabilities, `inf-clojure` tracks the type of a REPL and invokes the right code for each REPL type. ## Installation From 2c8e46b584be71fe1a585c9072da86382710dc59 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 1 Aug 2020 14:28:32 +0300 Subject: [PATCH 089/189] Release 3.0 --- CHANGELOG.md | 2 ++ inf-clojure.el | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9187e62..ad76f62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## 3.0.0 (2020-08-01) + ### New features * [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type`. diff --git a/inf-clojure.el b/inf-clojure.el index f12d2bd..62d9402 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 3.0.0-snapshot +;; Version: 3.0.0 ;; Package-Requires: ((emacs "24.4") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From e291da3cd0c11271ad7372594139974057612172 Mon Sep 17 00:00:00 2001 From: Robert Randolph Date: Thu, 10 Sep 2020 16:44:00 -0400 Subject: [PATCH 090/189] Update README.md Update readme's references to dir-locals.el to .dir-locals.el --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0cfb4dc..7ff5a2d 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ You can see all the configuration options available using the command While `inf-clojure` is capable of starting many common REPLs out of the box, it's fairly likely you will want to set some custom REPL startup command (e.g. because you need to include some `tools.deps` profile) and the REPL type -that goes with it. This is most easily achieved with the following `dir-locals.el`: +that goes with it. This is most easily achieved with the following `.dir-locals.el`: ```emacs-lisp ((nil @@ -214,7 +214,7 @@ If you want to update a specific form there is a function 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. If you use the -same project often, make a dir-locals file with this information in `inf-clojure-custom-startup`. +same project often, make a `.dir-locals.el` file with this information in `inf-clojure-custom-startup`. Note that if you decide _NOT_ to use the socket REPL, it is highly recommended you disable output coloring and/or readline facilities: `inf-clojure` does not From 8eaf885cb03515c010eff6d9924b641d30b3eb45 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sun, 2 Jun 2019 15:13:47 -0700 Subject: [PATCH 091/189] [Fix #152] Sanitize should only remove whitespace at the end of a command --- inf-clojure.el | 14 +------------- test/inf-clojure-tests.el | 23 ++++------------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 62d9402..e63a183 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -375,24 +375,12 @@ Should be a symbol that is a key in `inf-clojure-repl-features'." "Return non-nil iff STRING is a whole line semicolon comment." (string-match-p "^\s*;" string)) -(defun inf-clojure--make-single-line (string) - "Convert a multi-line STRING in a single-line STRING. -It also reduces redundant whitespace for readability and removes -comments." - (let* ((lines (seq-filter (lambda (s) (not (inf-clojure--whole-comment-line-p s))) - (split-string string "[\r\n]" t)))) - (mapconcat (lambda (s) - (if (not (string-match-p ";" s)) - (replace-regexp-in-string "\s+" " " s) - (concat s "\n"))) - lines " "))) - (defun inf-clojure--sanitize-command (command) "Sanitize COMMAND for sending it to a process. An example of things that this function does is to add a final newline at the end of the form. Return an empty string if the sanitized command is empty." - (let ((sanitized (inf-clojure--make-single-line command))) + (let ((sanitized (string-trim-right command))) (if (string-blank-p sanitized) "" (concat sanitized "\n")))) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 7821c06..1dd4d01 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -111,24 +111,6 @@ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) :to-equal "deref"))))) -(describe "inf-clojure--make-single-line" - (it "replaces newlines with whitespace" - (expect (inf-clojure--make-single-line "(do\n(println \"hello world\")\n)") :to-equal "(do (println \"hello world\") )")) - - (it "does not leave whitespace at the end" - (expect (inf-clojure--make-single-line "(do\n(println \"hello world\")\n)\n\n") :to-equal "(do (println \"hello world\") )")) - - (it "returns empty string when the line is only newlines" - (expect (inf-clojure--make-single-line "\n\n\n\n") :to-equal "")) - - (it "removes comments when on their own line" - (expect (inf-clojure--make-single-line "(do\n(println \"hello world\")\n ;; remove me\n)") :to-equal "(do (println \"hello world\") )")) - - (it "preserves newlines of inline comments" - (expect (inf-clojure--make-single-line "(do\n(println \"hello world\") ;; don't remove this\n)") :to-equal "(do (println \"hello world\") ;; don't remove this\n )")) - - ) - (describe "inf-clojure--sanitize-command" (it "sanitizes the command correctly" (expect (inf-clojure--sanitize-command "(doc println)") :to-equal "(doc println)\n")) @@ -137,7 +119,10 @@ (expect (inf-clojure--sanitize-command "(doc println)\n\n\n\n") :to-equal "(doc println)\n")) (it "returns empty string when the command is empty" - (expect (inf-clojure--sanitize-command " ") :to-equal ""))) + (expect (inf-clojure--sanitize-command " ") :to-equal "")) + + (it "only removes whitespace at the end of the command - fix 152" + (expect (inf-clojure--sanitize-command "1 5") :to-equal "1 5\n"))) (describe "inf-clojure--update-feature" (it "updates new forms correctly" From e144b335fae20418e783c4067463de38de56b65a Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sun, 2 Jun 2019 15:14:09 -0700 Subject: [PATCH 092/189] Improve the Makefile commands This also gets rid of one step in the CircleCI configuration. --- .circleci/config.yml | 1 - Makefile | 20 +++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c22fca..4b68ebe 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,6 @@ default: &default-steps steps: - checkout - run: apt-get update && apt-get install make - - run: make elpa - run: make test # Enumerated list of Emacs versions diff --git a/Makefile b/Makefile index 34fa168..d002f72 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,19 @@ -version: - emacs --version +.PHONY: clean version test -test : version - cask exec buttercup -L . +all: build -elpa: +clean: + rm -rf .cask + +.cask: cask install cask update + +version: + emacs --version + +build: version .cask + cask build + +test: version .cask + cask exec buttercup -L . From 6cb8e43b8426ad9f6a06cffd167bb4c1eb91ea2f Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 08:59:52 +0200 Subject: [PATCH 093/189] Update the CI images --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4b68ebe..0e778ab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,19 +11,19 @@ default: &default-steps jobs: test-emacs-25: docker: - - image: silex/emacs:25-dev + - image: silex/emacs:25-ci-cask entrypoint: bash <<: *default-steps test-emacs-26: docker: - - image: silex/emacs:26-dev + - image: silex/emacs:26-ci-cask entrypoint: bash <<: *default-steps test-emacs-master: docker: - - image: silex/emacs:master-dev + - image: silex/emacs:master-ci-cask entrypoint: bash <<: *default-steps From 62abe4ecf30398ad852bc9648f407ca987362203 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:00:23 +0200 Subject: [PATCH 094/189] Add Emacs 27 to the CI matrix --- .circleci/config.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0e778ab..1fc8575 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,6 +21,12 @@ jobs: entrypoint: bash <<: *default-steps + test-emacs-27: + docker: + - image: silex/emacs:27-ci-cask + entrypoint: bash + <<: *default-steps + test-emacs-master: docker: - image: silex/emacs:master-ci-cask @@ -33,4 +39,5 @@ workflows: jobs: - test-emacs-25 - test-emacs-26 + - test-emacs-27 - test-emacs-master From 784eb4055fb702f8dade4f369365aa5d55453ce5 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:35:07 +0200 Subject: [PATCH 095/189] Remove unused require --- inf-clojure.el | 1 - 1 file changed, 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index e63a183..35c7307 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -69,7 +69,6 @@ (require 'ansi-color) (require 'cl-lib) (require 'subr-x) -(require 'seq) (defvar inf-clojure-startup-forms '((lein . "lein repl") (boot . "boot repl") From 91f41210166073f1e6c4bc6049559be2d6460211 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:38:21 +0200 Subject: [PATCH 096/189] Bump the copyright years --- README.md | 2 +- inf-clojure.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ff5a2d..4bde87d 100644 --- a/README.md +++ b/README.md @@ -454,7 +454,7 @@ This creates `.inf-clojure.log` in the project directory so that you can `tail - ## License -Copyright © 2014-2020 Bozhidar Batsov and [contributors][]. +Copyright © 2014-2021 Bozhidar Batsov and [contributors][]. Distributed under the GNU General Public License; type C-h C-c to view it. diff --git a/inf-clojure.el b/inf-clojure.el index 35c7307..3b23cce 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1,6 +1,6 @@ ;;; inf-clojure.el --- Run an external Clojure process in an Emacs buffer -*- lexical-binding: t; -*- -;; Copyright © 2014-2020 Bozhidar Batsov +;; Copyright © 2014-2021 Bozhidar Batsov ;; Authors: Bozhidar Batsov ;; Olin Shivers From a98a260d0bcf8ee917bad5fe71d72add53ef7c92 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:38:33 +0200 Subject: [PATCH 097/189] [#152] Add a changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad76f62..87e4887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Bugs fixed + +[#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. + ## 3.0.0 (2020-08-01) ### New features From 68ab0f79c5bb259ac619156acc397dfeef291069 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:39:23 +0200 Subject: [PATCH 098/189] Bump the required Emacs version clojure-mode only supports Emacs 25+ --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 3b23cce..a372b15 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -7,7 +7,7 @@ ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure ;; Version: 3.0.0 -;; Package-Requires: ((emacs "24.4") (clojure-mode "5.11")) +;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From fd2d774a09cef6fe8b897cb4299851bcfb8c998a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:40:17 +0200 Subject: [PATCH 099/189] Bump the development version --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index a372b15..4d32d06 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 3.0.0 +;; Version: 3.1.0-snapshot ;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From 56810a76b32949d9634e2f50ffe5f2f5b15e5d99 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:42:57 +0200 Subject: [PATCH 100/189] Add a note about the required Emacs version --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4bde87d..aaa14f7 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,9 @@ the right code for each REPL type. ## Installation -Available on all major `package.el` community maintained repos - +**Note:** `inf-clojure` requires Emacs 25 or newer. + +`inf-clojure` is available on the community-maintained `package.el` repos - [MELPA Stable][] and [MELPA][] repos. MELPA Stable is recommended as it has the latest stable version. @@ -100,9 +102,9 @@ Add the following to your Emacs config to enable (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) ``` -**Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same time. They +**Warning:** Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same time. They have overlapping functionality and keybindings and the result will be nothing -short of havoc.** +short of havoc. ## Basic Usage From ec4a85e8687fd863bcb9d3c34fae2a39ea56b710 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:44:46 +0200 Subject: [PATCH 101/189] Bump copyright years --- test/inf-clojure-tests.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 1dd4d01..a331066 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -1,6 +1,6 @@ ;;; inf-clojure-tests.el --- Tests for Inf-Clojure -*- lexical-binding: t; -*- ;; -;; Copyright © 2014-2018 Bozhidar Batsov +;; Copyright © 2014-2021 Bozhidar Batsov ;; Authors: Bozhidar Batsov ;; Andrea Richiardi From f4a279ef5b007c3d43b79e22fecca6a331c5f3f0 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 7 Mar 2021 09:49:36 +0200 Subject: [PATCH 102/189] [Fix #177] Don't run the tests on Emacs 25 While inf-clojure works fine on Emacs 25, the testing library assess that we use in the test suite doesn't. Assess requires seq.el 2.14, which in turn requires Emacs 26. --- .circleci/config.yml | 7 ------- test/inf-clojure-tests.el | 9 ++------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1fc8575..31918ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,12 +9,6 @@ default: &default-steps # Enumerated list of Emacs versions jobs: - test-emacs-25: - docker: - - image: silex/emacs:25-ci-cask - entrypoint: bash - <<: *default-steps - test-emacs-26: docker: - image: silex/emacs:26-ci-cask @@ -37,7 +31,6 @@ workflows: version: 2 ci-test-matrix: jobs: - - test-emacs-25 - test-emacs-26 - test-emacs-27 - test-emacs-master diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index a331066..c35c9b2 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -4,9 +4,6 @@ ;; Authors: Bozhidar Batsov ;; Andrea Richiardi -;; URL: http://github.com/clojure-emacs/inf-clojure -;; Keywords: processes, clojure -;; Package-Requires: ((emacs "24.4") (clojure-mode "5.3")) ;; This file is not part of GNU Emacs. @@ -25,16 +22,14 @@ ;;; Commentary: ;; -;; Code completion using alexander-yakushev/compliment. +;; Tests for inf-clojure. ;;; Code: -;; Tests for inf-clojure.el - (message "Running tests on Emacs %s" emacs-version) (require 'buttercup) -(require 'assess) +(require 'assess) ;; requires Emacs 26, due to a dependency on seq.el (require 'inf-clojure) (cl-defmacro ict-with-assess-buffers ((&rest varlist) &body body) From 81e0912543894e335906009bb40217de8208ab9b Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 15 Mar 2021 11:12:06 +0200 Subject: [PATCH 103/189] Tweak some features --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index aaa14f7..d9c38aa 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ It supports the following REPLs: `inf-clojure` provides a set of essential features for interactive Clojure(Script) development: -* REPL +* Enhanced REPL * Interactive code evaluation * Code completion * Definition lookup @@ -51,8 +51,8 @@ Clojure(Script) development: * ElDoc * Apropos * Macroexpansion -* Require `:reload`/`:reload-all` -* Support connecting to socket REPLs +* Reloading a namespace (via `require :reload`/`require :reload-all`) +* Connecting to socket REPLs For a more powerful/full-featured solution see [CIDER](https://github.com/clojure-emacs/cider). From aaca7737a8a77cafa9d4cfabc1473ed3ef845048 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 15 Mar 2021 11:43:14 +0200 Subject: [PATCH 104/189] Tweak a changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87e4887..c29ea96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Bugs fixed -[#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. +* [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. ## 3.0.0 (2020-08-01) From b4193fce80a5d2b3cc777946f304059d07599d46 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Mon, 15 Mar 2021 19:28:45 -0500 Subject: [PATCH 105/189] Reindent tests --- test/inf-clojure-tests.el | 93 ++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index c35c9b2..71f9266 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -48,76 +48,77 @@ (expect (inf-clojure--kw-to-symbol "::keyword") :to-equal "keyword") (expect (inf-clojure--kw-to-symbol nil) :to-equal nil))) -(describe "completion bounds at point" () +(describe "completion bounds at point" (it "computes bounds for plain-text" - (ict-with-assess-buffers - ((a (insert "plain-text"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal "plain-text")))) + (ict-with-assess-buffers + ((a (insert "plain-text"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "plain-text")))) (it "computes bounds for @deref" - (ict-with-assess-buffers - ((a (insert "@deref"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal "deref")))) + (ict-with-assess-buffers + ((a (insert "@deref"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "deref")))) (it "computes bounds for ^:keyword" - (ict-with-assess-buffers - ((a (insert "^:keyword"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal ":keyword")))) + (ict-with-assess-buffers + ((a (insert "^:keyword"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal ":keyword")))) (it "computes bounds for ::keyword" - (ict-with-assess-buffers - ((a (insert "::keyword"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal "::keyword")))) + (ict-with-assess-buffers + ((a (insert "::keyword"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "::keyword")))) (it "computes bounds for [^:keyword (combined break chars and keyword)" - (ict-with-assess-buffers - ((a (insert "[^:keyword"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal ":keyword")))) + (ict-with-assess-buffers + ((a (insert "[^:keyword"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal ":keyword")))) (it "computes no bounds for point directly after a break expression" - (ict-with-assess-buffers - ((a (insert "@"))) - (with-current-buffer a - (expect - (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :not :to-be nil)))) + (ict-with-assess-buffers + ((a (insert "@"))) + (with-current-buffer a + (expect + (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :not :to-be nil)))) (it "computes bounds for [symbol" - (ict-with-assess-buffers - ((a (insert "[symbol"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal "symbol")))) + (ict-with-assess-buffers + ((a (insert "[symbol"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "symbol")))) (it "computes bounds for (@deref (multiple break chars)" - (ict-with-assess-buffers - ((a (insert "(@deref"))) - (with-current-buffer a - (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :to-equal "deref"))))) + (ict-with-assess-buffers + ((a (insert "(@deref"))) + (with-current-buffer a + (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) + :to-equal "deref"))))) (describe "inf-clojure--sanitize-command" (it "sanitizes the command correctly" - (expect (inf-clojure--sanitize-command "(doc println)") :to-equal "(doc println)\n")) + (expect (inf-clojure--sanitize-command "(doc println)") :to-equal "(doc println)\n")) (it "trims newline at the right of a command" - (expect (inf-clojure--sanitize-command "(doc println)\n\n\n\n") :to-equal "(doc println)\n")) + (expect (inf-clojure--sanitize-command "(doc println)\n\n\n\n") :to-equal "(doc println)\n")) (it "returns empty string when the command is empty" - (expect (inf-clojure--sanitize-command " ") :to-equal "")) + (expect (inf-clojure--sanitize-command " ") :to-equal "")) (it "only removes whitespace at the end of the command - fix 152" - (expect (inf-clojure--sanitize-command "1 5") :to-equal "1 5\n"))) + (expect (inf-clojure--sanitize-command "1 5") :to-equal "1 5\n"))) + (describe "inf-clojure--update-feature" (it "updates new forms correctly" From 675e9bed1503b7a1161ed1c1f517803bef929077 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sun, 14 Mar 2021 16:15:22 -0500 Subject: [PATCH 106/189] Handle newlines between forms for `inf-clojure-eval-buffer` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This sends the contents of the buffer. However, newlines cause the prompt to be returned. You can see this with even a regular clojure repl: ```bash ❯❯❯ clojure Clojure 1.10.2 user=> user=> user=> ``` (note using `clj` has rlwrap which hides a bit of this so make sure to use `clojure`). But what we can do is make sure to transform ```clojure (defn foo [] ...) (defn bar [] ...) ``` into ```clojure (defn foo [] ...) (defn bar [] ...) ``` So that the newlines don't trigger more repl prompts. Real world usage below: Before: ```clojure parse=> nil parse=> parse=> nil parse=> parse=> #'parse/data parse=> parse=> #'parse/parse-where parse=> parse=> #'parse/keywords parse=> parse=> #'parse/tokenize parse=> parse=> #'parse/parse parse=> parse=> #'parse/translate-where parse=> parse=> nil parse=> parse=> #'parse/query parse=> parse=> #'parse/query-test parse=> parse=> #'parse/bonus-points-test parse=> ``` After: ```clojure user=> nil parse=> nil parse=> #'parse/data parse=> #'parse/parse-where parse=> #'parse/keywords parse=> parse=> #'parse/parse parse=> #'parse/translate-where parse=> nil parse=> #'parse/query parse=> #'parse/query-test parse=> #'parse/bonus-points-test parse=> ``` --- inf-clojure.el | 34 +++++++++++++++++++++++++++++----- test/inf-clojure-tests.el | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 4d32d06..a97066b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -683,16 +683,40 @@ HOST is the host the process is running on, PORT is where it's listening." (interactive "shost: \nnport: ") (inf-clojure (cons host port))) +(defun inf-clojure--forms-without-newlines (str) + "Remove newlines between toplevel forms. +STR is a string of contents to be evaluated. When sending +multiple forms to a socket repl, each newline triggers a prompt. +So we replace all newlines between top level forms but not inside +of forms." + (condition-case nil + (with-temp-buffer + (progn + (clojurec-mode) + (insert str) + (whitespace-cleanup) + (goto-char (point-min)) + (while (not (eobp)) + (while (looking-at "\n") + (delete-char 1)) + (unless (eobp) + (clojure-forward-logical-sexp)) + (unless (eobp) + (forward-char))) + (buffer-substring-no-properties (point-min) (point-max)))) + (scan-error str))) + (defun inf-clojure-eval-region (start end &optional and-go) "Send the current region to the inferior Clojure process. Sends substring between START and END. Prefix argument AND-GO means switch to the Clojure buffer afterwards." (interactive "r\nP") - ;; drops newlines at the end of the region - (let ((str (replace-regexp-in-string - "[\n]+\\'" "" - (buffer-substring-no-properties start end)))) - (inf-clojure--send-string (inf-clojure-proc) str)) + (let* ((str (buffer-substring-no-properties start end)) + ;; newlines over a socket repl between top level forms cause + ;; a prompt to be returned. so here we dump the region into a + ;; temp buffer, and delete all newlines between the forms + (formatted (inf-clojure--forms-without-newlines str))) + (inf-clojure--send-string (inf-clojure-proc) formatted)) (when and-go (inf-clojure-switch-to-repl t))) (defun inf-clojure-eval-string (code) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 71f9266..635ac2c 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -119,6 +119,35 @@ (it "only removes whitespace at the end of the command - fix 152" (expect (inf-clojure--sanitize-command "1 5") :to-equal "1 5\n"))) +(describe "inf-clojure--forms-without-newlines" + (it "removes newlines between toplevel forms" + (expect (inf-clojure--forms-without-newlines + "(def foo 3)\n\n\n(def bar 4)") + :to-equal "(def foo 3)\n(def bar 4)")) + (it "doesn't remove newlines inside forms or strings" + (expect (inf-clojure--forms-without-newlines + " + +(defn foo [] + + :foo) + + +(def thing \"this + +is a string\") + +(defn bar [])") + ;; note no leading newline, newlines inside defn remain, + ;; newlines inside string remain + :to-equal "(defn foo [] + + :foo) +(def thing \"this + +is a string\") +(defn bar [])"))) + (describe "inf-clojure--update-feature" (it "updates new forms correctly" From f333ffdb0881ef2fb5860d194dc02b55335e8d33 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sun, 14 Mar 2021 16:30:13 -0500 Subject: [PATCH 107/189] Font lock on repl inserts --- inf-clojure.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index a97066b..c5730fa 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -776,7 +776,8 @@ Indent FORM. FORM is expected to have been trimmed." (insert (format "%s" form)) (let ((end (point))) (goto-char beginning) - (indent-sexp end))) + (indent-sexp end) + (font-lock-ensure beginning end))) (comint-send-input t t)))) (defun inf-clojure-insert-defun () From 3e712d9f489313c4097ccc891abedcfb6e1788d3 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 17 Mar 2021 14:21:04 +0200 Subject: [PATCH 108/189] Add a couple of changelog entries --- CHANGELOG.md | 2 ++ inf-clojure.el | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c29ea96..6aaafd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Bugs fixed * [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. +* [#188](https://github.com/clojure-emacs/inf-clojure/pull/188): Handle newlines between forms for `inf-clojure-eval-buffer`. +* [#189](https://github.com/clojure-emacs/inf-clojure/pull/189): Font-lock code inserted in the REPL from a source buffer. ## 3.0.0 (2020-08-01) diff --git a/inf-clojure.el b/inf-clojure.el index c5730fa..3832799 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -777,6 +777,7 @@ Indent FORM. FORM is expected to have been trimmed." (let ((end (point))) (goto-char beginning) (indent-sexp end) + ;; font-lock the inserted code (font-lock-ensure beginning end))) (comint-send-input t t)))) From 91145b034ba083afe76471ea5598a912862ae7a1 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 20 Mar 2021 02:12:52 -0500 Subject: [PATCH 109/189] Function to select repls as the current active connection very simple: if in a repl, use that. if not in a repl, display a list of inf-clojure process buffers. If given a prefix, always show a list. Makes running simultaneous repls far easier --- CHANGELOG.md | 4 ++++ README.md | 11 +++++++++++ inf-clojure.el | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aaafd4..56dc45a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#190](https://github.com/clojure-emacs/inf-clojure/pull/190): Helper function `inf-clojure-set-repl` to select inf-clojure process buffer. + ### Bugs fixed * [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. diff --git a/README.md b/README.md index d9c38aa..6bf9fca 100644 --- a/README.md +++ b/README.md @@ -316,6 +316,17 @@ one process, this does the right thing. If you run multiple processes, you might need to change `inf-clojure-buffer` to whichever process buffer you want to use. +You can use the helpful function `inf-clojure-set-repl`. If called in +an inf-clojure repl buffer, it will assign that buffer as the current +connection (`(setq inf-clojure-buffer (current-buffer)`). If you are +not in an inf-clojure repl buffer, it will offer a choice of +acceptable buffers to set as the repl buffer. If called with a prefix, +it will always give the list even if you are currently in an +acceptable repl buffer. Renaming buffers will greatly improve the +functionality of this list; the list "project-1: clojure repl", +"project-2: cljs repl" is far more understandable than "inf-clojure", +"inf-clojure<2>". + #### REPL Type An `inf-clojure` REPL has an associated type. The available types can be diff --git a/inf-clojure.el b/inf-clojure.el index 3832799..25457b5 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -199,6 +199,29 @@ has been found. See also variable `inf-clojure-buffer'." (unless no-error (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) +(defun inf-clojure-set-repl (always-ask) + "Set an inf clojure buffer as the active repl. +If in a repl already, use that unless a prefix is used (or +ALWAYS-ASK). Otherwise get a list of all active inf-clojure +repls and offer a choice. Recommended to rename buffers as they +are created with `rename-buffer`." + (interactive "P") + (cl-flet ((inf-clojure-repl-p () (and (derived-mode-p 'inf-clojure-mode) + (get-buffer-process (current-buffer)) + (process-live-p (get-buffer-process (current-buffer)))))) + (if (and (not always-ask) + (inf-clojure-repl-p)) + (setq inf-clojure-buffer (current-buffer)) + (let (repl-buffers) + (dolist (b (buffer-list)) + (with-current-buffer b + (when (inf-clojure-repl-p) + (push (buffer-name b) repl-buffers)))) + (if (> (length repl-buffers) 0) + (when-let ((repl-buffer (completing-read "Use for repl: " repl-buffers nil t))) + (setq inf-clojure-buffer (get-buffer repl-buffer))) + (user-error "No buffers have an inf-clojure process")))))) + (defvar-local inf-clojure-repl-type nil "Symbol to define your REPL type. Its root binding is nil and it can be further customized using From f24722c60477ff1177df1b8f5038984b2f2eb5f9 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 20 Mar 2021 09:46:11 -0500 Subject: [PATCH 110/189] Extract useful functions --- inf-clojure.el | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 25457b5..1ec3db8 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -199,6 +199,22 @@ has been found. See also variable `inf-clojure-buffer'." (unless no-error (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) +(defun inf-clojure-repl-p () + "Indicates if current buffer is an inf-clojure repl. +Checks the mode and that there is a live process." + (and (derived-mode-p 'inf-clojure-mode) + (get-buffer-process (current-buffer)) + (process-live-p (get-buffer-process (current-buffer))))) + +(defun inf-clojure-repls-list () + "Return a list of all known inf-clojure repls." + (let (repl-buffers) + (dolist (b (buffer-list)) + (with-current-buffer b + (when (inf-clojure-repl-p) + (push (buffer-name b) repl-buffers)))) + repl-buffers)) + (defun inf-clojure-set-repl (always-ask) "Set an inf clojure buffer as the active repl. If in a repl already, use that unless a prefix is used (or @@ -206,21 +222,14 @@ ALWAYS-ASK). Otherwise get a list of all active inf-clojure repls and offer a choice. Recommended to rename buffers as they are created with `rename-buffer`." (interactive "P") - (cl-flet ((inf-clojure-repl-p () (and (derived-mode-p 'inf-clojure-mode) - (get-buffer-process (current-buffer)) - (process-live-p (get-buffer-process (current-buffer)))))) - (if (and (not always-ask) - (inf-clojure-repl-p)) - (setq inf-clojure-buffer (current-buffer)) - (let (repl-buffers) - (dolist (b (buffer-list)) - (with-current-buffer b - (when (inf-clojure-repl-p) - (push (buffer-name b) repl-buffers)))) - (if (> (length repl-buffers) 0) - (when-let ((repl-buffer (completing-read "Use for repl: " repl-buffers nil t))) - (setq inf-clojure-buffer (get-buffer repl-buffer))) - (user-error "No buffers have an inf-clojure process")))))) + (if (and (not always-ask) + (inf-clojure-repl-p)) + (setq inf-clojure-buffer (current-buffer)) + (let ((repl-buffers (inf-clojure-repls-list))) + (if (> (length repl-buffers) 0) + (when-let ((repl-buffer (completing-read "Use for repl: " repl-buffers nil t))) + (setq inf-clojure-buffer (get-buffer repl-buffer))) + (user-error "No buffers have an inf-clojure process"))))) (defvar-local inf-clojure-repl-type nil "Symbol to define your REPL type. From 54ac59a6af9a9b548c62aaa07edcf7e240d90aa3 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 20 Mar 2021 14:02:08 -0500 Subject: [PATCH 111/189] Modeline with connected info note this changes the `inf-clojure-buffer` to always be a _buffer_ and not the name of a buffer. Seems like renaming can be quite risky since it was just a name of the buffer rather than the buffer. --- inf-clojure.el | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 1ec3db8..ac7951e 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -274,6 +274,14 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword \(as in :a, :c, etc.)" :type 'regexp) +(defun inf-clojure--modeline-info () + "Return modeline info. +Either \"not connected\" or \"repl-type: buffer-name\"" + (if (bufferp inf-clojure-buffer) + (with-current-buffer inf-clojure-buffer + (format "%s: %s" inf-clojure-repl-type (buffer-name (current-buffer)))) + "not connected")) + (defvar inf-clojure-mode-map (let ((map (copy-keymap comint-mode-map))) (define-key map (kbd "C-x C-e") #'inf-clojure-eval-last-sexp) @@ -358,6 +366,22 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword ["Quit REPL" inf-clojure-quit])) map)) +;;;###autoload +(defcustom inf-clojure-mode-line + '(:eval (format " inf-clojure[%s]" (inf-clojure--modeline-info))) + "Mode line lighter for cider mode. + +The value of this variable is a mode line template as in +`mode-line-format'. See Info Node `(elisp)Mode Line Format' for details +about mode line templates. + +Customize this variable to change how inf-clojure-minor-mode +displays its status in the mode line. The default value displays +the current connection. Set this variable to nil to disable the +mode line entirely." + :type 'sexp + :risky t) + ;;;###autoload (define-minor-mode inf-clojure-minor-mode "Minor mode for interacting with the inferior Clojure process buffer. @@ -365,7 +389,8 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword The following commands are available: \\{inf-clojure-minor-mode-map}" - :lighter "" :keymap inf-clojure-minor-mode-map + :lighter inf-clojure-mode-line + :keymap inf-clojure-minor-mode-map (setq-local comint-input-sender 'inf-clojure--send-string) (inf-clojure-eldoc-setup) (make-local-variable 'completion-at-point-functions) @@ -703,7 +728,7 @@ process buffer for a list of commands.)" (inf-clojure-mode) (setq-local inf-clojure-repl-type repl-type) (hack-dir-local-variables-non-file-buffer)))) - (setq inf-clojure-buffer "*inf-clojure*") + (setq inf-clojure-buffer (get-buffer "*inf-clojure*")) (if inf-clojure-repl-use-same-window (pop-to-buffer-same-window "*inf-clojure*") (pop-to-buffer "*inf-clojure*"))) From f7b6a8e14ea83775b07cc64366b2ffd0fd921b28 Mon Sep 17 00:00:00 2001 From: dan sutton Date: Sat, 20 Mar 2021 14:28:44 -0500 Subject: [PATCH 112/189] Don't try to select a dead buffer --- inf-clojure.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index ac7951e..062f925 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -277,7 +277,8 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword (defun inf-clojure--modeline-info () "Return modeline info. Either \"not connected\" or \"repl-type: buffer-name\"" - (if (bufferp inf-clojure-buffer) + (if (and (bufferp inf-clojure-buffer) + (buffer-live-p inf-clojure-buffer)) (with-current-buffer inf-clojure-buffer (format "%s: %s" inf-clojure-repl-type (buffer-name (current-buffer)))) "not connected")) From e1d7007f9a5afa7ec6dd81858ea18044eb0ff555 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 09:35:08 +0200 Subject: [PATCH 113/189] Touch up the previous commit --- README.md | 12 +++++++----- inf-clojure.el | 30 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 6bf9fca..75aa0ec 100644 --- a/README.md +++ b/README.md @@ -317,12 +317,14 @@ processes, you might need to change `inf-clojure-buffer` to whichever process buffer you want to use. You can use the helpful function `inf-clojure-set-repl`. If called in -an inf-clojure repl buffer, it will assign that buffer as the current -connection (`(setq inf-clojure-buffer (current-buffer)`). If you are -not in an inf-clojure repl buffer, it will offer a choice of -acceptable buffers to set as the repl buffer. If called with a prefix, +an `inf-clojure` REPL buffer, it will assign that buffer as the current +REPL (`(setq inf-clojure-buffer (current-buffer)`). If you are +not in an `inf-clojure` REPL buffer, it will offer a choice of +acceptable buffers to set as the REPL buffer. If called with a prefix, it will always give the list even if you are currently in an -acceptable repl buffer. Renaming buffers will greatly improve the +acceptable REPL buffer. + +**Tip:** Renaming buffers will greatly improve the functionality of this list; the list "project-1: clojure repl", "project-2: cljs repl" is far more understandable than "inf-clojure", "inf-clojure<2>". diff --git a/inf-clojure.el b/inf-clojure.el index 062f925..92812b7 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -191,7 +191,7 @@ Given a REPL-TYPE ('clojure, 'lumo, ...) and a FEATURE ('doc, (defun inf-clojure-proc (&optional no-error) "Return the current inferior Clojure process. -When NO-ERROR is non-nil, don't throw an error when no connection +When NO-ERROR is non-nil, don't throw an error when no process has been found. See also variable `inf-clojure-buffer'." (or (get-buffer-process (if (derived-mode-p 'inf-clojure-mode) (current-buffer) @@ -200,14 +200,14 @@ has been found. See also variable `inf-clojure-buffer'." (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) (defun inf-clojure-repl-p () - "Indicates if current buffer is an inf-clojure repl. + "Indicates if the current buffer is an inf-clojure REPL. Checks the mode and that there is a live process." (and (derived-mode-p 'inf-clojure-mode) (get-buffer-process (current-buffer)) (process-live-p (get-buffer-process (current-buffer))))) -(defun inf-clojure-repls-list () - "Return a list of all known inf-clojure repls." +(defun inf-clojure-repls () + "Return a list of all inf-clojure REPL buffers." (let (repl-buffers) (dolist (b (buffer-list)) (with-current-buffer b @@ -216,18 +216,18 @@ Checks the mode and that there is a live process." repl-buffers)) (defun inf-clojure-set-repl (always-ask) - "Set an inf clojure buffer as the active repl. -If in a repl already, use that unless a prefix is used (or + "Set an inf-clojure buffer as the active (default) REPL. +If in a REPL buffer already, use that unless a prefix is used (or ALWAYS-ASK). Otherwise get a list of all active inf-clojure -repls and offer a choice. Recommended to rename buffers as they -are created with `rename-buffer`." +REPLS and offer a choice. It's recommended to rename REPL +buffers after they are created with `rename-buffer'." (interactive "P") (if (and (not always-ask) (inf-clojure-repl-p)) (setq inf-clojure-buffer (current-buffer)) - (let ((repl-buffers (inf-clojure-repls-list))) + (let ((repl-buffers (inf-clojure-repls))) (if (> (length repl-buffers) 0) - (when-let ((repl-buffer (completing-read "Use for repl: " repl-buffers nil t))) + (when-let ((repl-buffer (completing-read "Select default REPL: " repl-buffers nil t))) (setq inf-clojure-buffer (get-buffer repl-buffer))) (user-error "No buffers have an inf-clojure process"))))) @@ -275,13 +275,13 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword :type 'regexp) (defun inf-clojure--modeline-info () - "Return modeline info. -Either \"not connected\" or \"repl-type: buffer-name\"" + "Return modeline info for `inf-clojure-minor-mode'. +Either \"no process\" or \"buffer-name(repl-type)\"" (if (and (bufferp inf-clojure-buffer) (buffer-live-p inf-clojure-buffer)) (with-current-buffer inf-clojure-buffer - (format "%s: %s" inf-clojure-repl-type (buffer-name (current-buffer)))) - "not connected")) + (format "%s(%s)" (buffer-name (current-buffer)) inf-clojure-repl-type)) + "no process")) (defvar inf-clojure-mode-map (let ((map (copy-keymap comint-mode-map))) @@ -378,7 +378,7 @@ about mode line templates. Customize this variable to change how inf-clojure-minor-mode displays its status in the mode line. The default value displays -the current connection. Set this variable to nil to disable the +the current REPL. Set this variable to nil to disable the mode line entirely." :type 'sexp :risky t) From 2046b12083ad7059ed8410e7623baa8b74c09c21 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 10:45:49 +0200 Subject: [PATCH 114/189] Make inf-clojure-repl-p a bit more flexible --- inf-clojure.el | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 92812b7..58dda37 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -199,12 +199,14 @@ has been found. See also variable `inf-clojure-buffer'." (unless no-error (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) -(defun inf-clojure-repl-p () - "Indicates if the current buffer is an inf-clojure REPL. +(defun inf-clojure-repl-p (&optional buf) + "Indicates if BUF is an inf-clojure REPL. +If BUF is nil then defaults to the current buffer. Checks the mode and that there is a live process." - (and (derived-mode-p 'inf-clojure-mode) - (get-buffer-process (current-buffer)) - (process-live-p (get-buffer-process (current-buffer))))) + (let ((buf (or buf (current-buffer)))) + (and (with-current-buffer buf (derived-mode-p 'inf-clojure-mode)) + (get-buffer-process buf) + (process-live-p (get-buffer-process buf))))) (defun inf-clojure-repls () "Return a list of all inf-clojure REPL buffers." From d79e4eba78bb3d6f021b2bda39aa8074595db77d Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 10:46:59 +0200 Subject: [PATCH 115/189] Remove a redundant call to with-current-buffer --- inf-clojure.el | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 58dda37..5f139c7 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -212,9 +212,8 @@ Checks the mode and that there is a live process." "Return a list of all inf-clojure REPL buffers." (let (repl-buffers) (dolist (b (buffer-list)) - (with-current-buffer b - (when (inf-clojure-repl-p) - (push (buffer-name b) repl-buffers)))) + (when (inf-clojure-repl-p b) + (push (buffer-name b) repl-buffers))) repl-buffers)) (defun inf-clojure-set-repl (always-ask) From 397272de241b64ad794a0f64c185bc77a1a23ecf Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 12:05:22 +0200 Subject: [PATCH 116/189] Auto-enable inf-clojure-minor-mode on starting inf-clojure That's inspired from the way CIDER starts cider-mode. --- CHANGELOG.md | 1 + README.md | 8 ++++++-- inf-clojure.el | 32 +++++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56dc45a..1468d2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#190](https://github.com/clojure-emacs/inf-clojure/pull/190): Helper function `inf-clojure-set-repl` to select inf-clojure process buffer. +* Auto-enable `inf-clojure-minor-mode` after invoking `inf-clojure`. This behaviour is controlled via `inf-clojure-auto-mode`. ### Bugs fixed diff --git a/README.md b/README.md index 75aa0ec..8f54179 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,12 @@ If the installation doesn't work try refreshing the package list: M-x package-refresh-contents -Add the following to your Emacs config to enable -`inf-clojure-minor-mode` for Clojure source buffers: +`inf-clojure-minor-mode` will be auto-enabled for Clojure source buffers after you do +`M-x inf-clojure`. You can disable this behavior by setting `inf-clojure-auto-mode` to +`nil`. + +You can also add the following to your Emacs config to enable +`inf-clojure-minor-mode` for Clojure source buffers, regardless of whether there's an `inf-clojure` REPL running: ```emacs-lisp (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) diff --git a/inf-clojure.el b/inf-clojure.el index 5f139c7..84b9d38 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -516,6 +516,34 @@ This should usually be a combination of `inf-clojure-prompt' and :safe #'booleanp :package-version '(inf-clojure . "2.0.0")) +(defcustom inf-clojure-auto-mode t + "When non-nil, automatically enable inf-clojure-minor-mode for all Clojure buffers." + :type 'boolean + :safe #'booleanp + :package-version '(inf-clojure . "3.1.0")) + +(defun inf-clojure--clojure-buffers () + "Return a list of all existing `clojure-mode' buffers." + (cl-remove-if-not + (lambda (buffer) (with-current-buffer buffer (derived-mode-p 'clojure-mode))) + (buffer-list))) + +(defun inf-clojure-enable-on-existing-clojure-buffers () + "Enable inf-clojure's minor mode on existing Clojure buffers. +See command `inf-clojure-minor-mode'." + (interactive) + (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) + (dolist (buffer (inf-clojure--clojure-buffers)) + (with-current-buffer buffer + (inf-clojure-minor-mode +1)))) + +(defun inf-clojure-disable-on-existing-clojure-buffers () + "Disable command `inf-clojure-minor-mode' on existing Clojure buffers." + (interactive) + (dolist (buffer (inf-clojure--clojure-buffers)) + (with-current-buffer buffer + (inf-clojure-minor-mode -1)))) + (defvar inf-clojure-buffer nil "The current `inf-clojure' process buffer. @@ -609,7 +637,9 @@ to continue it." (setq-local comint-prompt-read-only inf-clojure-prompt-read-only) (add-hook 'comint-preoutput-filter-functions #'inf-clojure-preoutput-filter nil t) (add-hook 'completion-at-point-functions #'inf-clojure-completion-at-point nil t) - (ansi-color-for-comint-mode-on)) + (ansi-color-for-comint-mode-on) + (when inf-clojure-auto-mode + (inf-clojure-enable-on-existing-clojure-buffers))) (defun inf-clojure-get-old-input () "Return a string containing the sexp ending at point." From 07b27380c4ce456ad112fedfc0e98be2abd07cfc Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 14:21:12 +0200 Subject: [PATCH 117/189] Include the project name automatically in the REPL buffer name --- CHANGELOG.md | 1 + inf-clojure.el | 50 +++++++++++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1468d2b..a1b244d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#190](https://github.com/clojure-emacs/inf-clojure/pull/190): Helper function `inf-clojure-set-repl` to select inf-clojure process buffer. * Auto-enable `inf-clojure-minor-mode` after invoking `inf-clojure`. This behaviour is controlled via `inf-clojure-auto-mode`. +* Include the project name automatically in the REPL buffer name. ### Bugs fixed diff --git a/inf-clojure.el b/inf-clojure.el index 84b9d38..6d1bbab 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -720,6 +720,11 @@ to suppress the usage of the target buffer discovery logic." (call-interactively #'inf-clojure) (rename-buffer target-buffer-name))) +(defun inf-clojure--project-name (dir) + "Extract a project name from a project DIR. +The name is simply the final segment of the path." + (file-name-nondirectory (directory-file-name dir))) + ;;;###autoload (defun inf-clojure (cmd) "Run an inferior Clojure process, input and output via buffer `*inf-clojure*'. @@ -744,26 +749,29 @@ process buffer for a list of commands.)" (mapcar #'cdr inf-clojure-startup-forms) nil 'confirm-after-completion)))) - (if (not (comint-check-proc "*inf-clojure*")) - ;; run the new process in the project's root when in a project folder - (let ((default-directory (or (clojure-project-dir) default-directory)) - (cmdlist (if (consp cmd) - (list cmd) - (split-string cmd))) - (repl-type (or (unless prefix-arg - inf-clojure-custom-repl-type) - (car (rassoc cmd inf-clojure-startup-forms)) - (inf-clojure--prompt-repl-type)))) - (message "Starting Clojure REPL via `%s'..." cmd) - (with-current-buffer (apply #'make-comint - "inf-clojure" (car cmdlist) nil (cdr cmdlist)) - (inf-clojure-mode) - (setq-local inf-clojure-repl-type repl-type) - (hack-dir-local-variables-non-file-buffer)))) - (setq inf-clojure-buffer (get-buffer "*inf-clojure*")) - (if inf-clojure-repl-use-same-window - (pop-to-buffer-same-window "*inf-clojure*") - (pop-to-buffer "*inf-clojure*"))) + (let* ((project-dir (clojure-project-dir)) + (repl-buffer-name (if project-dir (format "*inf-clojure %s*" (inf-clojure--project-name project-dir)) "*inf-clojure*")) + (comint-name (string-trim repl-buffer-name "*" "*"))) + (if (not (comint-check-proc repl-buffer-name)) + ;; run the new process in the project's root when in a project folder + (let ((default-directory (or project-dir default-directory)) + (cmdlist (if (consp cmd) + (list cmd) + (split-string cmd))) + (repl-type (or (unless prefix-arg + inf-clojure-custom-repl-type) + (car (rassoc cmd inf-clojure-startup-forms)) + (inf-clojure--prompt-repl-type)))) + (message "Starting Clojure REPL via `%s'..." cmd) + (with-current-buffer (apply #'make-comint + comint-name (car cmdlist) nil (cdr cmdlist)) + (inf-clojure-mode) + (setq-local inf-clojure-repl-type repl-type) + (hack-dir-local-variables-non-file-buffer)))) + (setq inf-clojure-buffer (get-buffer repl-buffer-name)) + (if inf-clojure-repl-use-same-window + (pop-to-buffer-same-window repl-buffer-name) + (pop-to-buffer repl-buffer-name)))) ;;;###autoload (defun inf-clojure-connect (host port) @@ -1436,7 +1444,7 @@ Useful for commands that can invoked outside of an ‘inf-clojure’ buffer "Send FORM and apply MATCH-P on the result of sending it to PROC. Note that this function will add a \n to the end of the string for evaluation, therefore FORM should not include it." - (funcall match-p (inf-clojure--process-response form proc nil))) +p (funcall match-p (inf-clojure--process-response form proc nil))) (provide 'inf-clojure) From dfc27a3484dfb70d77d0bfd903512f3cf301036a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 14:32:23 +0200 Subject: [PATCH 118/189] [Docs] Add a note about the REPL name inference --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8f54179..772fb1c 100644 --- a/README.md +++ b/README.md @@ -291,6 +291,10 @@ process with another `inf-clojure`. It will be in a new buffer, named `*inf-clojure*`. You can switch between the different process buffers with `switch-to-buffer`. +**Note:** If you're starting `inf-clojure` within a Clojure project directory +the name of the project will be incorporated into the name of the REPL buffer +- e.g. `*inf-clojure my-project*`. + Commands that send text from source buffers to Clojure processes (like `inf-clojure-eval-defun` or `inf-clojure-show-arglists`) have to choose a process to send to, when you have more than one Clojure process around. This is determined by the global variable `inf-clojure-buffer`. From 9841b38dde980789b3b5d13479c3b299fa3fcbd8 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 14:51:22 +0200 Subject: [PATCH 119/189] Remove some redundant code Seems I went overboard with the previous set of changes. --- inf-clojure.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 6d1bbab..12b0cb0 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -750,8 +750,9 @@ process buffer for a list of commands.)" nil 'confirm-after-completion)))) (let* ((project-dir (clojure-project-dir)) - (repl-buffer-name (if project-dir (format "*inf-clojure %s*" (inf-clojure--project-name project-dir)) "*inf-clojure*")) - (comint-name (string-trim repl-buffer-name "*" "*"))) + (repl-buffer-name (if project-dir + (format "*inf-clojure %s*" (inf-clojure--project-name project-dir)) + "*inf-clojure*"))) (if (not (comint-check-proc repl-buffer-name)) ;; run the new process in the project's root when in a project folder (let ((default-directory (or project-dir default-directory)) @@ -764,7 +765,7 @@ process buffer for a list of commands.)" (inf-clojure--prompt-repl-type)))) (message "Starting Clojure REPL via `%s'..." cmd) (with-current-buffer (apply #'make-comint - comint-name (car cmdlist) nil (cdr cmdlist)) + "inf-clojure" (car cmdlist) nil (cdr cmdlist)) (inf-clojure-mode) (setq-local inf-clojure-repl-type repl-type) (hack-dir-local-variables-non-file-buffer)))) From dd7dd78f27134534e6ea3dac98ec85430d255168 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 14:53:30 +0200 Subject: [PATCH 120/189] Tweak a couple of docstrings --- inf-clojure.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 12b0cb0..141d633 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -776,7 +776,7 @@ process buffer for a list of commands.)" ;;;###autoload (defun inf-clojure-connect (host port) - "Connect to a running socket-repl via `inf-clojure'. + "Connect to a running socket REPL server via `inf-clojure'. HOST is the host the process is running on, PORT is where it's listening." (interactive "shost: \nnport: ") (inf-clojure (cons host port))) @@ -784,7 +784,7 @@ HOST is the host the process is running on, PORT is where it's listening." (defun inf-clojure--forms-without-newlines (str) "Remove newlines between toplevel forms. STR is a string of contents to be evaluated. When sending -multiple forms to a socket repl, each newline triggers a prompt. +multiple forms to a REPL, each newline triggers a prompt. So we replace all newlines between top level forms but not inside of forms." (condition-case nil From 26a2076277087859dda35452193e09b12c44b3ec Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 22 Mar 2021 14:59:40 +0200 Subject: [PATCH 121/189] Replace if + not with unless --- inf-clojure.el | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 141d633..88a9c86 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -753,22 +753,24 @@ process buffer for a list of commands.)" (repl-buffer-name (if project-dir (format "*inf-clojure %s*" (inf-clojure--project-name project-dir)) "*inf-clojure*"))) - (if (not (comint-check-proc repl-buffer-name)) - ;; run the new process in the project's root when in a project folder - (let ((default-directory (or project-dir default-directory)) - (cmdlist (if (consp cmd) - (list cmd) - (split-string cmd))) - (repl-type (or (unless prefix-arg - inf-clojure-custom-repl-type) - (car (rassoc cmd inf-clojure-startup-forms)) - (inf-clojure--prompt-repl-type)))) - (message "Starting Clojure REPL via `%s'..." cmd) - (with-current-buffer (apply #'make-comint - "inf-clojure" (car cmdlist) nil (cdr cmdlist)) - (inf-clojure-mode) - (setq-local inf-clojure-repl-type repl-type) - (hack-dir-local-variables-non-file-buffer)))) + ;; Create a new comint buffer if needed + (unless (comint-check-proc repl-buffer-name) + ;; run the new process in the project's root when in a project folder + (let ((default-directory (or project-dir default-directory)) + (cmdlist (if (consp cmd) + (list cmd) + (split-string cmd))) + (repl-type (or (unless prefix-arg + inf-clojure-custom-repl-type) + (car (rassoc cmd inf-clojure-startup-forms)) + (inf-clojure--prompt-repl-type)))) + (message "Starting Clojure REPL via `%s'..." cmd) + (with-current-buffer (apply #'make-comint + "inf-clojure" (car cmdlist) nil (cdr cmdlist)) + (inf-clojure-mode) + (setq-local inf-clojure-repl-type repl-type) + (hack-dir-local-variables-non-file-buffer)))) + ;; update the default comint buffer and switch to it (setq inf-clojure-buffer (get-buffer repl-buffer-name)) (if inf-clojure-repl-use-same-window (pop-to-buffer-same-window repl-buffer-name) From 1e99b8246bb1fe7666d613a9ae566e2a939fc2bb Mon Sep 17 00:00:00 2001 From: dpsutton Date: Mon, 22 Mar 2021 09:21:57 -0500 Subject: [PATCH 122/189] The redundant bit of code was actually required (#191) Oh, well... Bozhidar needs to pay attention to what he's deleting. Cheers, Bozhidar --- inf-clojure.el | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 88a9c86..c9ede40 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -750,9 +750,11 @@ process buffer for a list of commands.)" nil 'confirm-after-completion)))) (let* ((project-dir (clojure-project-dir)) - (repl-buffer-name (if project-dir - (format "*inf-clojure %s*" (inf-clojure--project-name project-dir)) - "*inf-clojure*"))) + (process-buffer-name (if project-dir + (format "inf-clojure %s" (inf-clojure--project-name project-dir)) + "inf-clojure")) + ;; comint adds the asterisks to both sides + (repl-buffer-name (format "*%s*" process-buffer-name))) ;; Create a new comint buffer if needed (unless (comint-check-proc repl-buffer-name) ;; run the new process in the project's root when in a project folder @@ -766,7 +768,7 @@ process buffer for a list of commands.)" (inf-clojure--prompt-repl-type)))) (message "Starting Clojure REPL via `%s'..." cmd) (with-current-buffer (apply #'make-comint - "inf-clojure" (car cmdlist) nil (cdr cmdlist)) + process-buffer-name (car cmdlist) nil (cdr cmdlist)) (inf-clojure-mode) (setq-local inf-clojure-repl-type repl-type) (hack-dir-local-variables-non-file-buffer)))) From 37cfe852f8061e5b3dd5471fa50d96e5278c840a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 6 Apr 2021 10:32:07 +0300 Subject: [PATCH 123/189] Update some wording Support for terminal REPLs is not going to be deprecated. --- README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 772fb1c..0179fbf 100644 --- a/README.md +++ b/README.md @@ -217,22 +217,23 @@ If you want to update a specific form there is a function #### Caveats -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. If you use the -same project often, make a `.dir-locals.el` file with this information in `inf-clojure-custom-startup`. - -Note that if you decide _NOT_ to use the socket REPL, it is highly recommended -you disable output coloring and/or readline facilities: `inf-clojure` does not +As `inf-clojure` is built on top of `comint` it has all the usual comint limitations - +namely it can't handle well some fancy terminal features (e.g. ANSI colours). +In general the "dumber" your terminal REPL is, the better (e.g. `clojure` vs `clj`). +Connecting to a socket REPL is one simple way to avoid dealing with this type of +problems. + +If you decide _not_ to use the socket REPL, it is highly recommended +you disable output coloring and/or `readline` facilities: `inf-clojure` does not filter out ASCII escape characters at the moment and will not behave correctly. -For leiningen, there are no command line switches and you need to add +For Leiningen, there are no command-line switches and you need to add a custom [`project.clj` option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj): ```clojure ... - :repl-options {:color false} +:repl-options {:color false} ... ``` From c3ff2f40fdcedf3357cde868c278474767b65adb Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 6 Apr 2021 10:57:41 +0300 Subject: [PATCH 124/189] Add a note about comint --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0179fbf..bc87fe1 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ Functionality like code completion and eldoc is powered by evaluation of predefi As different Clojure REPLs have different capabilities, `inf-clojure` tracks the type of a REPL and invokes the right code for each REPL type. +`inf-clojure` is built on top of Emacs's [comint](https://github.com/emacs-mirror/emacs/blob/master/lisp/comint.el). Unfortunately `comint` is pretty light on official documentation, but there is a good overview/tutorial [here](https://www.masteringemacs.org/article/comint-writing-command-interpreter). + ## Installation **Note:** `inf-clojure` requires Emacs 25 or newer. From 696e5efb537d55c9db4d885c33d638f3eaf932a5 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 14 Apr 2021 09:54:08 +0300 Subject: [PATCH 125/189] Add a link to Discord --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bc87fe1..287fdbb 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![MELPA][melpa-badge]][melpa-package] [![MELPA Stable][melpa-stable-badge]][melpa-stable-package] [![Circle CI][circleci-badge]][circleci] +[![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://discord.com/invite/nFPpynQPME) # inf-clojure From 49b2257b76f53df12ff72c07426e90e3789d8d1d Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 2 May 2021 08:08:43 +0300 Subject: [PATCH 126/189] Remove the TOC Now GitHub generates one automatically. --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 287fdbb..c95cebd 100644 --- a/README.md +++ b/README.md @@ -20,14 +20,6 @@ the relevant git tag (e.g. 2.2.0) if you need documentation for a specific `inf-clojure` release.** *** -- [Overview](#overview) -- [Rationale](#rationale) -- [Installation](#installation) -- [Basic Usage](#basic-usage) -- [Configuration](#configuration) -- [Troubleshooting](#troubleshooting) -- [License](#license) - ## Overview `inf-clojure` aims to expose the extensive self-documenting features of Clojure From a2cebf5362fe583538dda8dcf6348a8d73b462a2 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 2 May 2021 08:09:39 +0300 Subject: [PATCH 127/189] Add a separator between a couple of paragraphs --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c95cebd..135945b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ It's based on ideas from the popular `inferior-lisp` package. interaction minor mode (`inf-clojure-minor-mode`), which extends `clojure-mode` with commands to evaluate forms directly in the REPL. +----------- + **This documentation tracks the `master` branch of `inf-clojure`. Some of the features and settings discussed here might not be available in older releases (including the current stable release). Please, consult From c23c55e662c16ec94e684b2ec9611e78531921a8 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 23 Jul 2021 10:18:36 +0300 Subject: [PATCH 128/189] Release 3.1.0 --- CHANGELOG.md | 2 ++ inf-clojure.el | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1b244d..e5c87a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## 3.1.0 (2021-07-23) + ### New features * [#190](https://github.com/clojure-emacs/inf-clojure/pull/190): Helper function `inf-clojure-set-repl` to select inf-clojure process buffer. diff --git a/inf-clojure.el b/inf-clojure.el index c9ede40..f3f6665 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 3.1.0-snapshot +;; Version: 3.1.0 ;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From 3d31beeb8d9236afad29aa2b15c46e10b93c706b Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Wed, 11 Aug 2021 09:45:33 +0300 Subject: [PATCH 129/189] Update my email --- inf-clojure.el | 2 +- test/inf-clojure-tests.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index f3f6665..790660b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -2,7 +2,7 @@ ;; Copyright © 2014-2021 Bozhidar Batsov -;; Authors: Bozhidar Batsov +;; Authors: Bozhidar Batsov ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 635ac2c..6023338 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -2,7 +2,7 @@ ;; ;; Copyright © 2014-2021 Bozhidar Batsov -;; Authors: Bozhidar Batsov +;; Authors: Bozhidar Batsov ;; Andrea Richiardi ;; This file is not part of GNU Emacs. From 38e7dc1829646b93473c31d704bda0dee6644a38 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Thu, 19 Aug 2021 14:46:47 +0300 Subject: [PATCH 130/189] Shuffle around the README badges --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 135945b..dc314a8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ -[![License GPL 3][badge-license]][copying] +[![Circle CI][circleci-badge]][circleci] [![MELPA][melpa-badge]][melpa-package] [![MELPA Stable][melpa-stable-badge]][melpa-stable-package] -[![Circle CI][circleci-badge]][circleci] +[![NonGNU ELPA](https://elpa.nongnu.org/nongnu/inf-clojure.svg)](https://elpa.nongnu.org/nongnu/inf-clojure.html) [![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://discord.com/invite/nFPpynQPME) +[![License GPL 3][badge-license]][copying] # inf-clojure From 765653dc23dc2a2c1520a1e24332ab9d4b49dd47 Mon Sep 17 00:00:00 2001 From: dpsutton Date: Wed, 27 Oct 2021 11:11:35 -0500 Subject: [PATCH 131/189] Set clojure-mode syntax table in repl buffer (#193) --- CHANGELOG.md | 1 + inf-clojure.el | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5c87a3..ec5e0c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Bugs fixed +* [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in repl buffer * [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. * [#188](https://github.com/clojure-emacs/inf-clojure/pull/188): Handle newlines between forms for `inf-clojure-eval-buffer`. * [#189](https://github.com/clojure-emacs/inf-clojure/pull/189): Font-lock code inserted in the REPL from a source buffer. diff --git a/inf-clojure.el b/inf-clojure.el index 790660b..bbcb0c1 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -770,6 +770,7 @@ process buffer for a list of commands.)" (with-current-buffer (apply #'make-comint process-buffer-name (car cmdlist) nil (cdr cmdlist)) (inf-clojure-mode) + (set-syntax-table clojure-mode-syntax-table) (setq-local inf-clojure-repl-type repl-type) (hack-dir-local-variables-non-file-buffer)))) ;; update the default comint buffer and switch to it From dca9f1957237214a0bb6155c68163efd6783e445 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Tue, 8 Feb 2022 15:40:27 +0900 Subject: [PATCH 132/189] Remove a noise character --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index bbcb0c1..bb38c7d 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1450,7 +1450,7 @@ Useful for commands that can invoked outside of an ‘inf-clojure’ buffer "Send FORM and apply MATCH-P on the result of sending it to PROC. Note that this function will add a \n to the end of the string for evaluation, therefore FORM should not include it." -p (funcall match-p (inf-clojure--process-response form proc nil))) + (funcall match-p (inf-clojure--process-response form proc nil))) (provide 'inf-clojure) From 59194187dfd289b77d927fcc17675555d5a78f38 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Tue, 8 Feb 2022 18:59:37 +0900 Subject: [PATCH 133/189] Declare global variable before referenced --- inf-clojure.el | 108 ++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index bb38c7d..2a3cfd1 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -154,6 +154,47 @@ (macroexpand . "(clojure.core/macroexpand '%s)") (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))))) +(defvar-local inf-clojure-repl-type nil + "Symbol to define your REPL type. +Its root binding is nil and it can be further customized using +either `setq-local` or an entry in `.dir-locals.el`." ) + +(defvar inf-clojure-buffer nil + "The current `inf-clojure' process buffer. + +MULTIPLE PROCESS SUPPORT +=========================================================================== +To run multiple Clojure processes, you start the first up +with \\[inf-clojure]. It will be in a buffer named `*inf-clojure*'. +Rename this buffer with \\[rename-buffer]. You may now start up a new +process with another \\[inf-clojure]. It will be in a new buffer, +named `*inf-clojure*'. You can switch between the different process +buffers with \\[switch-to-buffer]. + +Commands that send text from source buffers to Clojure processes -- +like `inf-clojure-eval-defun' or `inf-clojure-show-arglists' -- have to choose a +process to send to, when you have more than one Clojure process around. This +is determined by the global variable `inf-clojure-buffer'. Suppose you +have three inferior Clojures running: + Buffer Process + foo inf-clojure + bar inf-clojure<2> + *inf-clojure* inf-clojure<3> +If you do a \\[inf-clojure-eval-defun] command on some Clojure source code, +what process do you send it to? + +- If you're in a process buffer (foo, bar, or *inf-clojure*), + you send it to that process. +- If you're in some other buffer (e.g., a source file), you + send it to the process attached to buffer `inf-clojure-buffer'. +This process selection is performed by function `inf-clojure-proc'. + +Whenever \\[inf-clojure] fires up a new process, it resets +`inf-clojure-buffer' to be the new process's buffer. If you only run +one process, this does the right thing. If you run multiple +processes, you might need to change `inf-clojure-buffer' to +whichever process buffer you want to use.") + (defun inf-clojure--get-feature (repl-type feature no-error) "Get FEATURE for REPL-TYPE from repl-features. If no-error is truthy don't error if feature is not present." @@ -232,11 +273,6 @@ buffers after they are created with `rename-buffer'." (setq inf-clojure-buffer (get-buffer repl-buffer))) (user-error "No buffers have an inf-clojure process"))))) -(defvar-local inf-clojure-repl-type nil - "Symbol to define your REPL type. -Its root binding is nil and it can be further customized using -either `setq-local` or an entry in `.dir-locals.el`." ) - (defvar inf-clojure--repl-type-lock nil "Global lock for protecting against proc filter race conditions. See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filter.html") @@ -544,42 +580,6 @@ See command `inf-clojure-minor-mode'." (with-current-buffer buffer (inf-clojure-minor-mode -1)))) -(defvar inf-clojure-buffer nil - "The current `inf-clojure' process buffer. - -MULTIPLE PROCESS SUPPORT -=========================================================================== -To run multiple Clojure processes, you start the first up -with \\[inf-clojure]. It will be in a buffer named `*inf-clojure*'. -Rename this buffer with \\[rename-buffer]. You may now start up a new -process with another \\[inf-clojure]. It will be in a new buffer, -named `*inf-clojure*'. You can switch between the different process -buffers with \\[switch-to-buffer]. - -Commands that send text from source buffers to Clojure processes -- -like `inf-clojure-eval-defun' or `inf-clojure-show-arglists' -- have to choose a -process to send to, when you have more than one Clojure process around. This -is determined by the global variable `inf-clojure-buffer'. Suppose you -have three inferior Clojures running: - Buffer Process - foo inf-clojure - bar inf-clojure<2> - *inf-clojure* inf-clojure<3> -If you do a \\[inf-clojure-eval-defun] command on some Clojure source code, -what process do you send it to? - -- If you're in a process buffer (foo, bar, or *inf-clojure*), - you send it to that process. -- If you're in some other buffer (e.g., a source file), you - send it to the process attached to buffer `inf-clojure-buffer'. -This process selection is performed by function `inf-clojure-proc'. - -Whenever \\[inf-clojure] fires up a new process, it resets -`inf-clojure-buffer' to be the new process's buffer. If you only run -one process, this does the right thing. If you run multiple -processes, you might need to change `inf-clojure-buffer' to -whichever process buffer you want to use.") - (define-derived-mode inf-clojure-mode comint-mode "Inferior Clojure" "Major mode for interacting with an inferior Clojure process. Runs a Clojure interpreter as a subprocess of Emacs, with Clojure @@ -1253,19 +1253,6 @@ every other EXPR will be discarded and nil will be returned." (inf-clojure--read-or-nil) (inf-clojure--list-or-nil))) -(defun inf-clojure-completions (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." - (let* ((proc (inf-clojure-proc 'no-error)) - (completion-form (inf-clojure-get-feature proc 'completion t))) - (when (and proc completion-form (not (string-blank-p expr))) - (let ((completion-expr (format completion-form (substring-no-properties expr)))) - (funcall inf-clojure-completions-fn - (inf-clojure--process-response completion-expr proc "(" ")")))))) - (defcustom inf-clojure-completions-fn 'inf-clojure-list-completions "The function that parses completion results. @@ -1290,6 +1277,19 @@ you might want to use in your customization." :type 'function :package-version '(inf-clojure . "2.1.0")) +(defun inf-clojure-completions (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." + (let* ((proc (inf-clojure-proc 'no-error)) + (completion-form (inf-clojure-get-feature proc 'completion t))) + (when (and proc completion-form (not (string-blank-p expr))) + (let ((completion-expr (format completion-form (substring-no-properties expr)))) + (funcall inf-clojure-completions-fn + (inf-clojure--process-response completion-expr proc "(" ")")))))) + (defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()[@\\^]" "Regexp are hard. From a5108373680fc9b3b1eecc247d66f0bbeecc2537 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Tue, 8 Feb 2022 19:01:54 +0900 Subject: [PATCH 134/189] Fix byte-compile warnings of unused variables --- inf-clojure.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 2a3cfd1..34a6fee 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -507,7 +507,7 @@ Clojure to load that file." ;; :reload-all implies :reload and also forces loading of all libs that the ;; identified libs directly or indirectly load via require or use -(defun inf-clojure-reload-form (proc) +(defun inf-clojure-reload-form (_proc) "Return the form to query the Inf-Clojure PROC for reloading a namespace. If you are using REPL types, it will pickup the most appropriate `inf-clojure-reload-form` variant." @@ -525,7 +525,7 @@ Clojure to load that file." :safe #'stringp :package-version '(inf-clojure . "2.2.0")) -(defun inf-clojure-reload-all-form (proc) +(defun inf-clojure-reload-all-form (_proc) "Return the form to query the Inf-Clojure PROC for :reload-all of a namespace. If you are using REPL types, it will pickup the most appropriate `inf-clojure-reload-all-form` variant." From edbdd09569cac829f824a1f52dd15829de6f8904 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Tue, 8 Feb 2022 19:04:38 +0900 Subject: [PATCH 135/189] Specify customize variable :type attribute --- inf-clojure.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 34a6fee..4534766 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -450,7 +450,8 @@ number (e.g. (\"localhost\" . 5555))." "Form to be used to start `inf-clojure'. Can be a cons pair of (host . port) where host is a string and port is an integer, or a string to startup an interpreter like -\"planck\".") +\"planck\"." + :type '(choice (cons string integer) (const nil))) (defcustom inf-clojure-custom-repl-type nil From 975ed78919ff50ddc290a0630502c42cee3e9a81 Mon Sep 17 00:00:00 2001 From: Shohei YOSHIDA Date: Tue, 8 Feb 2022 22:38:56 +0900 Subject: [PATCH 136/189] Put a space after prompt --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 4534766..2008939 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -282,7 +282,7 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte (interactive) (let ((types (mapcar #'car inf-clojure-repl-features))) (intern - (completing-read "Set REPL type:" + (completing-read "Set REPL type: " (sort (mapcar #'symbol-name types) #'string-lessp))))) (defgroup inf-clojure nil From d89ad48a5b61ccf1c7417f63b006493cec4063f7 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 8 Feb 2022 18:27:52 +0200 Subject: [PATCH 137/189] Bump copyright --- README.md | 2 +- inf-clojure.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc314a8..971854d 100644 --- a/README.md +++ b/README.md @@ -476,7 +476,7 @@ This creates `.inf-clojure.log` in the project directory so that you can `tail - ## License -Copyright © 2014-2021 Bozhidar Batsov and [contributors][]. +Copyright © 2014-2022 Bozhidar Batsov and [contributors][]. Distributed under the GNU General Public License; type C-h C-c to view it. diff --git a/inf-clojure.el b/inf-clojure.el index 2008939..1ad0bbb 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1,6 +1,6 @@ ;;; inf-clojure.el --- Run an external Clojure process in an Emacs buffer -*- lexical-binding: t; -*- -;; Copyright © 2014-2021 Bozhidar Batsov +;; Copyright © 2014-2022 Bozhidar Batsov ;; Authors: Bozhidar Batsov ;; Olin Shivers From e47684de78da1ee470d42ae2a411909b2cf61d50 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 8 Feb 2022 18:28:24 +0200 Subject: [PATCH 138/189] Tweak a changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec5e0c1..01a558a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ ### Bugs fixed -* [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in repl buffer +* [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in REPL buffer. * [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. * [#188](https://github.com/clojure-emacs/inf-clojure/pull/188): Handle newlines between forms for `inf-clojure-eval-buffer`. * [#189](https://github.com/clojure-emacs/inf-clojure/pull/189): Font-lock code inserted in the REPL from a source buffer. From de59e5c416c242f77e3744ece3597843278191e5 Mon Sep 17 00:00:00 2001 From: dpsutton Date: Tue, 15 Mar 2022 05:58:11 -0500 Subject: [PATCH 139/189] Adds an option to disable eldoc (#197) Eldoc is quite nice and puts the function signatures in the minibuffer. But it does this at a cost. Since inf-clojure only uses a single connection (currently at least) the commands interrupt the values of `*1`, `*2`, etc. Further, this can lead to multiple prompts appearing in the repl buffer. ```clojure user=> user=> (map inc (range 4)) (1 2 3 4) user=> user=> *1 nil user=> ``` `user` appears multiple times, and then `*1` has been bound to the result of getting arglists. ```clojure user=> (+ 1 1) 2 user=> *1 ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]) ``` The multiple prompts is quite annoying when inserting forms into the repl. --- CHANGELOG.md | 4 ++++ README.md | 18 ++++++++++-------- inf-clojure.el | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01a558a..daccb36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#187](https://github.com/clojure-emacs/inf-clojure/pull/197): Defcustom `inf-clojure-enable-eldoc` to disable eldoc interaction. + ## 3.1.0 (2021-07-23) ### New features diff --git a/README.md b/README.md index 971854d..fe08189 100644 --- a/README.md +++ b/README.md @@ -356,18 +356,20 @@ startup when using the `inf-clojure` command or is specified manually when using #### ElDoc -**Note:** You can skip this section if you're using Emacs 26.1+, as `eldoc-mode` -is enabled by default there. - `eldoc-mode` is supported in Clojure source buffers and `*inferior-clojure*` buffers which are running a Clojure REPL. -When ElDoc is enabled and there is an active REPL, it will show the -argument list of the function call you are currently editing in the -echo area. +When ElDoc is enabled and there is an active REPL, it will show the argument +list of the function call you are currently editing in the echo area. It +accomplishes this by evaluating forms to get the metadata for the vars under +your cursor. One side effect of this is that it can mess with repl vars like +`*1` and `*2`. You can disable inf-clojure's Eldoc functionality with `(setq +inf-clojure-enable-eldoc nil)`. + -You can activate ElDoc with `M-x eldoc-mode` or by adding the -following to you Emacs config: +ElDoc should be enabled by default in Emacs 26.1+. If it is not active by +default, you can activate ElDoc with `M-x eldoc-mode` or by adding the following +to you Emacs config: ```emacs-lisp (add-hook 'clojure-mode-hook #'eldoc-mode) diff --git a/inf-clojure.el b/inf-clojure.el index 1ad0bbb..1e588fd 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -420,6 +420,13 @@ mode line entirely." :type 'sexp :risky t) +(defcustom inf-clojure-enable-eldoc t + "Var that allows disabling `eldoc-mode` in `inf-clojure`. + +Set to `nil` to disable eldoc. Eldoc can be quite useful by +displaying function signatures in the modeline, but can also +cause multiple prompts to appear and mess with `*1`, `*2`, etc.") + ;;;###autoload (define-minor-mode inf-clojure-minor-mode "Minor mode for interacting with the inferior Clojure process buffer. @@ -430,7 +437,8 @@ The following commands are available: :lighter inf-clojure-mode-line :keymap inf-clojure-minor-mode-map (setq-local comint-input-sender 'inf-clojure--send-string) - (inf-clojure-eldoc-setup) + (when inf-clojure-enable-eldoc + (inf-clojure-eldoc-setup)) (make-local-variable 'completion-at-point-functions) (add-to-list 'completion-at-point-functions #'inf-clojure-completion-at-point)) @@ -632,7 +640,8 @@ to continue it." (setq mode-line-process '(":%s")) (clojure-mode-variables) (clojure-font-lock-setup) - (inf-clojure-eldoc-setup) + (when inf-clojure-enable-eldoc + (inf-clojure-eldoc-setup)) (setq comint-get-old-input #'inf-clojure-get-old-input) (setq comint-input-filter #'inf-clojure-input-filter) (setq-local comint-prompt-read-only inf-clojure-prompt-read-only) @@ -1408,6 +1417,7 @@ Return the number of nested sexp the point was over or after." "Backend function for eldoc to show argument list in the echo area." ;; todo: this never gets unset once connected and is a lie (when (and (inf-clojure-connected-p) + inf-clojure-enable-eldoc ;; don't clobber an error message in the minibuffer (not (member last-command '(next-error previous-error)))) (let* ((info (inf-clojure-eldoc-info-in-current-sexp)) From 6dcf449dea3f68ec532d034bd3ac50773a2b3e9a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 15 Mar 2022 12:58:48 +0200 Subject: [PATCH 140/189] Bump the development version --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 1e588fd..6808409 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, clojure -;; Version: 3.1.0 +;; Version: 3.2.0-snapshot ;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From e6ae253326d5f508872ef494f77001ce6be88769 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 15 Mar 2022 12:59:58 +0200 Subject: [PATCH 141/189] Add missing metadata --- inf-clojure.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 6808409..ffe20e4 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -425,7 +425,10 @@ mode line entirely." Set to `nil` to disable eldoc. Eldoc can be quite useful by displaying function signatures in the modeline, but can also -cause multiple prompts to appear and mess with `*1`, `*2`, etc.") +cause multiple prompts to appear and mess with `*1`, `*2`, etc." + :type 'boolean + :safe 'booleanp + :package-version '(inf-clojure . "3.2.0")) ;;;###autoload (define-minor-mode inf-clojure-minor-mode From f511dcad0e0684c9609c7526930e88d11da989ab Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 15 Mar 2022 13:02:48 +0200 Subject: [PATCH 142/189] Tweak docstring --- inf-clojure.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index ffe20e4..b5b1388 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -421,11 +421,12 @@ mode line entirely." :risky t) (defcustom inf-clojure-enable-eldoc t - "Var that allows disabling `eldoc-mode` in `inf-clojure`. + "Var that allows disabling `eldoc-mode' in `inf-clojure'. -Set to `nil` to disable eldoc. Eldoc can be quite useful by +Set to nil to disable eldoc. Eldoc can be quite useful by displaying function signatures in the modeline, but can also -cause multiple prompts to appear and mess with `*1`, `*2`, etc." +cause multiple prompts to appear in the REPL and mess with *1, +*2, etc." :type 'boolean :safe 'booleanp :package-version '(inf-clojure . "3.2.0")) From abeab8d6d4cb3bdded5e9083776aab0c06cbdf57 Mon Sep 17 00:00:00 2001 From: winterbeardo <103951470+winterbeardo@users.noreply.github.com> Date: Thu, 21 Apr 2022 00:59:57 -0500 Subject: [PATCH 143/189] [Fix #185] Improve cmd string splitting (#198) The following now works: (inf-clojure "clojure -Sdeps \"{:deps {insn/insn {:mvn/version \\\"0.5.4\\\"}}}\"") --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index b5b1388..bb07c34 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -775,7 +775,7 @@ process buffer for a list of commands.)" (let ((default-directory (or project-dir default-directory)) (cmdlist (if (consp cmd) (list cmd) - (split-string cmd))) + (split-string-and-unquote cmd))) (repl-type (or (unless prefix-arg inf-clojure-custom-repl-type) (car (rassoc cmd inf-clojure-startup-forms)) From 8f295050a856b03d6ec14f0fd5e782e7acde6e2d Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 3 Jun 2022 11:23:50 -0400 Subject: [PATCH 144/189] Added function for switching back from an inf-clojure buffer (#200) * Added function for switching back from an inf-clojure buffer * set inf-clojure--recent-buffer on inf-clojure-connect * use most recent buffer instead of 'last swapped from' buffer * provide display-buffer-reuse-window one day I'll learn how to read and pass args in emacs --- CHANGELOG.md | 1 + inf-clojure.el | 27 +++++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index daccb36..4880f36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### New features +* [#168](https://github.com/clojure-emacs/inf-clojure/pull/197): Helper function `inf-clojure-switch-to-recent-buffer` to select the last buffer an inf-clojure process buffer was swapped to from. * [#187](https://github.com/clojure-emacs/inf-clojure/pull/197): Defcustom `inf-clojure-enable-eldoc` to disable eldoc interaction. ## 3.1.0 (2021-07-23) diff --git a/inf-clojure.el b/inf-clojure.el index bb07c34..484e211 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -330,6 +330,7 @@ Either \"no process\" or \"buffer-name(repl-type)\"" (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) (define-key map (kbd "C-c M-o") #'inf-clojure-clear-repl-buffer) (define-key map (kbd "C-c C-q") #'inf-clojure-quit) + (define-key map (kbd "C-c C-z") #'inf-clojure-switch-to-recent-buffer) (easy-menu-define inf-clojure-mode-menu map "Inferior Clojure REPL Menu" '("Inf-Clojure REPL" @@ -694,22 +695,36 @@ to continue it." (let ((comint-buffer-maximum-size 0)) (comint-truncate-buffer)))) +(defun inf-clojure--swap-to-buffer-window (to-buffer) + "Switch to `TO-BUFFER''s window." + (let ((pop-up-frames + ;; Be willing to use another frame + ;; that already has the window in it. + (or pop-up-frames + (get-buffer-window to-buffer t)))) + (pop-to-buffer to-buffer '(display-buffer-reuse-window . ())))) + (defun inf-clojure-switch-to-repl (eob-p) "Switch to the inferior Clojure process buffer. With prefix argument EOB-P, positions cursor at end of buffer." (interactive "P") (if (get-buffer-process inf-clojure-buffer) - (let ((pop-up-frames - ;; Be willing to use another frame - ;; that already has the window in it. - (or pop-up-frames - (get-buffer-window inf-clojure-buffer t)))) - (pop-to-buffer inf-clojure-buffer)) + (inf-clojure--swap-to-buffer-window inf-clojure-buffer) (call-interactively #'inf-clojure)) (when eob-p (push-mark) (goto-char (point-max)))) +(defun inf-clojure-switch-to-recent-buffer () + "Switch to the most recently used `inf-clojure-minor-mode' buffer." + (interactive) + (let ((recent-inf-clojure-minor-mode-buffer (seq-find (lambda (buf) + (with-current-buffer buf (bound-and-true-p inf-clojure-minor-mode))) + (buffer-list)))) + (if recent-inf-clojure-minor-mode-buffer + (inf-clojure--swap-to-buffer-window recent-inf-clojure-minor-mode-buffer) + (message "inf-clojure: No recent buffer known.")))) + (defun inf-clojure-quit (&optional buffer) "Kill the REPL buffer and its underlying process. From 64c9af8531afcb3c03ed990b4f6ea101a0b4d577 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 11 Jul 2022 08:50:28 +0300 Subject: [PATCH 145/189] Tweak the README a bit --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fe08189..d919ba2 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This package provides basic interaction with a Clojure subprocess (REPL). It's based on ideas from the popular `inferior-lisp` package. -`inf-clojure` has two components - a nice REPL buffer (`inf-clojure`) and a REPL +`inf-clojure` has two components - a nice REPL buffer (`inf-clojure-mode`) and a REPL interaction minor mode (`inf-clojure-minor-mode`), which extends `clojure-mode` with commands to evaluate forms directly in the REPL. @@ -70,18 +70,18 @@ the right code for each REPL type. **Note:** `inf-clojure` requires Emacs 25 or newer. -`inf-clojure` is available on the community-maintained `package.el` repos - +`inf-clojure` is available on the official [NonGNU ELPA](https://elpa.nongnu.org/nongnu/inf-clojure.html) `package.el` repo and on the community-maintained [MELPA Stable][] and [MELPA][] repos. -MELPA Stable is recommended as it has the latest stable version. +NonGNU ELPA and MELPA Stable are recommended as they have the latest stable version. MELPA has a development snapshot for users who don't mind breakage but -don't want to run from a git checkout. +don't want to run `inf-clojure` from a git checkout. You can install `inf-clojure` using the following command: M-x package-install [RET] inf-clojure [RET] -or if you'd rather keep it in your dotfiles: +or if you'd rather keep it in your Emacs config: ```emacs-lisp (unless (package-installed-p 'inf-clojure) @@ -122,11 +122,11 @@ and enter its host and port numbers. Inf-clojure aims to be very simple and offer tooling that the REPL itself exposes. A few commands are: -- 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` +- 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`) 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 From f3c1de4a43f8cb6dbd6caf919665057db04321a4 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 11 Jul 2022 08:54:30 +0300 Subject: [PATCH 146/189] Replace mentions of clojure-complete with incomplete --- README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d919ba2..391c0a5 100644 --- a/README.md +++ b/README.md @@ -385,13 +385,13 @@ Code completion is a tricky aspect if you are trying to be as close to a generic REPL as possible. Planck and lumo REPL implementations explicitly provide completion functions in their REPL namespaces. For clojure, you will need to have a library on your classpath. If you are -using lein, you already have -[clojure-complete](https://github.com/ninjudd/clojure-complete). You +using a recent version of Leiningen, you already have +[incomplete](https://github.com/nrepl/incomplete). You could alternatively use `compliment {:mvn/version "0.3.10"}`. ```emacs-lisp -;; for clojure-complete -(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")") +;; for incomplete +(inf-clojure-update-feature 'clojure 'completion "(incomplete.core/completions \"%s\")") ;; or ;; for compliment @@ -401,17 +401,14 @@ could alternatively use `compliment {:mvn/version "0.3.10"}`. If you give a form for the completion form, it is your responsibility to ensure that this namespace is on the classpath and required. If -using lein, this is done for you with clojure-complete. If adding -compliment, the following sample deps.edn can conveniently add the dep -to your program. - -Sample deps.edn: +using Leiningen, this is done for you with `incomplete`. If adding +`compliment`, the following sample `deps.edn` can conveniently add the dep +to your program: ```clojure {:aliases {:compliment {:extra-deps {compliment {:mvn/version "0.3.10"}}}}} ``` - Use the startup command: `clojure -A:compliment`. Then require the ns once so that the completion machinery will work: `(require 'compliment.core)`. Now tab completion should work. @@ -422,7 +419,7 @@ to customization. Not only you can `setq` the customary `inf-clojure-completion-form-planck` and `inf-clojure-completion-form-joker` - 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 +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 @@ -434,7 +431,7 @@ it](https://github.com/clojure-emacs/cider/blob/3e9ed12e8cfbad04d7618e649322765d For an optimal Lumo experience the `-d` needs to be passed to Lumo when launched from the command line. This disable `readline` support -in order to play nicely with emacs. +in order to play nicely with Emacs. ## Troubleshooting From 771cf6da1df65e1fccfcd0d0a9fc911b100e4bed Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Mon, 11 Jul 2022 08:55:53 +0300 Subject: [PATCH 147/189] Update one more reference to clojure-complete --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 391c0a5..6e8d53e 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ If you want to update a specific form there is a function `inf-clojure-update-repl-feature` which can be used like so: ```emacs-lisp -(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")") +(inf-clojure-update-feature 'clojure 'completion "(incomplete.core/completions \"%s\")") ``` #### Caveats From 0bef87ca08f131867cdd5d7d4a22b211c3dc9557 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 15 Jul 2022 11:56:49 +0300 Subject: [PATCH 148/189] Tweak keywords --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 484e211..cec2a45 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -5,7 +5,7 @@ ;; Authors: Bozhidar Batsov ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure -;; Keywords: processes, clojure +;; Keywords: processes, comint, clojure ;; Version: 3.2.0-snapshot ;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) From 8ac47af1083c640ef558ece8556de9caf3f9f4ea Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 15 Jul 2022 11:59:33 +0300 Subject: [PATCH 149/189] Fix package version extraction logic --- inf-clojure.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index cec2a45..643b75e 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -293,8 +293,9 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte :link '(emacs-commentary-link :tag "Commentary" "inf-clojure")) (defconst inf-clojure-version - (eval-when-compile - (lm-version (or load-file-name buffer-file-name))) + (or (if (fboundp 'package-get-version) + (package-get-version)) + "3.2.0") "The current version of `inf-clojure'.") (defcustom inf-clojure-prompt-read-only t From 67b0403aa183d521e36545266100f1f62a34e783 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 15 Jul 2022 12:05:27 +0300 Subject: [PATCH 150/189] Release 3.2.0 --- CHANGELOG.md | 13 ++++++++++--- inf-clojure.el | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4880f36..c752aca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,18 @@ ## master (unreleased) +## 3.2.0 (2022-07-15) + ### New features -* [#168](https://github.com/clojure-emacs/inf-clojure/pull/197): Helper function `inf-clojure-switch-to-recent-buffer` to select the last buffer an inf-clojure process buffer was swapped to from. -* [#187](https://github.com/clojure-emacs/inf-clojure/pull/197): Defcustom `inf-clojure-enable-eldoc` to disable eldoc interaction. +* [#168](https://github.com/clojure-emacs/inf-clojure/pull/197): New helper function `inf-clojure-switch-to-recent-buffer` to select the last buffer an inf-clojure process buffer was swapped to from. +* [#187](https://github.com/clojure-emacs/inf-clojure/pull/197): New defcustom `inf-clojure-enable-eldoc` to disable eldoc interaction. + +### Bugs fixed + +* [#185](https://github.com/clojure-emacs/inf-clojure/issues/185): Improve cmd string splitting. +* [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in REPL buffer. +* Fix `inf-clojure-display-version` (it wasn't extracting properly the package version). ## 3.1.0 (2021-07-23) @@ -17,7 +25,6 @@ ### Bugs fixed -* [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in REPL buffer. * [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. * [#188](https://github.com/clojure-emacs/inf-clojure/pull/188): Handle newlines between forms for `inf-clojure-eval-buffer`. * [#189](https://github.com/clojure-emacs/inf-clojure/pull/189): Font-lock code inserted in the REPL from a source buffer. diff --git a/inf-clojure.el b/inf-clojure.el index 643b75e..6e871ff 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -6,7 +6,7 @@ ;; Olin Shivers ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure -;; Version: 3.2.0-snapshot +;; Version: 3.2.0 ;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From 7de63df35fd912fb04fde56a1c07862e0e22bfe4 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sat, 16 Jul 2022 19:51:15 +0300 Subject: [PATCH 151/189] Small fixes to make NonGNU ELPA happier Thanks @monnier! --- .gitignore | 4 ++++ inf-clojure.el | 25 +++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index c724233..22372af 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ TAGS dist .vagrant/ .dir-locals?.el + +# ELPA-generated files +/inf-clojure-autoloads.el +/inf-clojure-pkg.el diff --git a/inf-clojure.el b/inf-clojure.el index 6e871ff..9cc217d 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -4,6 +4,7 @@ ;; Authors: Bozhidar Batsov ;; Olin Shivers +;; Maintainer: Bozhidar Batsov ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure ;; Version: 3.2.0 @@ -212,8 +213,8 @@ If no-error is truthy don't error if feature is not present." (defun inf-clojure--update-feature (repl-type feature form) "Return a copy of the datastructure containing the repl features. -Given a REPL-TYPE ('clojure, 'lumo, ...) and a FEATURE ('doc, -'apropos, ...) and a FORM this will return a new datastructure +Given a REPL-TYPE (`clojure', `lumo', ...) and a FEATURE (`doc', +`apropos', ...) and a FORM this will return a new datastructure that can be set as `inf-clojure-repl-features'." (let ((original (alist-get repl-type inf-clojure-repl-features))) (if original @@ -225,8 +226,8 @@ that can be set as `inf-clojure-repl-features'." (defun inf-clojure-update-feature (repl-type feature form) "Mutate the repl features to the new FORM. -Given a REPL-TYPE ('clojure, 'lumo, ...) and a FEATURE ('doc, -'apropos, ...) and a FORM this will set +Given a REPL-TYPE (`clojure', `lumo', ...) and a FEATURE (`doc', +`apropos', ...) and a FORM this will set `inf-clojure-repl-features' with these new values." (setq inf-clojure-repl-features (inf-clojure--update-feature repl-type feature form))) @@ -352,7 +353,7 @@ Either \"no process\" or \"buffer-name(repl-type)\"" map)) (defvar inf-clojure-insert-commands-map - (let ((map (define-prefix-command 'inf-clojure-insert-commands-map))) + (let ((map (make-sparse-keymap))) (define-key map (kbd "d") #'inf-clojure-insert-defun) (define-key map (kbd "C-d") #'inf-clojure-insert-defun) (define-key map (kbd "e") #'inf-clojure-insert-last-sexp) @@ -369,7 +370,7 @@ Either \"no process\" or \"buffer-name(repl-type)\"" (define-key map (kbd "C-c C-r") #'inf-clojure-eval-region) (define-key map (kbd "C-c M-r") #'inf-clojure-reload) (define-key map (kbd "C-c C-n") #'inf-clojure-eval-form-and-next) - (define-key map (kbd "C-c C-j") 'inf-clojure-insert-commands-map) + (define-key map (kbd "C-c C-j") inf-clojure-insert-commands-map) (define-key map (kbd "C-c C-z") #'inf-clojure-switch-to-repl) (define-key map (kbd "C-c C-i") #'inf-clojure-show-ns-vars) (define-key map (kbd "C-c C-S-a") #'inf-clojure-apropos) @@ -430,7 +431,7 @@ displaying function signatures in the modeline, but can also cause multiple prompts to appear in the REPL and mess with *1, *2, etc." :type 'boolean - :safe 'booleanp + :safe #'booleanp :package-version '(inf-clojure . "3.2.0")) ;;;###autoload @@ -926,10 +927,10 @@ Indent FORM. FORM is expected to have been trimmed." (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point)))) -;;; Now that inf-clojure-eval-/defun/region takes an optional prefix arg, -;;; these commands are redundant. But they are kept around for the user -;;; to bind if he wishes, for backwards functionality, and because it's -;;; easier to type C-c e than C-u C-c C-e. +;; Now that inf-clojure-eval-/defun/region takes an optional prefix arg, +;; these commands are redundant. But they are kept around for the user +;; to bind if he wishes, for backwards functionality, and because it's +;; easier to type C-c e than C-u C-c C-e. (defun inf-clojure-eval-region-and-go (start end) "Send the current region to the inferior Clojure, and switch to its buffer. @@ -1017,7 +1018,7 @@ display." (if (zerop (length ans)) default ans)))) -;;; Adapted from function-called-at-point in help.el. +;; Adapted from function-called-at-point in help.el. (defun inf-clojure-fn-called-at-pt () "Return the name of the function called in the current call. The value is nil if it can't find one." From 151b20ba9d3ae39b88f91aecbab98bd5a5215f1a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 22 Jul 2022 09:28:14 +0300 Subject: [PATCH 152/189] Release 3.2.1 --- CHANGELOG.md | 6 ++++++ inf-clojure.el | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c752aca..139613a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## master (unreleased) +## 3.2.1 (2022-07-22) + +### Bugs fixed + +* Address some small issues with NonGNU ELPA (e.g. missing maintainer metadata). + ## 3.2.0 (2022-07-15) ### New features diff --git a/inf-clojure.el b/inf-clojure.el index 9cc217d..1297cb5 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -7,7 +7,7 @@ ;; Maintainer: Bozhidar Batsov ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure -;; Version: 3.2.0 +;; Version: 3.2.1 ;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. @@ -296,7 +296,7 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte (defconst inf-clojure-version (or (if (fboundp 'package-get-version) (package-get-version)) - "3.2.0") + "3.2.1") "The current version of `inf-clojure'.") (defcustom inf-clojure-prompt-read-only t From f436760489cd95400b5a5449158161031beac7ba Mon Sep 17 00:00:00 2001 From: Emma Griffin <53583563+E-A-Griffin@users.noreply.github.com> Date: Sat, 23 Jul 2022 11:36:04 -0400 Subject: [PATCH 153/189] Add ClojureCLR support (#203) --- CHANGELOG.md | 1 + README.md | 3 ++- inf-clojure.el | 20 ++++++++++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 139613a..a0fa722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## master (unreleased) +* [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. ## 3.2.1 (2022-07-22) diff --git a/README.md b/README.md index 6e8d53e..a0ec0dd 100644 --- a/README.md +++ b/README.md @@ -31,13 +31,14 @@ It supports the following REPLs: - Clojure - ClojureScript +- ClojureCLR (via [lein-clr](https://github.com/kumarshantanu/lein-clr)) - [Planck](http://planck-repl.org/) - [Lumo](https://github.com/anmonteiro/lumo) - [Joker](https://joker-lang.org/) - [babashka](https://github.com/borkdude/babashka) `inf-clojure` provides a set of essential features for interactive -Clojure(Script) development: +Clojure/ClojureScript/ClojureCLR development: * Enhanced REPL * Interactive code evaluation diff --git a/inf-clojure.el b/inf-clojure.el index 1297cb5..a213a55 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -36,7 +36,7 @@ ;; REPL. ;; ;; `inf-clojure` provides a set of essential features for interactive -;; Clojure(Script) development: +;; Clojure/ClojureScript/ClojureCLR development: ;; ;; * REPL ;; * Interactive code evaluation @@ -75,6 +75,7 @@ (boot . "boot repl") (clojure . "clojure") (cljs . "clojure -m cljs.main -r") + (lein-clr . "lein clr repl") (planck . "planck -d") (babashka . "bb") (lumo . "lumo -d") @@ -153,7 +154,22 @@ (ns-vars . "(clojure.repl/dir %s)") (set-ns . "(clojure.core/in-ns '%s)") (macroexpand . "(clojure.core/macroexpand '%s)") - (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))))) + (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))) + (lein-clr . ((load . "(clojure.core/load-file \"%s\")") + (doc . "(clojure.repl/doc %s)") + (source . "(clojure.repl/source %s)") + (arglists . + "(try + (:arglists + (clojure.core/meta + (clojure.core/resolve + (clojure.core/read-string \"%s\")))) + (catch Exception e nil))") + (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))") + (ns-vars . "(clojure.repl/dir %s)") + (set-ns . "(clojure.core/in-ns '%s)") + (macroexpand . "(clojure.core/macroexpand '%s)") + (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))))) (defvar-local inf-clojure-repl-type nil "Symbol to define your REPL type. From 59a9f0695f3d97a593f8d5ea04b51ea5dcb2718a Mon Sep 17 00:00:00 2001 From: dpsutton Date: Sun, 7 Aug 2022 16:13:04 -0500 Subject: [PATCH 154/189] Ensure repl scrolls on insert (#204) When inserting forms into the repl, the buffer doesn't always scroll to show the new input and result. This has been fixed in CIDER in a similar way, so now I'm bringing the same trick here. See https://github.com/clojure-emacs/cider/pull/2590 for more details. --- CHANGELOG.md | 2 ++ inf-clojure.el | 25 +++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0fa722..6bf9e4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) * [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. +* [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands + ## 3.2.1 (2022-07-22) diff --git a/inf-clojure.el b/inf-clojure.el index a213a55..3b7f8dc 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -920,16 +920,21 @@ Prefix argument AND-GO means switch to the Clojure buffer afterwards." "Insert FORM into process and evaluate. Indent FORM. FORM is expected to have been trimmed." (let ((clojure-process (inf-clojure-proc))) - (with-current-buffer (process-buffer clojure-process) - (comint-goto-process-mark) - (let ((beginning (point))) - (insert (format "%s" form)) - (let ((end (point))) - (goto-char beginning) - (indent-sexp end) - ;; font-lock the inserted code - (font-lock-ensure beginning end))) - (comint-send-input t t)))) + ;; ensure the repl buffer scrolls. See similar fix in CIDER: + ;; https://github.com/clojure-emacs/cider/pull/2590 + (with-selected-window (or (get-buffer-window inf-clojure-buffer) + (selected-window)) + (with-current-buffer (process-buffer clojure-process) + (comint-goto-process-mark) + (let ((beginning (point))) + (insert form) + (let ((end (point))) + (goto-char beginning) + (indent-sexp end) + ;; font-lock the inserted code + (font-lock-ensure beginning end) + (goto-char end))) + (comint-send-input t t))))) (defun inf-clojure-insert-defun () "Send current defun to process." From e5ce3839835b9b561fca5810f43f413c96c197d9 Mon Sep 17 00:00:00 2001 From: Danny Date: Sun, 13 Nov 2022 13:54:16 +0000 Subject: [PATCH 155/189] Use comint-mode-map as parent map instead Whilst playing with inf-clojure-mode-map, some previous binds are overriden, because copy-keymap is used instead of set-parent-map. This will help for that. --- inf-clojure.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 3b7f8dc..b439722 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -339,7 +339,8 @@ Either \"no process\" or \"buffer-name(repl-type)\"" "no process")) (defvar inf-clojure-mode-map - (let ((map (copy-keymap comint-mode-map))) + (let ((map (make-sparse-keymap))) + (set-keymap-parent map comint-mode-map) (define-key map (kbd "C-x C-e") #'inf-clojure-eval-last-sexp) (define-key map (kbd "C-c C-l") #'inf-clojure-load-file) (define-key map (kbd "C-c C-a") #'inf-clojure-show-arglists) From 4ab78518c881dc3653e4f071eb4865c1c51f91c2 Mon Sep 17 00:00:00 2001 From: Justin Tirrell Date: Fri, 24 Feb 2023 11:45:14 -0500 Subject: [PATCH 156/189] Display message after setting repl --- CHANGELOG.md | 1 + inf-clojure.el | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bf9e4c..a77b1e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## master (unreleased) * [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. * [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands +* [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting repl. ## 3.2.1 (2022-07-22) diff --git a/inf-clojure.el b/inf-clojure.el index b439722..0dbc7f6 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -281,14 +281,17 @@ ALWAYS-ASK). Otherwise get a list of all active inf-clojure REPLS and offer a choice. It's recommended to rename REPL buffers after they are created with `rename-buffer'." (interactive "P") - (if (and (not always-ask) - (inf-clojure-repl-p)) - (setq inf-clojure-buffer (current-buffer)) - (let ((repl-buffers (inf-clojure-repls))) - (if (> (length repl-buffers) 0) - (when-let ((repl-buffer (completing-read "Select default REPL: " repl-buffers nil t))) - (setq inf-clojure-buffer (get-buffer repl-buffer))) - (user-error "No buffers have an inf-clojure process"))))) + (let ((new-repl-buffer + (if (and (not always-ask) + (inf-clojure-repl-p)) + (setq inf-clojure-buffer (current-buffer)) + (let ((repl-buffers (inf-clojure-repls))) + (if (> (length repl-buffers) 0) + (when-let ((repl-buffer (completing-read "Select default REPL: " repl-buffers nil t))) + (setq inf-clojure-buffer (get-buffer repl-buffer))) + (user-error "No buffers have an inf-clojure process")))))) + (when new-repl-buffer + (message "Current inf-clojure REPL set to %s" new-repl-buffer)))) (defvar inf-clojure--repl-type-lock nil "Global lock for protecting against proc filter race conditions. From 3cfc4f0bd598146b4ca664b8a3da2e5410681a36 Mon Sep 17 00:00:00 2001 From: Justin Tirrell Date: Fri, 24 Feb 2023 18:37:49 -0500 Subject: [PATCH 157/189] Don't use outer let --- inf-clojure.el | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 0dbc7f6..01d6f1b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -281,17 +281,17 @@ ALWAYS-ASK). Otherwise get a list of all active inf-clojure REPLS and offer a choice. It's recommended to rename REPL buffers after they are created with `rename-buffer'." (interactive "P") - (let ((new-repl-buffer - (if (and (not always-ask) - (inf-clojure-repl-p)) - (setq inf-clojure-buffer (current-buffer)) - (let ((repl-buffers (inf-clojure-repls))) - (if (> (length repl-buffers) 0) - (when-let ((repl-buffer (completing-read "Select default REPL: " repl-buffers nil t))) - (setq inf-clojure-buffer (get-buffer repl-buffer))) - (user-error "No buffers have an inf-clojure process")))))) - (when new-repl-buffer - (message "Current inf-clojure REPL set to %s" new-repl-buffer)))) + (if (and (not always-ask) + (inf-clojure-repl-p)) + (progn + (setq inf-clojure-buffer (current-buffer)) + (message "Current inf-clojure REPL set to %s" inf-clojure-buffer)) + (let ((repl-buffers (inf-clojure-repls))) + (if (> (length repl-buffers) 0) + (when-let ((repl-buffer (completing-read "Select default REPL: " repl-buffers nil t))) + (setq inf-clojure-buffer (get-buffer repl-buffer)) + (message "Current inf-clojure REPL set to %s" inf-clojure-buffer)) + (user-error "No buffers have an inf-clojure process"))))) (defvar inf-clojure--repl-type-lock nil "Global lock for protecting against proc filter race conditions. From fb9b5ea55f9ef02be32660cc29df15023968fb78 Mon Sep 17 00:00:00 2001 From: Justin Tirrell Date: Sat, 25 Feb 2023 12:39:49 -0500 Subject: [PATCH 158/189] Extract function to prompt for repl buffer --- inf-clojure.el | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 01d6f1b..3e86834 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -274,6 +274,16 @@ Checks the mode and that there is a live process." (push (buffer-name b) repl-buffers))) repl-buffers)) +(defun inf-clojure--prompt-repl-buffer (prompt) + "Prompt the user to select an inf-clojure repl buffer. +PROMPT is a string to prompt the user. +Returns nil when no buffer is selected." + (let ((repl-buffers (inf-clojure-repls))) + (if (> (length repl-buffers) 0) + (when-let ((repl-buffer (completing-read prompt repl-buffers nil t))) + (get-buffer repl-buffer)) + (user-error "No buffers have an inf-clojure process")))) + (defun inf-clojure-set-repl (always-ask) "Set an inf-clojure buffer as the active (default) REPL. If in a REPL buffer already, use that unless a prefix is used (or @@ -281,17 +291,13 @@ ALWAYS-ASK). Otherwise get a list of all active inf-clojure REPLS and offer a choice. It's recommended to rename REPL buffers after they are created with `rename-buffer'." (interactive "P") - (if (and (not always-ask) - (inf-clojure-repl-p)) - (progn - (setq inf-clojure-buffer (current-buffer)) - (message "Current inf-clojure REPL set to %s" inf-clojure-buffer)) - (let ((repl-buffers (inf-clojure-repls))) - (if (> (length repl-buffers) 0) - (when-let ((repl-buffer (completing-read "Select default REPL: " repl-buffers nil t))) - (setq inf-clojure-buffer (get-buffer repl-buffer)) - (message "Current inf-clojure REPL set to %s" inf-clojure-buffer)) - (user-error "No buffers have an inf-clojure process"))))) + (when-let ((new-repl-buffer + (if (or always-ask + (not (inf-clojure-repl-p))) + (inf-clojure--prompt-repl-buffer "Select default REPL: ") + (current-buffer)))) + (setq inf-clojure-buffer new-repl-buffer) + (message "Current inf-clojure REPL set to %s" new-repl-buffer))) (defvar inf-clojure--repl-type-lock nil "Global lock for protecting against proc filter race conditions. From 05bf92ffbd6cf613eab4edaa07865f219c6d10dd Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 24 Mar 2023 10:22:10 +0200 Subject: [PATCH 159/189] Update the CI setup to match that of CIDER --- .circleci/config.yml | 120 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 31918ba..d2a8cef 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,36 +1,120 @@ version: 2.1 +orbs: + win: circleci/windows@2.2.0 + # Default actions to perform on each Emacs version -default: &default-steps - steps: - - checkout - - run: apt-get update && apt-get install make - - run: make test +commands: + setup: + steps: + - checkout + - run: + name: Install Eldev + command: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev > x.sh && source ./x.sh + + macos-setup: + steps: + - checkout + - run: + name: Install Emacs latest + command: | + echo "HOMEBREW_NO_AUTO_UPDATE=1" >> $BASH_ENV + brew install homebrew/cask/emacs + - run: + name: Install Eldev + command: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev > x.sh && source ./x.sh + + setup-windows: + steps: + - checkout + - run: + name: Install Eldev + command: | + # Remove expired DST Root CA X3 certificate. Workaround + # for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=51038 + # bug on Emacs 27.2. + gci cert:\LocalMachine\Root\DAC9024F54D8F6DF94935FB1732638CA6AD77C13 + gci cert:\LocalMachine\Root\DAC9024F54D8F6DF94935FB1732638CA6AD77C13 | Remove-Item + (iwr https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev.ps1).Content | powershell -command - + test: + steps: + - run: + name: Run regression tests + command: eldev -dtT -p test + lint: + steps: + - run: + name: Run Elisp-lint + command: eldev lint + - run: + name: Byte-compile `.el' files + command: eldev -dtT compile --warnings-as-errors -# Enumerated list of Emacs versions jobs: - test-emacs-26: + test-ubuntu-emacs-26: + docker: + - image: silex/emacs:26-ci + entrypoint: bash + steps: + - setup + - test + + test-ubuntu-emacs-27: docker: - - image: silex/emacs:26-ci-cask + - image: silex/emacs:27-ci entrypoint: bash - <<: *default-steps + steps: + - setup + - test - test-emacs-27: + test-ubuntu-emacs-28: docker: - - image: silex/emacs:27-ci-cask + - image: silex/emacs:28-ci entrypoint: bash - <<: *default-steps + steps: + - setup + - test - test-emacs-master: + test-ubuntu-emacs-master: docker: - - image: silex/emacs:master-ci-cask + - image: silex/emacs:master-ci entrypoint: bash - <<: *default-steps + steps: + - setup + - test + + test-macos-emacs-latest: + macos: + xcode: "14.0.0" + steps: + - macos-setup + - test + + test-windows-emacs-latest: + executor: win/default + steps: + - run: + name: Install Emacs latest + command: | + choco install emacs + - setup-windows + - test + + test-lint: + docker: + - image: silex/emacs:28-ci + steps: + - setup + - lint workflows: version: 2 ci-test-matrix: jobs: - - test-emacs-26 - - test-emacs-27 - - test-emacs-master + - test-ubuntu-emacs-26 + - test-ubuntu-emacs-27 + - test-ubuntu-emacs-28 + - test-ubuntu-emacs-master + - test-lint + - test-macos-emacs-latest + - test-windows-emacs-latest From 2fd4873025be00ddc092a664b482048e06c5aa47 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 24 Mar 2023 11:12:32 +0200 Subject: [PATCH 160/189] Replace Cask with Eldev --- Cask | 11 ----------- Eldev | 7 +++++++ Makefile | 19 ------------------- 3 files changed, 7 insertions(+), 30 deletions(-) delete mode 100644 Cask create mode 100644 Eldev delete mode 100644 Makefile diff --git a/Cask b/Cask deleted file mode 100644 index d2a5667..0000000 --- a/Cask +++ /dev/null @@ -1,11 +0,0 @@ -(source gnu) -(source melpa) - -(package-file "inf-clojure.el") - -(files "*.el" (:exclude ".dir-locals.el")) - -(development - (depends-on "clojure-mode") - (depends-on "buttercup") - (depends-on "assess")) diff --git a/Eldev b/Eldev new file mode 100644 index 0000000..8581b45 --- /dev/null +++ b/Eldev @@ -0,0 +1,7 @@ +; -*- mode: emacs-lisp; lexical-binding: t; no-byte-compile: t -*- + +(eldev-use-package-archive 'gnu) +(eldev-use-package-archive 'nongnu) +(eldev-use-package-archive 'melpa-stable) + +(eldev-use-plugin 'autoloads) diff --git a/Makefile b/Makefile deleted file mode 100644 index d002f72..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -.PHONY: clean version test - -all: build - -clean: - rm -rf .cask - -.cask: - cask install - cask update - -version: - emacs --version - -build: version .cask - cask build - -test: version .cask - cask exec buttercup -L . From 836d7a31735bd77340fe5fc772cda2cb8f1a2c00 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 24 Mar 2023 11:13:08 +0200 Subject: [PATCH 161/189] Ignore .eldev --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 22372af..9e62e23 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ elpa* TAGS .DS_STORE dist +.eldev .vagrant/ .dir-locals?.el From e555702f87ea2d20109c15766652b6f3d004976a Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 24 Mar 2023 11:22:58 +0200 Subject: [PATCH 162/189] Add the missing assess dep for the tests --- Eldev | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Eldev b/Eldev index 8581b45..80ae7b1 100644 --- a/Eldev +++ b/Eldev @@ -4,4 +4,7 @@ (eldev-use-package-archive 'nongnu) (eldev-use-package-archive 'melpa-stable) +;; the tests depend on the assess library +(eldev-add-extra-dependencies 'test 'assess) + (eldev-use-plugin 'autoloads) From 8ad2242b75ea1a06fad391deb8f858a392408a94 Mon Sep 17 00:00:00 2001 From: Michael Bruce Date: Sun, 26 Mar 2023 20:46:52 +0100 Subject: [PATCH 163/189] [#209] Implement a command that starts a socket REPL (inf-clojure-socket-repl) (#210) --- CHANGELOG.md | 1 + README.md | 3 + inf-clojure.el | 178 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 156 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a77b1e5..836cd49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. * [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands * [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting repl. +* [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. ## 3.2.1 (2022-07-22) diff --git a/README.md b/README.md index a0ec0dd..7a022aa 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,9 @@ 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. +If you want to use a socket REPL server, use `M-x inf-clojure-socket-repl` +which will start a socket server and connect to it for you. + If you've already started a socket REPL server, use `M-x inf-clojure-connect` and enter its host and port numbers. diff --git a/inf-clojure.el b/inf-clojure.el index 3e86834..6f8d216 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -8,7 +8,7 @@ ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure ;; Version: 3.2.1 -;; Package-Requires: ((emacs "25.1") (clojure-mode "5.11")) +;; Package-Requires: ((emacs "26.2") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. @@ -74,7 +74,7 @@ (defvar inf-clojure-startup-forms '((lein . "lein repl") (boot . "boot repl") (clojure . "clojure") - (cljs . "clojure -m cljs.main -r") + (cljs . "clojure -M -m cljs.main -r") (lein-clr . "lein clr repl") (planck . "planck -d") (babashka . "bb") @@ -140,6 +140,17 @@ (set-ns . "(clojure.core/in-ns '%s)") (macroexpand . "(clojure.core/macroexpand '%s)") (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))) + (node-babashka . ((load . "(clojure.core/load-file \"%s\")") + (doc . "(clojure.repl/doc %s)") + (source . "(clojure.repl/source %s)") + (arglists . + "(try (-> '%s clojure.core/resolve clojure.core/meta :arglists) + (catch Throwable e nil))") + (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))") + (ns-vars . "(clojure.repl/dir %s)") + (set-ns . "(clojure.core/in-ns '%s)") + (macroexpand . "(clojure.core/macroexpand '%s)") + (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))) (clojure . ((load . "(clojure.core/load-file \"%s\")") (doc . "(clojure.repl/doc %s)") (source . "(clojure.repl/source %s)") @@ -641,33 +652,34 @@ Customization: Entry to this mode runs the hooks on `comint-mode-hook' and You can send text to the inferior Clojure process from other buffers containing Clojure source. - `inf-clojure-switch-to-repl' switches the current buffer to the Clojure process buffer. + `inf-clojure-switch-to-repl' switches the current buffer to the Clojure + process buffer. `inf-clojure-eval-defun' sends the current defun to the Clojure process. `inf-clojure-eval-region' sends the current region to the Clojure process. Prefixing the inf-clojure-eval/defun/region commands with - a \\[universal-argument] causes a switch to the Clojure process buffer after sending - the text. + a \\[universal-argument] causes a switch to the Clojure process buffer after + sending the text. Commands:\\ -\\[comint-send-input] after the end of the process' output sends the text from the - end of process to point. -\\[comint-send-input] before the end of the process' output copies the sexp ending at point - to the end of the process' output, and sends it. -\\[comint-copy-old-input] copies the sexp ending at point to the end of the process' output, - allowing you to edit it before sending it. -If `comint-use-prompt-regexp' is nil (the default), \\[comint-insert-input] on old input - copies the entire old input to the end of the process' output, allowing - you to edit it before sending it. When not used on old input, or if - `comint-use-prompt-regexp' is non-nil, \\[comint-insert-input] behaves according to - its global binding. +\\[comint-send-input] after the end of the process' output sends the text from + the end of process to point. +\\[comint-send-input] before the end of the process' output copies the sexp + ending at point to the end of the process' output, and sends it. +\\[comint-copy-old-input] copies the sexp ending at point to the end of the + process' output,allowing you to edit it before sending it. +If `comint-use-prompt-regexp' is nil (the default), \\[comint-insert-input] on + old input copies the entire old input to the end of the process' output, + allowing you to edit it before sending it. When not used on old input, or if + `comint-use-prompt-regexp' is non-nil, \\[comint-insert-input] behaves + according to its global binding. \\[backward-delete-char-untabify] converts tabs to spaces as it moves back. \\[clojure-indent-line] indents for Clojure; with argument, shifts rest of expression rigidly with the current line. -\\[indent-sexp] does \\[clojure-indent-line] on each line starting within following expression. -Paragraphs are separated only by blank lines. Semicolons start comments. -If you accidentally suspend your process, use \\[comint-continue-subjob] -to continue it." +\\[indent-sexp] does \\[clojure-indent-line] on each line starting within + following expression. Paragraphs are separated only by blank lines. + Semicolons start comments. If you accidentally suspend your process, + use \\[comint-continue-subjob] to continue it." (setq comint-input-sender 'inf-clojure--send-string) (setq comint-prompt-regexp inf-clojure-comint-prompt-regexp) (setq mode-line-process '(":%s")) @@ -807,9 +819,11 @@ process buffer for a list of commands.)" nil 'confirm-after-completion)))) (let* ((project-dir (clojure-project-dir)) - (process-buffer-name (if project-dir - (format "inf-clojure %s" (inf-clojure--project-name project-dir)) - "inf-clojure")) + (process-buffer-name (or + inf-clojure-custom-repl-name + (if project-dir + (format "inf-clojure %s" (inf-clojure--project-name project-dir)) + "inf-clojure"))) ;; comint adds the asterisks to both sides (repl-buffer-name (format "*%s*" process-buffer-name))) ;; Create a new comint buffer if needed @@ -819,10 +833,11 @@ process buffer for a list of commands.)" (cmdlist (if (consp cmd) (list cmd) (split-string-and-unquote cmd))) - (repl-type (or (unless prefix-arg + (repl-type (or inf-clojure-socket-repl-type + (unless prefix-arg inf-clojure-custom-repl-type) - (car (rassoc cmd inf-clojure-startup-forms)) - (inf-clojure--prompt-repl-type)))) + (car (rassoc cmd inf-clojure-startup-forms)) + (inf-clojure--prompt-repl-type)))) (message "Starting Clojure REPL via `%s'..." cmd) (with-current-buffer (apply #'make-comint process-buffer-name (car cmdlist) nil (cdr cmdlist)) @@ -843,6 +858,117 @@ HOST is the host the process is running on, PORT is where it's listening." (interactive "shost: \nnport: ") (inf-clojure (cons host port))) +(defvar-local inf-clojure-socket-callback nil + "Used to transfer state between the socket process buffer & REPL buffer.") + +(defvar-local inf-clojure-socket-buffer nil + "Used to kill the associated socket buffer when it's REPL buffer is killed.") + +(defun inf-clojure-socket-filter (process output) + "A filter that gets triggered each time the socket receives new OUTPUT. +This function prints out the output received but also +watches for a prompt using the `inf-clojure-prompt' regexp, once +this happens a callback is triggered if available. The callback +is intended to be used to trigger a `inf-clojure-connect' once we +can determine that a socket REPL is ready to receive a +connection. + +PROCESS is the process object that is being filtered. + +OUTPUT is the latest data received from the process" + (let ((server-buffer (process-buffer process))) + (when (buffer-live-p server-buffer) + (with-current-buffer server-buffer + (insert output))) + (let ((prompt-displayed (string-match inf-clojure-prompt output))) + (when prompt-displayed + (message (format "Socket REPL startup detected for %s" (process-name process))) + (with-current-buffer server-buffer + (when inf-clojure-socket-callback + (funcall inf-clojure-socket-callback))))))) + +(defun inf-clojure-socket-repl-sentinel (process event) + "Ensures socket REPL are cleaned up when the REPL buffer is closed. + +PROCESS is the process object that is connected to a socket REPL. + +EVENT is the event that triggered this function to be called." + (when (not (process-live-p process)) + (let ((repl-buffer (process-buffer process))) + (with-current-buffer repl-buffer + (when inf-clojure-socket-buffer + (kill-buffer inf-clojure-socket-buffer)))))) + +(defvar inf-clojure-socket-repl-startup-forms + '((lein . "JVM_OPTS='-Dclojure.server.repl={:port %d :accept clojure.core.server/repl}' lein repl") + (boot . "export BOOT_JVM_OPTIONS='-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\"' boot repl") + (clojure . "clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\"") + (cljs . "clojure -J-Dclojure.server.repl=\"{:port %d :accept cljs.server.browser/repl}\"") + (lein-clr . "JVM_OPTS='-Dclojure.server.repl={:port %d :accept clojure.core.server/repl}' lein clr repl") + (planck . "planck -n %d") + (babashka . "bb socket-repl %d"))) + +(defcustom inf-clojure-socket-repl-port + nil + "Port to be used when creating a socket REPL via `inf-clojure-socket-repl'. +If left as nil a random port will be selected between 5500-6000." + :type '(choice integer (const nil)) + :package-version '(inf-clojure . "3.3")) + +;;;###autoload +(defun inf-clojure-socket-repl (cmd) + "Start a socket REPL server and connect to it via `inf-clojure'. +CMD is the command line used to start the socket REPL, if this +isn't provided you will be prompted to select from the defaults +provided in `inf-clojure-socket-repl-startup-forms' or +`inf-clojure-custom-startup' if this is defined." + (interactive (list (or (unless current-prefix-arg + inf-clojure-custom-startup) + (completing-read "Select Clojure socket REPL startup command: " + (mapcar #'cdr inf-clojure-socket-repl-startup-forms) + nil + 'confirm-after-completion)))) + (let* ((host "localhost") + (port (or inf-clojure-socket-repl-port (+ 5500 (random 500)))) + (project-dir (clojure-project-dir)) + (repl-type (or (unless prefix-arg + inf-clojure-custom-repl-type) + (car (rassoc cmd inf-clojure-socket-repl-startup-forms)) + (inf-clojure--prompt-repl-type))) + (project-name (inf-clojure--project-name (or project-dir "standalone"))) + (socket-process-name (format "*%s-%s-socket-server*" project-name repl-type)) + (socket-buffer-name (format "*%s-%s-socket*" project-name repl-type)) + (socket-buffer (get-buffer-create socket-buffer-name)) + (repl-buffer-name (format "%s-%s-repl" project-name repl-type)) + (socket-form (or cmd + (cdr (assoc repl-type inf-clojure-socket-repl-startup-forms)) + inf-clojure-custom-startup)) + (socket-cmd (format socket-form port)) + (sock (let ((default-directory (or project-dir default-directory))) + (start-file-process-shell-command + socket-process-name socket-buffer + socket-cmd)))) + (with-current-buffer socket-buffer + (setq-local + inf-clojure-socket-callback + (lambda () + (let ((with-process-repl-buffer-name (concat "*" repl-buffer-name "*"))) + (setq inf-clojure-socket-repl-type + repl-type + inf-clojure-custom-repl-name + repl-buffer-name + repl-buffer + (get-buffer-create with-process-repl-buffer-name)) + (inf-clojure-connect host port) + (with-current-buffer with-process-repl-buffer-name + (setq inf-clojure-socket-buffer socket-buffer)) + (set-process-sentinel + (get-buffer-process (get-buffer with-process-repl-buffer-name)) + #'inf-clojure-socket-repl-sentinel))))) + (set-process-filter sock #'inf-clojure-socket-filter) + (message "Starting %s socket REPL server at %s:%d with %s" repl-type host port socket-cmd))) + + (defun inf-clojure--forms-without-newlines (str) "Remove newlines between toplevel forms. STR is a string of contents to be evaluated. When sending From b153e5126419910c38691088aab569b7c281068c Mon Sep 17 00:00:00 2001 From: dpsutton Date: Sat, 8 Apr 2023 04:52:51 -0500 Subject: [PATCH 164/189] Cleanup socket repl startup (#212) This simplifies the socket repl startup code and addresses some lint warnings. --- inf-clojure.el | 78 +++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 6f8d216..4c5e018 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -518,6 +518,9 @@ Should be a symbol that is a key in `inf-clojure-repl-features'." (const :tag "babashka" babashka) (const :tag "determine at startup" nil))) +(defvar inf-clojure-custom-repl-name nil + "A string to be used as the repl buffer name.") + (defun inf-clojure--whole-comment-line-p (string) "Return non-nil iff STRING is a whole line semicolon comment." (string-match-p "^\s*;" string)) @@ -606,7 +609,9 @@ This should usually be a combination of `inf-clojure-prompt' and :package-version '(inf-clojure . "2.0.0")) (defcustom inf-clojure-auto-mode t - "When non-nil, automatically enable inf-clojure-minor-mode for all Clojure buffers." + "Automatically enable inf-clojure-minor-mode. +All buffers in `clojure-mode' will automatically be in +`inf-clojure-minor-mode' unless set to nil." :type 'boolean :safe #'booleanp :package-version '(inf-clojure . "3.1.0")) @@ -795,7 +800,7 @@ The name is simply the final segment of the path." (file-name-nondirectory (directory-file-name dir))) ;;;###autoload -(defun inf-clojure (cmd) +(defun inf-clojure (cmd &optional suppress-message) "Run an inferior Clojure process, input and output via buffer `*inf-clojure*'. If there is a process already running in `*inf-clojure*', just switch to that buffer. @@ -809,6 +814,9 @@ and `inf-clojure-custom-startup' if those are set. Use a prefix to prevent using these when they are set. +Prints a message that it has connected to the host and port +unless SUPPRESS-MESSAGE is truthy. + Runs the hooks from `inf-clojure-mode-hook' (after the `comint-mode-hook' is run). \(Type \\[describe-mode] in the process buffer for a list of commands.)" @@ -833,12 +841,12 @@ process buffer for a list of commands.)" (cmdlist (if (consp cmd) (list cmd) (split-string-and-unquote cmd))) - (repl-type (or inf-clojure-socket-repl-type - (unless prefix-arg + (repl-type (or (unless prefix-arg inf-clojure-custom-repl-type) - (car (rassoc cmd inf-clojure-startup-forms)) - (inf-clojure--prompt-repl-type)))) - (message "Starting Clojure REPL via `%s'..." cmd) + (car (rassoc cmd inf-clojure-startup-forms)) + (inf-clojure--prompt-repl-type)))) + (unless suppress-message + (message "Starting Clojure REPL via `%s'..." cmd)) (with-current-buffer (apply #'make-comint process-buffer-name (car cmdlist) nil (cdr cmdlist)) (inf-clojure-mode) @@ -849,14 +857,17 @@ process buffer for a list of commands.)" (setq inf-clojure-buffer (get-buffer repl-buffer-name)) (if inf-clojure-repl-use-same-window (pop-to-buffer-same-window repl-buffer-name) - (pop-to-buffer repl-buffer-name)))) + (pop-to-buffer repl-buffer-name)) + repl-buffer-name)) -;;;###autoload -(defun inf-clojure-connect (host port) +;;;###autol +(defun inf-clojure-connect (host port &optional suppress-message) "Connect to a running socket REPL server via `inf-clojure'. -HOST is the host the process is running on, PORT is where it's listening." +HOST is the host the process is running on, PORT is where it's +listening. SUPPRESS-MESSAGE is optional and if truthy will +prevent showing the startup message." (interactive "shost: \nnport: ") - (inf-clojure (cons host port))) + (inf-clojure (cons host port) suppress-message)) (defvar-local inf-clojure-socket-callback nil "Used to transfer state between the socket process buffer & REPL buffer.") @@ -882,12 +893,11 @@ OUTPUT is the latest data received from the process" (insert output))) (let ((prompt-displayed (string-match inf-clojure-prompt output))) (when prompt-displayed - (message (format "Socket REPL startup detected for %s" (process-name process))) (with-current-buffer server-buffer (when inf-clojure-socket-callback (funcall inf-clojure-socket-callback))))))) -(defun inf-clojure-socket-repl-sentinel (process event) +(defun inf-clojure-socket-repl-sentinel (process _event) "Ensures socket REPL are cleaned up when the REPL buffer is closed. PROCESS is the process object that is connected to a socket REPL. @@ -917,11 +927,11 @@ If left as nil a random port will be selected between 5500-6000." ;;;###autoload (defun inf-clojure-socket-repl (cmd) - "Start a socket REPL server and connect to it via `inf-clojure'. -CMD is the command line used to start the socket REPL, if this -isn't provided you will be prompted to select from the defaults -provided in `inf-clojure-socket-repl-startup-forms' or -`inf-clojure-custom-startup' if this is defined." + "Start a socket REPL server and connects to it via `inf-clojure-connect'. +CMD is the command line instruction used to start the socket +REPL. It should be a string with \"%d\" in it to take a random +port. Set `inf-clojure-custom-startup' or choose from the +defaults provided in `inf-clojure-socket-repl-startup-forms'." (interactive (list (or (unless current-prefix-arg inf-clojure-custom-startup) (completing-read "Select Clojure socket REPL startup command: " @@ -937,13 +947,9 @@ provided in `inf-clojure-socket-repl-startup-forms' or (inf-clojure--prompt-repl-type))) (project-name (inf-clojure--project-name (or project-dir "standalone"))) (socket-process-name (format "*%s-%s-socket-server*" project-name repl-type)) - (socket-buffer-name (format "*%s-%s-socket*" project-name repl-type)) - (socket-buffer (get-buffer-create socket-buffer-name)) - (repl-buffer-name (format "%s-%s-repl" project-name repl-type)) - (socket-form (or cmd - (cdr (assoc repl-type inf-clojure-socket-repl-startup-forms)) - inf-clojure-custom-startup)) - (socket-cmd (format socket-form port)) + (socket-buffer (get-buffer-create + (format "*%s-%s-socket*" project-name repl-type))) + (socket-cmd (format cmd port)) (sock (let ((default-directory (or project-dir default-directory))) (start-file-process-shell-command socket-process-name socket-buffer @@ -952,19 +958,13 @@ provided in `inf-clojure-socket-repl-startup-forms' or (setq-local inf-clojure-socket-callback (lambda () - (let ((with-process-repl-buffer-name (concat "*" repl-buffer-name "*"))) - (setq inf-clojure-socket-repl-type - repl-type - inf-clojure-custom-repl-name - repl-buffer-name - repl-buffer - (get-buffer-create with-process-repl-buffer-name)) - (inf-clojure-connect host port) - (with-current-buffer with-process-repl-buffer-name - (setq inf-clojure-socket-buffer socket-buffer)) - (set-process-sentinel - (get-buffer-process (get-buffer with-process-repl-buffer-name)) - #'inf-clojure-socket-repl-sentinel))))) + (let* ((inf-clojure-custom-repl-type repl-type) + (created-repl-buffer (inf-clojure-connect host port :suppress-message))) + (with-current-buffer (get-buffer created-repl-buffer) + (setq-local inf-clojure-socket-buffer socket-buffer) + (set-process-sentinel + (get-buffer-process (current-buffer)) + #'inf-clojure-socket-repl-sentinel)))))) (set-process-filter sock #'inf-clojure-socket-filter) (message "Starting %s socket REPL server at %s:%d with %s" repl-type host port socket-cmd))) From 9aea5012bf9047781a21a3b62cea134b126f7709 Mon Sep 17 00:00:00 2001 From: p4v4n Date: Sat, 9 Sep 2023 04:56:00 +0530 Subject: [PATCH 165/189] Replace `beginning-of-defun` fn --- CHANGELOG.md | 1 + inf-clojure.el | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 836cd49..c7e8a9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## master (unreleased) +* Improve support for multiple forms in the same line by replacing beginning-of-defun fn. * [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. * [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands * [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting repl. diff --git a/inf-clojure.el b/inf-clojure.el index 4c5e018..9efe1de 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1018,7 +1018,7 @@ current defun else return the string.." (let ((end (point)) (case-fold-search t) (func (if bounds #'cons #'buffer-substring-no-properties))) - (beginning-of-defun) + (beginning-of-defun-raw) (funcall func (point) end)))) (defun inf-clojure-eval-defun (&optional and-go) From ece16ffeefc5ab23a31012d10765c34197510220 Mon Sep 17 00:00:00 2001 From: Roman Rudakov Date: Sat, 24 May 2025 18:32:24 +0200 Subject: [PATCH 166/189] Add clojure-ts-mode support --- CHANGELOG.md | 5 +- README.md | 16 ++++++ inf-clojure.el | 148 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 115 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7e8a9b..e824df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,13 @@ # Changelog ## master (unreleased) + * Improve support for multiple forms in the same line by replacing beginning-of-defun fn. * [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. * [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands * [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting repl. -* [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. - +* [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. +- [#217](https://github.com/clojure-emacs/inf-clojure/pull/217): Add `clojure-ts-mode` support. ## 3.2.1 (2022-07-22) diff --git a/README.md b/README.md index 7a022aa..fb81008 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,10 @@ You can also add the following to your Emacs config to enable ```emacs-lisp (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) + +;; or if you're a `clojure-ts-mode' user: + +(add-hook 'clojure-ts-mode-hook #'inf-clojure-minor-mode) ``` **Warning:** Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same time. They @@ -217,6 +221,18 @@ If you want to update a specific form there is a function (inf-clojure-update-feature 'clojure 'completion "(incomplete.core/completions \"%s\")") ``` +### `clojure-ts-mode` support + +`inf-clojure` will try to use `clojure-ts-mode` by default if it's +available with fallback to `clojure-mode`. + +If you want to use `inf-clojure` with `clojure-mode` exclusively, you +can set it to: + +```emacs-lisp +(setopt inf-clojure-source-modes '(clojure-mode)) +``` + #### Caveats As `inf-clojure` is built on top of `comint` it has all the usual comint limitations - diff --git a/inf-clojure.el b/inf-clojure.el index 9efe1de..5634f9a 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -65,11 +65,13 @@ (require 'comint) (require 'clojure-mode) +(require 'clojure-ts-mode nil :no-error) (require 'eldoc) (require 'thingatpt) (require 'ansi-color) (require 'cl-lib) (require 'subr-x) +(require 'project) (defvar inf-clojure-startup-forms '((lein . "lein repl") (boot . "boot repl") @@ -193,10 +195,10 @@ either `setq-local` or an entry in `.dir-locals.el`." ) MULTIPLE PROCESS SUPPORT =========================================================================== To run multiple Clojure processes, you start the first up -with \\[inf-clojure]. It will be in a buffer named `*inf-clojure*'. +with \\[inf-clojure]. It will be in a buffer named *inf-clojure*. Rename this buffer with \\[rename-buffer]. You may now start up a new process with another \\[inf-clojure]. It will be in a new buffer, -named `*inf-clojure*'. You can switch between the different process +named *inf-clojure*. You can switch between the different process buffers with \\[switch-to-buffer]. Commands that send text from source buffers to Clojure processes -- @@ -205,7 +207,7 @@ process to send to, when you have more than one Clojure process around. This is determined by the global variable `inf-clojure-buffer'. Suppose you have three inferior Clojures running: Buffer Process - foo inf-clojure + foo `inf-clojure' bar inf-clojure<2> *inf-clojure* inf-clojure<3> If you do a \\[inf-clojure-eval-defun] command on some Clojure source code, @@ -269,7 +271,7 @@ has been found. See also variable `inf-clojure-buffer'." (error "No Clojure subprocess; see variable `inf-clojure-buffer'")))) (defun inf-clojure-repl-p (&optional buf) - "Indicates if BUF is an inf-clojure REPL. + "Indicates if BUF is an `inf-clojure' REPL. If BUF is nil then defaults to the current buffer. Checks the mode and that there is a live process." (let ((buf (or buf (current-buffer)))) @@ -278,7 +280,7 @@ Checks the mode and that there is a live process." (process-live-p (get-buffer-process buf))))) (defun inf-clojure-repls () - "Return a list of all inf-clojure REPL buffers." + "Return a list of all `inf-clojure' REPL buffers." (let (repl-buffers) (dolist (b (buffer-list)) (when (inf-clojure-repl-p b) @@ -286,27 +288,27 @@ Checks the mode and that there is a live process." repl-buffers)) (defun inf-clojure--prompt-repl-buffer (prompt) - "Prompt the user to select an inf-clojure repl buffer. + "Prompt the user to select an `inf-clojure' repl buffer. PROMPT is a string to prompt the user. Returns nil when no buffer is selected." (let ((repl-buffers (inf-clojure-repls))) (if (> (length repl-buffers) 0) - (when-let ((repl-buffer (completing-read prompt repl-buffers nil t))) + (when-let* ((repl-buffer (completing-read prompt repl-buffers nil t))) (get-buffer repl-buffer)) (user-error "No buffers have an inf-clojure process")))) (defun inf-clojure-set-repl (always-ask) - "Set an inf-clojure buffer as the active (default) REPL. + "Set an `inf-clojure' buffer as the active (default) REPL. If in a REPL buffer already, use that unless a prefix is used (or -ALWAYS-ASK). Otherwise get a list of all active inf-clojure +ALWAYS-ASK). Otherwise get a list of all active `inf-clojure' REPLS and offer a choice. It's recommended to rename REPL buffers after they are created with `rename-buffer'." (interactive "P") - (when-let ((new-repl-buffer - (if (or always-ask - (not (inf-clojure-repl-p))) - (inf-clojure--prompt-repl-buffer "Select default REPL: ") - (current-buffer)))) + (when-let* ((new-repl-buffer + (if (or always-ask + (not (inf-clojure-repl-p))) + (inf-clojure--prompt-repl-buffer "Select default REPL: ") + (current-buffer)))) (setq inf-clojure-buffer new-repl-buffer) (message "Current inf-clojure REPL set to %s" new-repl-buffer))) @@ -349,6 +351,14 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword \(as in :a, :c, etc.)" :type 'regexp) +(defcustom inf-clojure-source-modes '(clojure-ts-mode clojure-mode) + "Used to determine if a buffer contains Clojure source code. + +Any buffer with one of these major modes, it's considered a Clojure +source file by all `inf-clojure' commands." + :type '(repeat symbol) + :safe #'symbolp) + (defun inf-clojure--modeline-info () "Return modeline info for `inf-clojure-minor-mode'. Either \"no process\" or \"buffer-name(repl-type)\"" @@ -453,7 +463,7 @@ The value of this variable is a mode line template as in `mode-line-format'. See Info Node `(elisp)Mode Line Format' for details about mode line templates. -Customize this variable to change how inf-clojure-minor-mode +Customize this variable to change how `inf-clojure-minor-mode' displays its status in the mode line. The default value displays the current REPL. Set this variable to nil to disable the mode line entirely." @@ -609,24 +619,35 @@ This should usually be a combination of `inf-clojure-prompt' and :package-version '(inf-clojure . "2.0.0")) (defcustom inf-clojure-auto-mode t - "Automatically enable inf-clojure-minor-mode. + "Automatically enable `inf-clojure-minor-mode'. All buffers in `clojure-mode' will automatically be in `inf-clojure-minor-mode' unless set to nil." :type 'boolean :safe #'booleanp :package-version '(inf-clojure . "3.1.0")) +(defun inf-clojure--get-preferred-major-modes () + "Return list of preferred major modes that are actually available." + (cl-remove-if-not (lambda (mode) (featurep mode)) + inf-clojure-source-modes)) + +(defun inf-clojure--clojure-buffer-p () + "Return TRUE if the current buffer is a Clojure buffer." + (derived-mode-p (inf-clojure--get-preferred-major-modes))) + (defun inf-clojure--clojure-buffers () "Return a list of all existing `clojure-mode' buffers." - (cl-remove-if-not - (lambda (buffer) (with-current-buffer buffer (derived-mode-p 'clojure-mode))) - (buffer-list))) + (cl-remove-if-not (lambda (buffer) + (with-current-buffer buffer + (inf-clojure--clojure-buffer-p))) + (buffer-list))) (defun inf-clojure-enable-on-existing-clojure-buffers () "Enable inf-clojure's minor mode on existing Clojure buffers. See command `inf-clojure-minor-mode'." (interactive) - (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) + (dolist (mode (inf-clojure--get-preferred-major-modes)) + (add-hook (derived-mode-hook-name mode) #'inf-clojure-minor-mode)) (dolist (buffer (inf-clojure--clojure-buffers)) (with-current-buffer buffer (inf-clojure-minor-mode +1)))) @@ -688,6 +709,8 @@ If `comint-use-prompt-regexp' is nil (the default), \\[comint-insert-input] on (setq comint-input-sender 'inf-clojure--send-string) (setq comint-prompt-regexp inf-clojure-comint-prompt-regexp) (setq mode-line-process '(":%s")) + ;; NOTE: Using Tree-sitter based syntax highlighting in comint + ;; buffer is currently not possible. (clojure-mode-variables) (clojure-font-lock-setup) (when inf-clojure-enable-eldoc @@ -799,10 +822,24 @@ to suppress the usage of the target buffer discovery logic." The name is simply the final segment of the path." (file-name-nondirectory (directory-file-name dir))) +(defun inf-clojure--project-dir () + "Return current Clojure project root." + (let ((project-vc-extra-root-markers '("project.clj" ; Leiningen + "build.boot" ; Boot + "build.gradle" ; Gradle + "build.gradle.kts" ; Gradle + "deps.edn" ; Clojure CLI (a.k.a. tools.deps) + "shadow-cljs.edn" ; shadow-cljs + "bb.edn" ; babashka + "nbb.edn" ; nbb + "basilisp.edn" ; Basilisp (Python) + ))) + (project-root (project-current)))) + ;;;###autoload (defun inf-clojure (cmd &optional suppress-message) - "Run an inferior Clojure process, input and output via buffer `*inf-clojure*'. -If there is a process already running in `*inf-clojure*', just + "Run an inferior Clojure process, input and output via buffer *inf-clojure*. +If there is a process already running in *inf-clojure*, just switch to that buffer. CMD is a string which serves as the startup command or a cons of @@ -826,7 +863,7 @@ process buffer for a list of commands.)" (mapcar #'cdr inf-clojure-startup-forms) nil 'confirm-after-completion)))) - (let* ((project-dir (clojure-project-dir)) + (let* ((project-dir (inf-clojure--project-dir)) (process-buffer-name (or inf-clojure-custom-repl-name (if project-dir @@ -850,7 +887,9 @@ process buffer for a list of commands.)" (with-current-buffer (apply #'make-comint process-buffer-name (car cmdlist) nil (cdr cmdlist)) (inf-clojure-mode) - (set-syntax-table clojure-mode-syntax-table) + (set-syntax-table (pcase (car (inf-clojure--get-preferred-major-modes)) + ('clojure-ts-mode clojure-ts-mode-syntax-table) + (_ clojure-mode-syntax-table))) (setq-local inf-clojure-repl-type repl-type) (hack-dir-local-variables-non-file-buffer)))) ;; update the default comint buffer and switch to it @@ -940,7 +979,7 @@ defaults provided in `inf-clojure-socket-repl-startup-forms'." 'confirm-after-completion)))) (let* ((host "localhost") (port (or inf-clojure-socket-repl-port (+ 5500 (random 500)))) - (project-dir (clojure-project-dir)) + (project-dir (inf-clojure--project-dir)) (repl-type (or (unless prefix-arg inf-clojure-custom-repl-type) (car (rassoc cmd inf-clojure-socket-repl-startup-forms)) @@ -978,7 +1017,8 @@ of forms." (condition-case nil (with-temp-buffer (progn - (clojurec-mode) + ;; Activate preferred major mode. + (funcall (car (inf-clojure--get-preferred-major-modes))) (insert str) (whitespace-cleanup) (goto-char (point-min)) @@ -986,8 +1026,10 @@ of forms." (while (looking-at "\n") (delete-char 1)) (unless (eobp) - (clojure-forward-logical-sexp)) - (unless (eobp) + ;; NOTE: There is no special API for that in + ;; `clojure-ts-mode', so probably for now lets keep this + ;; `clojure-mode' function. + (clojure-forward-logical-sexp) (forward-char))) (buffer-substring-no-properties (point-min) (point-max)))) (scan-error str))) @@ -1105,13 +1147,6 @@ START and END are the beginning and end positions in the buffer to send." This holds a cons cell of the form `(DIRECTORY . FILE)' describing the last `inf-clojure-load-file' command.") -(defcustom inf-clojure-source-modes '(clojure-mode) - "Used to determine if a buffer contains Clojure source code. -If it's loaded into a buffer that is in one of these major modes, it's -considered a Clojure source file by `inf-clojure-load-file'. -Used by this command to determine defaults." - :type '(repeat symbol)) - (defun inf-clojure-load-file (&optional switch-to-repl file-name) "Load a Clojure file into the inferior Clojure process. @@ -1123,7 +1158,7 @@ is present it will be used instead of the current file." (file-name (or file-name (car (comint-get-source "Load Clojure file: " inf-clojure-prev-l/c-dir/file ;; nil because doesn't need an exact name - inf-clojure-source-modes nil)))) + (inf-clojure--get-preferred-major-modes) nil)))) (load-form (inf-clojure-get-feature proc 'load))) (comint-check-source file-name) ; Check to see if buffer needs saved. (setq inf-clojure-prev-l/c-dir/file (cons (file-name-directory file-name) @@ -1132,23 +1167,32 @@ is present it will be used instead of the current file." (when switch-to-repl (inf-clojure-switch-to-repl t)))) +(defun inf-clojure--find-ns () + "Return the namespace of the current Clojure buffer. + +This function delegates its job to an appropritate function, considering +`inf-clojure-source-modes'." + (pcase (car (inf-clojure--get-preferred-major-modes)) + ('clojure-ts-mode (clojure-ts-find-ns)) + (_ (clojure-find-ns)))) + (defun inf-clojure-reload (arg) "Send a query to the inferior Clojure for reloading the namespace. -See variable `inf-clojure-reload-form' and +See variable `inf-clojure-reload-form' and variable `inf-clojure-reload-all-form'. The prefix argument ARG can change the behavior of the command: - - C-u M-x `inf-clojure-reload': prompts for a namespace name. - - M-- M-x `inf-clojure-reload': executes (require ... :reload-all). - - M-- C-u M-x `inf-clojure-reload': reloads all AND prompts." + - \\`C-u' \\[inf-clojure-reload]: prompts for a namespace name. + - \\`M--' \\[inf-clojure-reload]: executes (require ... :reload-all). + - \\`M--' \\`C-u' \\[inf-clojure-reload]: reloads all AND prompts." (interactive "P") (let* ((proc (inf-clojure-proc)) (reload-all-p (or (equal arg '-) (equal arg '(-4)))) (prompt-p (or (equal arg '(4)) (equal arg '(-4)))) (ns (if prompt-p - (car (inf-clojure-symprompt "Namespace" (clojure-find-ns))) - (clojure-find-ns))) + (car (inf-clojure-symprompt "Namespace" (inf-clojure--find-ns))) + (inf-clojure--find-ns))) (form (if (not reload-all-p) (inf-clojure-reload-form proc) (inf-clojure-reload-all-form proc)))) @@ -1249,7 +1293,7 @@ STRING if present." (prin1-to-string (substring-no-properties string)))) nil (expand-file-name inf-clojure--log-file-name - (clojure-project-dir)) + (inf-clojure--project-dir)) 'append 'no-annoying-write-file-in-minibuffer))) @@ -1357,11 +1401,11 @@ for evaluation, therefore FORM should not include it." (defun inf-clojure-arglists (fn) "Send a query to the inferior Clojure for the arglists for function FN. See variable `inf-clojure-arglists-form'." - (when-let ((proc (inf-clojure-proc 'no-error))) - (when-let ((arglists-form (inf-clojure-get-feature proc 'arglists))) - (thread-first (format arglists-form fn) - (inf-clojure--process-response proc "(" ")") - (inf-clojure--some))))) + (when-let* ((proc (inf-clojure-proc 'no-error)) + (arglists-form (inf-clojure-get-feature proc 'arglists))) + (thread-first (format arglists-form fn) + (inf-clojure--process-response proc "(" ")") + (inf-clojure--some)))) (defun inf-clojure-show-arglists (prompt-for-symbol) "Show the arglists for function FN in the mini-buffer. @@ -1383,8 +1427,8 @@ prefix argument PROMPT-FOR-NS, it prompts for a namespace name." (interactive "P") (let* ((proc (inf-clojure-proc)) (ns (if prompt-for-ns - (car (inf-clojure-symprompt "Ns vars" (clojure-find-ns))) - (clojure-find-ns))) + (car (inf-clojure-symprompt "Ns vars" (inf-clojure--find-ns))) + (inf-clojure--find-ns))) (ns-vars-form (inf-clojure-get-feature proc 'ns-vars))) (inf-clojure--send-string proc (format ns-vars-form ns)))) @@ -1396,8 +1440,8 @@ PROMPT-FOR-NS, it prompts for a namespace name." (interactive "P") (let* ((proc (inf-clojure-proc)) (ns (if prompt-for-ns - (car (inf-clojure-symprompt "Set ns to" (clojure-find-ns))) - (clojure-find-ns))) + (car (inf-clojure-symprompt "Set ns to" (inf-clojure--find-ns))) + (inf-clojure--find-ns))) (set-ns-form (inf-clojure-get-feature proc 'set-ns))) (when (or (not ns) (equal ns "")) (user-error "No namespace selected")) From aff7407a7571c184a9f9c553498f0ce420ee35a5 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 11:44:10 +0300 Subject: [PATCH 167/189] Bump the copyright years --- README.md | 2 +- inf-clojure.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb81008..8b0a969 100644 --- a/README.md +++ b/README.md @@ -495,7 +495,7 @@ This creates `.inf-clojure.log` in the project directory so that you can `tail - ## License -Copyright © 2014-2022 Bozhidar Batsov and [contributors][]. +Copyright © 2014-2025 Bozhidar Batsov and [contributors][]. Distributed under the GNU General Public License; type C-h C-c to view it. diff --git a/inf-clojure.el b/inf-clojure.el index 5634f9a..f0c7ea5 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1,6 +1,6 @@ ;;; inf-clojure.el --- Run an external Clojure process in an Emacs buffer -*- lexical-binding: t; -*- -;; Copyright © 2014-2022 Bozhidar Batsov +;; Copyright © 2014-2025 Bozhidar Batsov ;; Authors: Bozhidar Batsov ;; Olin Shivers From 9c06132cd31249d1078d8954e59cbfb9e1b562df Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 11:45:30 +0300 Subject: [PATCH 168/189] Bump the dev version --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index f0c7ea5..ebb3511 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -7,7 +7,7 @@ ;; Maintainer: Bozhidar Batsov ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure -;; Version: 3.2.1 +;; Version: 3.3.0-snapshot ;; Package-Requires: ((emacs "26.2") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From 6833bb81fafeabb48a4f3ee5b89a5ae0bfb45889 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 11:48:19 +0300 Subject: [PATCH 169/189] Require Emacs 27 --- .circleci/config.yml | 9 --------- CHANGELOG.md | 3 ++- inf-clojure.el | 6 ++---- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d2a8cef..30583b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,14 +51,6 @@ commands: command: eldev -dtT compile --warnings-as-errors jobs: - test-ubuntu-emacs-26: - docker: - - image: silex/emacs:26-ci - entrypoint: bash - steps: - - setup - - test - test-ubuntu-emacs-27: docker: - image: silex/emacs:27-ci @@ -111,7 +103,6 @@ workflows: version: 2 ci-test-matrix: jobs: - - test-ubuntu-emacs-26 - test-ubuntu-emacs-27 - test-ubuntu-emacs-28 - test-ubuntu-emacs-master diff --git a/CHANGELOG.md b/CHANGELOG.md index e824df5..8149bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ * [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands * [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting repl. * [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. -- [#217](https://github.com/clojure-emacs/inf-clojure/pull/217): Add `clojure-ts-mode` support. +* [#217](https://github.com/clojure-emacs/inf-clojure/pull/217): Add `clojure-ts-mode` support. +* Require Emacs 27. ## 3.2.1 (2022-07-22) diff --git a/inf-clojure.el b/inf-clojure.el index ebb3511..d70848c 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -8,7 +8,7 @@ ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure ;; Version: 3.3.0-snapshot -;; Package-Requires: ((emacs "26.2") (clojure-mode "5.11")) +;; Package-Requires: ((emacs "27") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. @@ -332,9 +332,7 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte :link '(emacs-commentary-link :tag "Commentary" "inf-clojure")) (defconst inf-clojure-version - (or (if (fboundp 'package-get-version) - (package-get-version)) - "3.2.1") + (package-get-version) "The current version of `inf-clojure'.") (defcustom inf-clojure-prompt-read-only t From 6bf42957aa53cb68a355f48bab4166b085ae5cea Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 11:53:17 +0300 Subject: [PATCH 170/189] Tweak the README markup a bit --- README.md | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8b0a969..91801df 100644 --- a/README.md +++ b/README.md @@ -40,18 +40,18 @@ It supports the following REPLs: `inf-clojure` provides a set of essential features for interactive Clojure/ClojureScript/ClojureCLR development: -* Enhanced REPL -* Interactive code evaluation -* Code completion -* Definition lookup -* Documentation lookup -* ElDoc -* Apropos -* Macroexpansion -* Reloading a namespace (via `require :reload`/`require :reload-all`) -* Connecting to socket REPLs - -For a more powerful/full-featured solution see [CIDER](https://github.com/clojure-emacs/cider). +- Enhanced REPL +- Interactive code evaluation +- Code completion +- Definition lookup +- Documentation lookup +- ElDoc +- Apropos +- Macroexpansion +- Reloading a namespace (via `require :reload`/`require :reload-all`) +- Connecting to socket REPLs + +For a more powerful/full-featured solution see [CIDER][]. ## Rationale @@ -156,7 +156,7 @@ configurable. You can 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) -or by setting them in in your init file. +or by setting them in in your [init file][Emacs init file]. You can see all the configuration options available using the command `M-x customize-group RET inf-clojure`. @@ -245,7 +245,7 @@ If you decide _not_ to use the socket REPL, it is highly recommended you disable output coloring and/or `readline` facilities: `inf-clojure` does not filter out ASCII escape characters at the moment and will not behave correctly. -For Leiningen, there are no command-line switches and you need to add +For [Leiningen][], there are no command-line switches and you need to add a custom [`project.clj` option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj): @@ -261,8 +261,8 @@ If you have the new [Clojure CLI tools][] installed you can use the `clojure` co _do not use `clj` because it adds readline support_ -``` shellsession -$ clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" +``` shell +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`: @@ -270,6 +270,7 @@ Then either `C-c M-c RET localhost RET 5555` from within Emacs or add the follow ```emacs-lisp ((nil . ((inf-clojure-custom-startup . ("localhost" . 5555))))) ``` + #### Leiningen Socket REPL For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `project.clj`: @@ -386,7 +387,6 @@ your cursor. One side effect of this is that it can mess with repl vars like `*1` and `*2`. You can disable inf-clojure's Eldoc functionality with `(setq inf-clojure-enable-eldoc nil)`. - ElDoc should be enabled by default in Emacs 26.1+. If it is not active by default, you can activate ElDoc with `M-x eldoc-mode` or by adding the following to you Emacs config: @@ -416,7 +416,6 @@ could alternatively use `compliment {:mvn/version "0.3.10"}`. ;; or ;; for compliment (inf-clojure-update-feature 'clojure 'completion "(compliment.core/completions \"%s\")") - ``` If you give a form for the completion form, it is your responsibility @@ -479,7 +478,7 @@ The explanation of this problem and solution can be found [here](https://groups. The solution is to create a file named `.jline.rc` in your `$HOME` directory and add this line to that file: -``` +```ini jline.terminal=unsupported ``` @@ -514,4 +513,3 @@ Distributed under the GNU General Public License; type C-h C-c to vie [melpa stable]: http://stable.melpa.org [Emacs init file]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html [Clojure cli tools]: https://clojure.org/guides/getting_started -[Boot]: http://boot-clj.com From 616c40f9e4c7d18e96ebbe303edca14e0e90a090 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 11:59:38 +0300 Subject: [PATCH 171/189] Drop support for Lumo It has been abandoned a few years ago. --- CHANGELOG.md | 12 +++++++++--- README.md | 29 +++++------------------------ inf-clojure.el | 24 ++---------------------- 3 files changed, 16 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8149bd2..52823a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,19 @@ ## master (unreleased) -* Improve support for multiple forms in the same line by replacing beginning-of-defun fn. +### New features + * [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. -* [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands -* [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting repl. * [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. * [#217](https://github.com/clojure-emacs/inf-clojure/pull/217): Add `clojure-ts-mode` support. + +### Changes + +* Improve support for multiple forms in the same line by replacing `beginning-of-defun` fn. +* [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands +* [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting REPL. * Require Emacs 27. +* Drop support for Lumo. ## 3.2.1 (2022-07-22) diff --git a/README.md b/README.md index 91801df..92fd6bd 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ It supports the following REPLs: - ClojureScript - ClojureCLR (via [lein-clr](https://github.com/kumarshantanu/lein-clr)) - [Planck](http://planck-repl.org/) -- [Lumo](https://github.com/anmonteiro/lumo) - [Joker](https://joker-lang.org/) - [babashka](https://github.com/borkdude/babashka) @@ -181,7 +180,7 @@ There are two important configuration variables here: 1. `inf-clojure-custom-startup`: Which startup command to use so inf-clojure can run the inferior Clojure process (REPL). -2. `inf-clojure-custom-repl-type`: The type of the REPL started by the above command (e.g. `lumo`). +2. `inf-clojure-custom-repl-type`: The type of the REPL started by the above command (e.g. `planck`). If these are set and you wish to prevent inf-clojure from using them, use a prefix arg when invoking `inf-clojure` (`C-u M-x inf-clojure`). @@ -290,18 +289,6 @@ information on how connect: The socket server REPL configuration options are described [here](https://clojure.org/reference/repl_and_main#_launching_a_socket_server). -#### Lumo Socket REPL - -Lumo is decoupled from `inf-clojure-project-type` and therefore the command used depends on what you are using for dependency resolution. - -For example if a `project.clj` is present in the project root folder, `inf-clojure-lein-cmd` will be used. - -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`: - -```emacs-lisp -((nil (inf-clojure-custom-startup "localhost" . 5555))) -``` - #### Multiple Process Support To run multiple Clojure processes, you start the first up @@ -365,7 +352,7 @@ obtained from `inf-clojure-repl-features`: ```emacs-lisp (mapcar 'car inf-clojure-repl-features) -;; => (cljs lumo planck joker clojure babashka) +;; => (cljs planck joker clojure babashka) ``` What does it mean that a REPL type is supported? Well, it means that @@ -402,7 +389,7 @@ You can leave it enabled, it just won't show anything in the echo area. #### Code Completion Code completion is a tricky aspect if you are trying to be as close to -a generic REPL as possible. Planck and lumo REPL implementations +a generic REPL as possible. Some runtimes (e.g. Planck) explicitly provide completion functions in their REPL namespaces. For clojure, you will need to have a library on your classpath. If you are using a recent version of Leiningen, you already have @@ -434,7 +421,7 @@ once so that the completion machinery will work: `(require For more advanced customization, code completion is particularly open to customization. Not only you can `setq` the customary -`inf-clojure-completion-form`, `inf-clojure-completion-form-lumo`, +`inf-clojure-completion-form`, `inf-clojure-completion-form-planck` and `inf-clojure-completion-form-joker` - the form to send to the REPL - but you can also use `inf-clojure-completions-fn` for specifying a @@ -446,12 +433,6 @@ 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 -when launched from the command line. This disable `readline` support -in order to play nicely with Emacs. - ## Troubleshooting ### Things seem broken @@ -459,7 +440,7 @@ in order to play nicely with Emacs. 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 +correct calls. Most end up in `(planck.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 diff --git a/inf-clojure.el b/inf-clojure.el index d70848c..3e81d9f 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -47,7 +47,6 @@ ;; * Apropos ;; * Macroexpansion ;; * Support connecting to socket REPLs -;; * Support for Lumo ;; * Support for Planck ;; * Support for Joker ;; @@ -80,7 +79,6 @@ (lein-clr . "lein clr repl") (planck . "planck -d") (babashka . "bb") - (lumo . "lumo -d") (joker . "joker"))) (defvar inf-clojure-repl-features @@ -92,23 +90,6 @@ (set-ns . "(in-ns '%s)") (macroexpand . "(cljs.core/macroexpand '%s)") (macroexpand-1 . "(cljs.core/macroexpand-1 '%s)"))) - (lumo . ((load . "(clojure.core/load-file \"%s\")") - (doc . "(lumo.repl/doc %s)") - (source . "(lumo.repl/source %s)") - (arglists . - "(let [old-value lumo.repl/*pprint-results*] - (set! lumo.repl/*pprint-results* false) - (js/setTimeout #(set! lumo.repl/*pprint-results* old-value) 0) - (lumo.repl/get-arglists \"%s\"))") - (apropos . "(lumo.repl/apropos \"%s\")") - (ns-vars . "(lumo.repl/dir %s)") - (set-ns . "(in-ns '%s)") - (macroexpand . "(macroexpand-1 '%s)") - (macroexpand-1 . "(macroexpand-1 '%s)") - (completion . - "(let [ret (atom nil)] - (lumo.repl/get-completions \"%s\" (fn [res] (reset! ret (map str res)))) - @ret)"))) (planck . ((load . "(load-file \"%s\")") (doc . "(planck.repl/doc %s)") (source . "(planck.repl/source %s)") @@ -242,7 +223,7 @@ If no-error is truthy don't error if feature is not present." (defun inf-clojure--update-feature (repl-type feature form) "Return a copy of the datastructure containing the repl features. -Given a REPL-TYPE (`clojure', `lumo', ...) and a FEATURE (`doc', +Given a REPL-TYPE (`clojure', `planck', ...) and a FEATURE (`doc', `apropos', ...) and a FORM this will return a new datastructure that can be set as `inf-clojure-repl-features'." (let ((original (alist-get repl-type inf-clojure-repl-features))) @@ -255,7 +236,7 @@ that can be set as `inf-clojure-repl-features'." (defun inf-clojure-update-feature (repl-type feature form) "Mutate the repl features to the new FORM. -Given a REPL-TYPE (`clojure', `lumo', ...) and a FEATURE (`doc', +Given a REPL-TYPE (`clojure', `planck', ...) and a FEATURE (`doc', `apropos', ...) and a FORM this will set `inf-clojure-repl-features' with these new values." (setq inf-clojure-repl-features (inf-clojure--update-feature repl-type feature form))) @@ -520,7 +501,6 @@ Should be a symbol that is a key in `inf-clojure-repl-features'." :package-version '(inf-clojure . "3.0.0") :type '(choice (const :tag "clojure" clojure) (const :tag "cljs" cljs) - (const :tag "lumo" lumo) (const :tag "planck" planck) (const :tag "joker" joker) (const :tag "babashka" babashka) From 53efc1aa6e03a594aad185adf11e533a11207e88 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 12:01:09 +0300 Subject: [PATCH 172/189] Update the required Emacs version in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92fd6bd..3b91a80 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ the right code for each REPL type. ## Installation -**Note:** `inf-clojure` requires Emacs 25 or newer. +**Note:** `inf-clojure` requires Emacs 27 or newer. `inf-clojure` is available on the official [NonGNU ELPA](https://elpa.nongnu.org/nongnu/inf-clojure.html) `package.el` repo and on the community-maintained [MELPA Stable][] and [MELPA][] repos. From 4dc2b36223bb6d4063b9c2b6e56875af9c944061 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 12:07:36 +0300 Subject: [PATCH 173/189] Use real callouts --- README.md | 70 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 3b91a80..4e729cb 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,13 @@ It's based on ideas from the popular `inferior-lisp` package. interaction minor mode (`inf-clojure-minor-mode`), which extends `clojure-mode` with commands to evaluate forms directly in the REPL. ------------ - -**This documentation tracks the `master` branch of `inf-clojure`. Some of -the features and settings discussed here might not be available in -older releases (including the current stable release). Please, consult -the relevant git tag (e.g. 2.2.0) if you need documentation for a -specific `inf-clojure` release.** -*** +> [!IMPORTANT] +> +> This documentation tracks the `master` branch of `inf-clojure`. Some of +> the features and settings discussed here might not be available in +> older releases (including the current stable release). Please, consult +> the relevant git tag (e.g. 2.2.0) if you need documentation for a +> specific `inf-clojure` release. ## Overview @@ -54,21 +53,31 @@ For a more powerful/full-featured solution see [CIDER][]. ## Rationale -`inf-clojure`'s goal is to provide the simplest possible way to interact with a Clojure REPL. -In Emacs terminology "inferior" process is a subprocess started by Emacs (it being the "superior" process, of course). +`inf-clojure`'s goal is to provide the simplest possible way to interact with a +Clojure REPL. In Emacs terminology "inferior" process is a subprocess started +by Emacs (it being the "superior" process, of course). -`inf-clojure` doesn't require much of setup, as at its core it simply runs a terminal REPL process, pipes input to it, and -processes its output. As the Clojure socket REPL works in exactly the same manner `inf-clojure` can also interact with it. +`inf-clojure` doesn't require much of setup, as at its core it simply runs a +terminal REPL process, pipes input to it, and processes its output. As the +Clojure socket REPL works in exactly the same manner `inf-clojure` can also +interact with it. -Functionality like code completion and eldoc is powered by evaluation of predefined code snippets that provide the necessary results. -As different Clojure REPLs have different capabilities, `inf-clojure` tracks the type of a REPL and invokes -the right code for each REPL type. +Functionality like code completion and eldoc is powered by evaluation of +predefined code snippets that provide the necessary results. As different +Clojure REPLs have different capabilities, `inf-clojure` tracks the type of a +REPL and invokes the right code for each REPL type. -`inf-clojure` is built on top of Emacs's [comint](https://github.com/emacs-mirror/emacs/blob/master/lisp/comint.el). Unfortunately `comint` is pretty light on official documentation, but there is a good overview/tutorial [here](https://www.masteringemacs.org/article/comint-writing-command-interpreter). +`inf-clojure` is built on top of Emacs's +[comint](https://github.com/emacs-mirror/emacs/blob/master/lisp/comint.el). Unfortunately +`comint` is pretty light on official documentation, but there is a good +overview/tutorial +[here](https://www.masteringemacs.org/article/comint-writing-command-interpreter). ## Installation -**Note:** `inf-clojure` requires Emacs 27 or newer. +> [!IMPORTANT] +> +> `inf-clojure` requires Emacs 27 or newer. `inf-clojure` is available on the official [NonGNU ELPA](https://elpa.nongnu.org/nongnu/inf-clojure.html) `package.el` repo and on the community-maintained [MELPA Stable][] and [MELPA][] repos. @@ -98,7 +107,8 @@ If the installation doesn't work try refreshing the package list: `nil`. You can also add the following to your Emacs config to enable -`inf-clojure-minor-mode` for Clojure source buffers, regardless of whether there's an `inf-clojure` REPL running: +`inf-clojure-minor-mode` for Clojure source buffers, regardless of whether +there's an `inf-clojure` REPL running: ```emacs-lisp (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode) @@ -108,9 +118,11 @@ You can also add the following to your Emacs config to enable (add-hook 'clojure-ts-mode-hook #'inf-clojure-minor-mode) ``` -**Warning:** Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same time. They -have overlapping functionality and keybindings and the result will be nothing -short of havoc. +> [!WARNING] +> +> Don't enable `inf-clojure-minor-mode` and `cider-mode` at the same time. They +> have overlapping functionality and keybindings and the result will be nothing +> short of havoc. ## Basic Usage @@ -147,8 +159,6 @@ for the symbol you want to show the docstring for. ## Configuration -**Note:** The configuration options were changed massively in `inf-clojure` 3.0. - In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely configurable. @@ -173,8 +183,10 @@ that goes with it. This is most easily achieved with the following `.dir-locals. (inf-clojure-custom-repl-type . clojure))) ``` -**Note:** This file has to be in the directory in which you're invoking `inf-clojure` or a parent -directory. +> [!IMPORTANT] +> +> This file has to be in the directory in which you're invoking +> `inf-clojure` or a parent directory. There are two important configuration variables here: @@ -298,9 +310,11 @@ process with another `inf-clojure`. It will be in a new buffer, named `*inf-clojure*`. You can switch between the different process buffers with `switch-to-buffer`. -**Note:** If you're starting `inf-clojure` within a Clojure project directory -the name of the project will be incorporated into the name of the REPL buffer -- e.g. `*inf-clojure my-project*`. +> [!NOTE] +> +> If you're starting `inf-clojure` within a Clojure project directory +> the name of the project will be incorporated into the name of the REPL buffer +> - e.g. `*inf-clojure my-project*`. Commands that send text from source buffers to Clojure processes (like `inf-clojure-eval-defun` or `inf-clojure-show-arglists`) have to choose a process to send to, when you have more than From 847d7057f6e7e8077c718bdd11d20c9e60c60cd8 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 12:11:17 +0300 Subject: [PATCH 174/189] Tweak a warning --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e729cb..a937c08 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,9 @@ option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj) If you have the new [Clojure CLI tools][] installed you can use the `clojure` command: -_do not use `clj` because it adds readline support_ +> [!IMPORTANT] +> +> Do not use `clj` because it adds readline support. ``` shell clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" From c103f2a5463001620c3c7489e3581aa0914c37db Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 12:12:06 +0300 Subject: [PATCH 175/189] m-x -> M-x --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a937c08..7c7a357 100644 --- a/README.md +++ b/README.md @@ -459,7 +459,7 @@ inf-clojure largely needs to know the REPL type so it can format the correct calls. Most end up in `(planck.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 +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. From 0743744608c89fb1a0f0b8799a28e98b2b8c8a5f Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 12:27:39 +0300 Subject: [PATCH 176/189] More README improvements --- README.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7c7a357..6d6978e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![MELPA][melpa-badge]][melpa-package] [![MELPA Stable][melpa-stable-badge]][melpa-stable-package] [![NonGNU ELPA](https://elpa.nongnu.org/nongnu/inf-clojure.svg)](https://elpa.nongnu.org/nongnu/inf-clojure.html) -[![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://discord.com/invite/nFPpynQPME) [![License GPL 3][badge-license]][copying] # inf-clojure @@ -301,7 +300,8 @@ information on how connect: ((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). +The socket server REPL configuration options are described +[here](https://clojure.org/reference/repl_and_main#_launching_a_socket_server). #### Multiple Process Support @@ -314,9 +314,9 @@ buffers with `switch-to-buffer`. > [!NOTE] > -> If you're starting `inf-clojure` within a Clojure project directory -> the name of the project will be incorporated into the name of the REPL buffer -> - e.g. `*inf-clojure my-project*`. +> If you're starting `inf-clojure` within a Clojure project directory the name +> of the project will be incorporated into the name of the REPL buffer - +> e.g. `*inf-clojure my-project*`. Commands that send text from source buffers to Clojure processes (like `inf-clojure-eval-defun` or `inf-clojure-show-arglists`) have to choose a process to send to, when you have more than @@ -355,10 +355,12 @@ acceptable buffers to set as the REPL buffer. If called with a prefix, it will always give the list even if you are currently in an acceptable REPL buffer. -**Tip:** Renaming buffers will greatly improve the -functionality of this list; the list "project-1: clojure repl", -"project-2: cljs repl" is far more understandable than "inf-clojure", -"inf-clojure<2>". +> [!TIP] +> +> Renaming buffers will greatly improve the +> functionality of this list; the list "project-1: clojure repl", +> "project-2: cljs repl" is far more understandable than "inf-clojure", +> "inf-clojure<2>". #### REPL Type @@ -444,9 +446,10 @@ 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 +CIDER does it](https://github.com/clojure-emacs/cider/blob/3e9ed12e8cfbad04d7618e649322765dc9bff5d6/cider-interaction.el#L595). ## Troubleshooting From 8735dcea9cfb4bd7c8b81bd7f52aef9853995f24 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 12:28:49 +0300 Subject: [PATCH 177/189] Tweak the changelog markup --- CHANGELOG.md | 134 +++++++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52823a2..3109832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,142 +4,142 @@ ### New features -* [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. -* [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. -* [#217](https://github.com/clojure-emacs/inf-clojure/pull/217): Add `clojure-ts-mode` support. +- [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. +- [#210](https://github.com/clojure-emacs/inf-clojure/pull/210) Include `inf-clojure-socket-repl` to create a socket REPL and connect to it from inside Emacs. +- [#217](https://github.com/clojure-emacs/inf-clojure/pull/217): Add `clojure-ts-mode` support. ### Changes -* Improve support for multiple forms in the same line by replacing `beginning-of-defun` fn. -* [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands -* [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting REPL. -* Require Emacs 27. -* Drop support for Lumo. +- Improve support for multiple forms in the same line by replacing `beginning-of-defun` fn. +- [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands +- [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting REPL. +- Require Emacs 27. +- Drop support for Lumo. ## 3.2.1 (2022-07-22) ### Bugs fixed -* Address some small issues with NonGNU ELPA (e.g. missing maintainer metadata). +- Address some small issues with NonGNU ELPA (e.g. missing maintainer metadata). ## 3.2.0 (2022-07-15) ### New features -* [#168](https://github.com/clojure-emacs/inf-clojure/pull/197): New helper function `inf-clojure-switch-to-recent-buffer` to select the last buffer an inf-clojure process buffer was swapped to from. -* [#187](https://github.com/clojure-emacs/inf-clojure/pull/197): New defcustom `inf-clojure-enable-eldoc` to disable eldoc interaction. +- [#168](https://github.com/clojure-emacs/inf-clojure/pull/197): New helper function `inf-clojure-switch-to-recent-buffer` to select the last buffer an inf-clojure process buffer was swapped to from. +- [#187](https://github.com/clojure-emacs/inf-clojure/pull/197): New defcustom `inf-clojure-enable-eldoc` to disable eldoc interaction. ### Bugs fixed -* [#185](https://github.com/clojure-emacs/inf-clojure/issues/185): Improve cmd string splitting. -* [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in REPL buffer. -* Fix `inf-clojure-display-version` (it wasn't extracting properly the package version). +- [#185](https://github.com/clojure-emacs/inf-clojure/issues/185): Improve cmd string splitting. +- [#193](https://github.com/clojure-emacs/inf-clojure/pull/193): Set syntax table in REPL buffer. +- Fix `inf-clojure-display-version` (it wasn't extracting properly the package version). ## 3.1.0 (2021-07-23) ### New features -* [#190](https://github.com/clojure-emacs/inf-clojure/pull/190): Helper function `inf-clojure-set-repl` to select inf-clojure process buffer. -* Auto-enable `inf-clojure-minor-mode` after invoking `inf-clojure`. This behaviour is controlled via `inf-clojure-auto-mode`. -* Include the project name automatically in the REPL buffer name. +- [#190](https://github.com/clojure-emacs/inf-clojure/pull/190): Helper function `inf-clojure-set-repl` to select inf-clojure process buffer. +- Auto-enable `inf-clojure-minor-mode` after invoking `inf-clojure`. This behaviour is controlled via `inf-clojure-auto-mode`. +- Include the project name automatically in the REPL buffer name. ### Bugs fixed -* [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. -* [#188](https://github.com/clojure-emacs/inf-clojure/pull/188): Handle newlines between forms for `inf-clojure-eval-buffer`. -* [#189](https://github.com/clojure-emacs/inf-clojure/pull/189): Font-lock code inserted in the REPL from a source buffer. +- [#152](https://github.com/clojure-emacs/inf-clojure/issues/152): Sanitize should only remove whitespace at the end of a command. +- [#188](https://github.com/clojure-emacs/inf-clojure/pull/188): Handle newlines between forms for `inf-clojure-eval-buffer`. +- [#189](https://github.com/clojure-emacs/inf-clojure/pull/189): Font-lock code inserted in the REPL from a source buffer. ## 3.0.0 (2020-08-01) ### New features -* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type`. -* Made it possible to add user-defined REPL types (by modifying `inf-clojure-repl-features`). +- [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Invoke `inf-clojure` with a prefix argument to prevent using `inf-clojure-custom-startup` and `inf-clojure-custom-repl-type`. +- Made it possible to add user-defined REPL types (by modifying `inf-clojure-repl-features`). ### Changes -* **(Breaking)** Restructure massively the configuration. See `inf-clojure-repl-features` for details. -* [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom. -* [#173](https://github.com/clojure-emacs/inf-clojure/issues/173): Use clojure-mode's project detection instead of duplicate version in inf-clojure. +- **(Breaking)*- Restructure massively the configuration. See `inf-clojure-repl-features` for details. +- [#174](https://github.com/clojure-emacs/inf-clojure/pull/174): Set REPL type from startup form or prompt at startup, introduce `inf-clojure-custom-repl-type` defcustom. +- [#173](https://github.com/clojure-emacs/inf-clojure/issues/173): Use clojure-mode's project detection instead of duplicate version in inf-clojure. ### Bugs fixed -* [#178](https://github.com/clojure-emacs/inf-clojure/issues/178): Ensure a valid directory is used when starting process. +- [#178](https://github.com/clojure-emacs/inf-clojure/issues/178): Ensure a valid directory is used when starting process. ## 2.2.0 (2020-04-15) ### New features -* [#170](https://github.com/clojure-emacs/inf-clojure/pull/170): Add insert defun and last sexp commands. -* [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). +- [#170](https://github.com/clojure-emacs/inf-clojure/pull/170): Add insert defun and last sexp commands. +- [#160](https://github.com/clojure-emacs/inf-clojure/pull/160): Support [Joker](https://joker-lang.org/). ### Bugs fixed -* [#164](https://github.com/clojure-emacs/inf-clojure/pull/164): Fix for eldoc-mode on ClojureCLR. -* [#135](https://github.com/clojure-emacs/inf-clojure/pull/135): Improve command sanitation code. -* Fix `info-clojure-apropos`. +- [#164](https://github.com/clojure-emacs/inf-clojure/pull/164): Fix for eldoc-mode on ClojureCLR. +- [#135](https://github.com/clojure-emacs/inf-clojure/pull/135): Improve command sanitation code. +- Fix `info-clojure-apropos`. ## 2.1.0 (2018-01-02) ### New Features -* [#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. -* [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Expose `inf-clojure-apropos` as `C-c C-S-a` in `inf-clojure-mode` (the REPL). -* [#125](https://github.com/clojure-emacs/inf-clojure/pull/125): Avoid throwing an error for frequent operations like completion. -* [#130](https://github.com/clojure-emacs/inf-clojure/pull/130): Support loading directory locals in our buffers. -* [#129](https://github.com/clojure-emacs/inf-clojure/pull/129): Improve the completion bounds detection (now with keywords). -* [#132](https://github.com/clojure-emacs/inf-clojure/pull/132): Introduce inf-clojure-reload. +- [#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. +- [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Expose `inf-clojure-apropos` as `C-c C-S-a` in `inf-clojure-mode` (the REPL). +- [#125](https://github.com/clojure-emacs/inf-clojure/pull/125): Avoid throwing an error for frequent operations like completion. +- [#130](https://github.com/clojure-emacs/inf-clojure/pull/130): Support loading directory locals in our buffers. +- [#129](https://github.com/clojure-emacs/inf-clojure/pull/129): Improve the completion bounds detection (now with keywords). +- [#132](https://github.com/clojure-emacs/inf-clojure/pull/132): Introduce inf-clojure-reload. ### Bugs Fixed -* [#79](https://github.com/clojure-emacs/inf-clojure/pull/82): Eldoc error when running boot repl. -* [#83](https://github.com/clojure-emacs/inf-clojure/pull/85): No such namespace: complete.core in lumo REPL. -* [#93](https://github.com/clojure-emacs/inf-clojure/pull/93): Slow response from inf-clojure (completions, arglists, ...). -* [#101](https://github.com/clojure-emacs/inf-clojure/pull/101): `inf-clojure-set-ns` hangs Emacs. -* [#119](https://github.com/clojure-emacs/inf-clojure/pull/119): Set inf-clojure-buffer REPL type on detect. -* [#120](https://github.com/clojure-emacs/inf-clojure/pull/120): Send REPL string always, even if empty. -* [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Fix inf-clojure-apropos. -* [#131](https://github.com/clojure-emacs/inf-clojure/pull/131): Add macroexpand forms for Lumo. +- [#79](https://github.com/clojure-emacs/inf-clojure/pull/82): Eldoc error when running boot repl. +- [#83](https://github.com/clojure-emacs/inf-clojure/pull/85): No such namespace: complete.core in lumo REPL. +- [#93](https://github.com/clojure-emacs/inf-clojure/pull/93): Slow response from inf-clojure (completions, arglists, ...). +- [#101](https://github.com/clojure-emacs/inf-clojure/pull/101): `inf-clojure-set-ns` hangs Emacs. +- [#119](https://github.com/clojure-emacs/inf-clojure/pull/119): Set inf-clojure-buffer REPL type on detect. +- [#120](https://github.com/clojure-emacs/inf-clojure/pull/120): Send REPL string always, even if empty. +- [#128](https://github.com/clojure-emacs/inf-clojure/pull/128): Fix inf-clojure-apropos. +- [#131](https://github.com/clojure-emacs/inf-clojure/pull/131): Add macroexpand forms for Lumo. ## 2.0.1 (2017-05-18) ### Bugs Fixed -* [#77](https://github.com/clojure-emacs/inf-clojure/pull/77): Fix request "Eval expression:" if arglists return is `nil`. +- [#77](https://github.com/clojure-emacs/inf-clojure/pull/77): Fix request "Eval expression:" if arglists return is `nil`. ## 2.0.0 (2017-05-01) ### New Features -* [#63](https://github.com/clojure-emacs/inf-clojure/pull/69): Fix spurious process output on init. -* [#57](https://github.com/clojure-emacs/inf-clojure/pull/68): Add `inf-clojure-connect`. -* [#66](https://github.com/clojure-emacs/inf-clojure/pull/56): Add Planck support. -* [#51](https://github.com/clojure-emacs/inf-clojure/pull/51): Commands do not prompt by default anymore, unless they receive a non-nil prefix argument. -* [#44](https://github.com/clojure-emacs/inf-clojure/pull/44): Add REPL types and Lumo support. -* [#50](https://github.com/clojure-emacs/inf-clojure/pull/50): Rename defcustoms to `inf-clojure-*-form` where appropriate. -* [#34](https://github.com/clojure-emacs/inf-clojure/pull/34): Add support for socket REPL connections. -* New interactive command `inf-clojure-display-version`. -* [#42](https://github.com/clojure-emacs/inf-clojure/issues/42): Add a defcustom controlling the window in which the REPL buffer is displayed (`inf-clojure-repl-use-same-window`). -* Font-lock the code in the REPL. -* Handle properly ANSI color escape sequences in the REPL. -* [#41](https://github.com/clojure-emacs/inf-clojure/issues/41): Add a command to quit the REPL (it's bound to `C-c C-q`). -* [#29](https://github.com/clojure-emacs/inf-clojure/issues/29): Add a command to restart the REPL. -* [#31](https://github.com/clojure-emacs/inf-clojure/issues/31): Invoke different init command based on the project type (boot, lein or generic). +- [#63](https://github.com/clojure-emacs/inf-clojure/pull/69): Fix spurious process output on init. +- [#57](https://github.com/clojure-emacs/inf-clojure/pull/68): Add `inf-clojure-connect`. +- [#66](https://github.com/clojure-emacs/inf-clojure/pull/56): Add Planck support. +- [#51](https://github.com/clojure-emacs/inf-clojure/pull/51): Commands do not prompt by default anymore, unless they receive a non-nil prefix argument. +- [#44](https://github.com/clojure-emacs/inf-clojure/pull/44): Add REPL types and Lumo support. +- [#50](https://github.com/clojure-emacs/inf-clojure/pull/50): Rename defcustoms to `inf-clojure-*-form` where appropriate. +- [#34](https://github.com/clojure-emacs/inf-clojure/pull/34): Add support for socket REPL connections. +- New interactive command `inf-clojure-display-version`. +- [#42](https://github.com/clojure-emacs/inf-clojure/issues/42): Add a defcustom controlling the window in which the REPL buffer is displayed (`inf-clojure-repl-use-same-window`). +- Font-lock the code in the REPL. +- Handle properly ANSI color escape sequences in the REPL. +- [#41](https://github.com/clojure-emacs/inf-clojure/issues/41): Add a command to quit the REPL (it's bound to `C-c C-q`). +- [#29](https://github.com/clojure-emacs/inf-clojure/issues/29): Add a command to restart the REPL. +- [#31](https://github.com/clojure-emacs/inf-clojure/issues/31): Invoke different init command based on the project type (boot, lein or generic). ### Changes -* Display the REPL in a different window by default (it used to be displayed in the current window). -* [#26](https://github.com/clojure-emacs/inf-clojure/issues/26): Make switching to the REPL optional on `inf-clojure-load-file` (it's now controlled via a prefix argument). -* Removed the `inf-clojure` alias `run-clojure`. +- Display the REPL in a different window by default (it used to be displayed in the current window). +- [#26](https://github.com/clojure-emacs/inf-clojure/issues/26): Make switching to the REPL optional on `inf-clojure-load-file` (it's now controlled via a prefix argument). +- Removed the `inf-clojure` alias `run-clojure`. ### Bugs Fixed -* [#35](https://github.com/clojure-emacs/inf-clojure/issues/35): Fix prompt being included in input history. +- [#35](https://github.com/clojure-emacs/inf-clojure/issues/35): Fix prompt being included in input history. ## 1.4.0 (2016-01-17) ### New Features -* [#22](https://github.com/clojure-emacs/inf-clojure/pull/22): Add ElDoc support. +- [#22](https://github.com/clojure-emacs/inf-clojure/pull/22): Add ElDoc support. From 782bcd9ec89533d7a78dc087e42cc5f27bb5e70b Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 13:01:08 +0300 Subject: [PATCH 178/189] Add Emacs 29 and 30 to the CI matrix --- .circleci/config.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 30583b1..6527b13 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -67,6 +67,22 @@ jobs: - setup - test + test-ubuntu-emacs-29: + docker: + - image: silex/emacs:29-ci + entrypoint: bash + steps: + - setup + - test + + test-ubuntu-emacs-30: + docker: + - image: silex/emacs:30-ci + entrypoint: bash + steps: + - setup + - test + test-ubuntu-emacs-master: docker: - image: silex/emacs:master-ci @@ -94,7 +110,7 @@ jobs: test-lint: docker: - - image: silex/emacs:28-ci + - image: silex/emacs:30-ci steps: - setup - lint @@ -105,6 +121,8 @@ workflows: jobs: - test-ubuntu-emacs-27 - test-ubuntu-emacs-28 + - test-ubuntu-emacs-29 + - test-ubuntu-emacs-30 - test-ubuntu-emacs-master - test-lint - test-macos-emacs-latest From d285b62ecb74e47f7422e72754a5500f4ad86f7d Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:05:53 +0300 Subject: [PATCH 179/189] Address a couple of lint issues --- inf-clojure.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 3e81d9f..cd77498 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1,4 +1,4 @@ -;;; inf-clojure.el --- Run an external Clojure process in an Emacs buffer -*- lexical-binding: t; -*- +;;; inf-clojure.el --- Basic interaction with a Clojure REPL -*- lexical-binding: t; -*- ;; Copyright © 2014-2025 Bozhidar Batsov @@ -8,7 +8,7 @@ ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure ;; Version: 3.3.0-snapshot -;; Package-Requires: ((emacs "27") (clojure-mode "5.11")) +;; Package-Requires: ((emacs "27.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From 1b817dca59c763e96162b1d7d9b87f5108a1975f Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:10:51 +0300 Subject: [PATCH 180/189] Tweak the name of a variable --- inf-clojure.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index cd77498..d29e5bd 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1120,7 +1120,7 @@ START and END are the beginning and end positions in the buffer to send." (interactive) (inf-clojure-eval-defun t)) -(defvar inf-clojure-prev-l/c-dir/file nil +(defvar inf-clojure-prev-loaded-dir-and-file nil "Record last directory and file used in loading or compiling. This holds a cons cell of the form `(DIRECTORY . FILE)' describing the last `inf-clojure-load-file' command.") @@ -1134,12 +1134,12 @@ is present it will be used instead of the current file." (interactive "P") (let* ((proc (inf-clojure-proc)) (file-name (or file-name - (car (comint-get-source "Load Clojure file: " inf-clojure-prev-l/c-dir/file + (car (comint-get-source "Load Clojure file: " inf-clojure-prev-loaded-dir-and-file ;; nil because doesn't need an exact name (inf-clojure--get-preferred-major-modes) nil)))) (load-form (inf-clojure-get-feature proc 'load))) (comint-check-source file-name) ; Check to see if buffer needs saved. - (setq inf-clojure-prev-l/c-dir/file (cons (file-name-directory file-name) + (setq inf-clojure-prev-loaded-dir-and-file (cons (file-name-directory file-name) (file-name-nondirectory file-name))) (inf-clojure--send-string proc (format load-form file-name)) (when switch-to-repl From ac073957ababe266863d66e1b9dd9ada4629e3cd Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:15:48 +0300 Subject: [PATCH 181/189] Address a couple of byte-compilation issues --- inf-clojure.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inf-clojure.el b/inf-clojure.el index d29e5bd..56bf0ec 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -814,6 +814,8 @@ The name is simply the final segment of the path." ))) (project-root (project-current)))) +(defvar clojure-ts-mode-syntax-table) + ;;;###autoload (defun inf-clojure (cmd &optional suppress-message) "Run an inferior Clojure process, input and output via buffer *inf-clojure*. @@ -1145,6 +1147,8 @@ is present it will be used instead of the current file." (when switch-to-repl (inf-clojure-switch-to-repl t)))) +(declare-function clojure-ts-find-ns "clojure-ts-mode") + (defun inf-clojure--find-ns () "Return the namespace of the current Clojure buffer. From 43c436f93da45cdf487ed6bee243006884d8845d Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:19:33 +0300 Subject: [PATCH 182/189] Remove duplicated [] characters from a regexp --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 56bf0ec..c275108 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1504,7 +1504,7 @@ evaluating \\[inf-clojure-completion-form] at the REPL." (funcall inf-clojure-completions-fn (inf-clojure--process-response completion-expr proc "(" ")")))))) -(defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()[@\\^]" +(defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()@\\^" "Regexp are hard. This regex has been built in order to match the first of the From fd9a8fe3bae6e2a64244f8f1ca866bc56447a625 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:23:08 +0300 Subject: [PATCH 183/189] Remove boot project detection Boot is dead. --- inf-clojure.el | 1 - 1 file changed, 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index c275108..d2e56c2 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -803,7 +803,6 @@ The name is simply the final segment of the path." (defun inf-clojure--project-dir () "Return current Clojure project root." (let ((project-vc-extra-root-markers '("project.clj" ; Leiningen - "build.boot" ; Boot "build.gradle" ; Gradle "build.gradle.kts" ; Gradle "deps.edn" ; Clojure CLI (a.k.a. tools.deps) From 89d8874a19c84e3a737a3f3696bfad540b74f117 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:24:52 +0300 Subject: [PATCH 184/189] Revert "Remove duplicated [] characters from a regexp" The previous change resulted in some other lint error. Regular expressions are hard! This reverts commit 43c436f93da45cdf487ed6bee243006884d8845d. --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index d2e56c2..83f640c 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1503,7 +1503,7 @@ evaluating \\[inf-clojure-completion-form] at the REPL." (funcall inf-clojure-completions-fn (inf-clojure--process-response completion-expr proc "(" ")")))))) -(defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()@\\^" +(defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()[@\\^]" "Regexp are hard. This regex has been built in order to match the first of the From b6268430a357b34a10fe9412df507bed77e28fa4 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 16:26:58 +0300 Subject: [PATCH 185/189] Tweak a docstring --- inf-clojure.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inf-clojure.el b/inf-clojure.el index 83f640c..77336a2 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -824,7 +824,7 @@ switch to that buffer. CMD is a string which serves as the startup command or a cons of host and port. - Prompts user for repl startup command and repl type if not + Prompts user for REPL startup command and REPL type if not inferrable from startup command. Uses `inf-clojure-custom-repl-type' and `inf-clojure-custom-startup' if those are set. Use a prefix to prevent using these when they From c86e4a1947707818795d99eabbb5af9549c9960f Mon Sep 17 00:00:00 2001 From: Roman Rudakov Date: Sun, 25 May 2025 17:14:45 +0200 Subject: [PATCH 186/189] Fix CI failures --- .circleci/config.yml | 9 --------- inf-clojure.el | 18 +++++++++++------- test/inf-clojure-tests.el | 5 ++--- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6527b13..f03a87f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,14 +51,6 @@ commands: command: eldev -dtT compile --warnings-as-errors jobs: - test-ubuntu-emacs-27: - docker: - - image: silex/emacs:27-ci - entrypoint: bash - steps: - - setup - - test - test-ubuntu-emacs-28: docker: - image: silex/emacs:28-ci @@ -119,7 +111,6 @@ workflows: version: 2 ci-test-matrix: jobs: - - test-ubuntu-emacs-27 - test-ubuntu-emacs-28 - test-ubuntu-emacs-29 - test-ubuntu-emacs-30 diff --git a/inf-clojure.el b/inf-clojure.el index 77336a2..9122371 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -8,7 +8,7 @@ ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure ;; Version: 3.3.0-snapshot -;; Package-Requires: ((emacs "27.1") (clojure-mode "5.11")) +;; Package-Requires: ((emacs "28.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. @@ -1004,12 +1004,16 @@ of forms." (while (not (eobp)) (while (looking-at "\n") (delete-char 1)) + ;; NOTE: There is no special API for that in + ;; `clojure-ts-mode', so probably for now lets keep this + ;; `clojure-mode' function. (unless (eobp) - ;; NOTE: There is no special API for that in - ;; `clojure-ts-mode', so probably for now lets keep this - ;; `clojure-mode' function. - (clojure-forward-logical-sexp) - (forward-char))) + (clojure-forward-logical-sexp)) + (unless (eobp) + (forward-char) + ;; Remove an empty line at the end of the buffer. + (when (eobp) + (delete-char -1)))) (buffer-substring-no-properties (point-min) (point-max)))) (scan-error str))) @@ -1503,7 +1507,7 @@ evaluating \\[inf-clojure-completion-form] at the REPL." (funcall inf-clojure-completions-fn (inf-clojure--process-response completion-expr proc "(" ")")))))) -(defconst inf-clojure-clojure-expr-break-chars "^[] \"'`><,;|&{()[@\\^]" +(defconst inf-clojure-clojure-expr-break-chars "^][ \"'`><,;|&{()@\\^" "Regexp are hard. This regex has been built in order to match the first of the diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 6023338..af6dea9 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -88,9 +88,8 @@ (ict-with-assess-buffers ((a (insert "@"))) (with-current-buffer a - (expect - (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point)) - :not :to-be nil)))) + (expect (inf-clojure-completion-bounds-of-expr-at-point) + :to-be nil)))) (it "computes bounds for [symbol" (ict-with-assess-buffers From 7f5dd9cf897b6612d72b1f8daba49579b9b3488f Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 23:52:19 +0300 Subject: [PATCH 187/189] Tweak docstrings --- inf-clojure.el | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 9122371..610f7c5 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -1508,21 +1508,12 @@ evaluating \\[inf-clojure-completion-form] at the REPL." (inf-clojure--process-response completion-expr proc "(" ")")))))) (defconst inf-clojure-clojure-expr-break-chars "^][ \"'`><,;|&{()@\\^" - "Regexp are hard. + "A list of characters that serve as expression boundaries. -This regex has been built in order to match the first of the -listed chars. There are a couple of quirks to consider: - -- the ] is always a special in elisp regex so you have to put it - directly AFTER [ if you want to match it as literal. -- The ^ needs to be escaped with \\^. - -Tests and `re-builder' are your friends.") +See `inf-clojure-completion-bounds-of-expr-at-point'.") (defun inf-clojure--kw-to-symbol (kw) - "Convert the keyword KW to a symbol. - -This guy was taken from CIDER, thanks folks." + "Convert the keyword KW to a symbol." (when kw (replace-regexp-in-string "\\`:+" "" kw))) From bdef6110a3d051c08179503207eadc43b1dd4d09 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 23:54:00 +0300 Subject: [PATCH 188/189] Release 3.3 --- CHANGELOG.md | 2 ++ README.md | 2 +- inf-clojure.el | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3109832..d483b14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## 3.3.0 (2025-05-25) + ### New features - [#202](https://github.com/clojure-emacs/inf-clojure/issues/202): Add ClojureCLR support. diff --git a/README.md b/README.md index 6d6978e..c6322c5 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ overview/tutorial > [!IMPORTANT] > -> `inf-clojure` requires Emacs 27 or newer. +> `inf-clojure` requires Emacs 28 or newer. `inf-clojure` is available on the official [NonGNU ELPA](https://elpa.nongnu.org/nongnu/inf-clojure.html) `package.el` repo and on the community-maintained [MELPA Stable][] and [MELPA][] repos. diff --git a/inf-clojure.el b/inf-clojure.el index 610f7c5..37f91ed 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -7,7 +7,7 @@ ;; Maintainer: Bozhidar Batsov ;; URL: http://github.com/clojure-emacs/inf-clojure ;; Keywords: processes, comint, clojure -;; Version: 3.3.0-snapshot +;; Version: 3.3.0 ;; Package-Requires: ((emacs "28.1") (clojure-mode "5.11")) ;; This file is not part of GNU Emacs. From 5decdb89d261247dec01879e763cec0d6b7d04f4 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 25 May 2025 23:55:32 +0300 Subject: [PATCH 189/189] Update changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d483b14..f3c3e90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ - Improve support for multiple forms in the same line by replacing `beginning-of-defun` fn. - [#204](https://github.com/clojure-emacs/inf-clojure/issues/204): Scroll repl buffer on insert commands - [#208](https://github.com/clojure-emacs/inf-clojure/pull/208) Display message after setting REPL. -- Require Emacs 27. +- Require Emacs 28. - Drop support for Lumo. ## 3.2.1 (2022-07-22) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy