summaryrefslogtreecommitdiff
path: root/cider-repl.el
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2018-09-08 10:27:30 -0700
committerSean Whitton <spwhitton@spwhitton.name>2018-09-08 10:27:30 -0700
commit9148631b2f93ae849cfa141ac11447be42c8f31c (patch)
tree037f9fa2cbb72d7ca0118c1f89961efbafb64065 /cider-repl.el
parent42d3b3f307a8d59632bba30a35d2695f72cf63dc (diff)
parent58f79015f3a28d6aee2fb841b31db3d8a46829d5 (diff)
Merge tag 'v0.18.0+dfsg' into wip/master
DFSG-clean upstream version 0.18.0
Diffstat (limited to 'cider-repl.el')
-rw-r--r--cider-repl.el213
1 files changed, 91 insertions, 122 deletions
diff --git a/cider-repl.el b/cider-repl.el
index bb659215..14eaeb84 100644
--- a/cider-repl.el
+++ b/cider-repl.el
@@ -1,4 +1,4 @@
-;;; cider-repl.el --- REPL interactions -*- lexical-binding: t -*-
+;;; cider-repl.el --- CIDER REPL mode interactions -*- lexical-binding: t -*-
;; Copyright © 2012-2013 Tim King, Phil Hagelberg, Bozhidar Batsov
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
@@ -28,7 +28,8 @@
;;; Commentary:
-;; REPL interactions.
+;; This functionality concerns `cider-repl-mode' and REPL interaction. For
+;; REPL/connection life-cycle management see cider-connection.el.
;;; Code:
@@ -45,6 +46,7 @@
(require 'clojure-mode)
(require 'easymenu)
(require 'cl-lib)
+(require 'sesman)
(eval-when-compile
(defvar paredit-version)
@@ -136,6 +138,16 @@ change the setting's value."
:group 'cider-repl
:package-version '(cider . "0.17.0"))
+(defcustom cider-repl-auto-detect-type t
+ "Control whether to auto-detect the REPL type using track-state information.
+If you disable this you'll have to manually change the REPL type between
+Clojure and ClojureScript when invoking REPL type changing forms.
+Use `cider-set-repl-type' to manually change the REPL type."
+ :type 'boolean
+ :group 'cider-repl
+ :safe #'booleanp
+ :package-version '(cider . "0.18.0"))
+
(defcustom cider-repl-use-clojure-font-lock t
"Non-nil means to use Clojure mode font-locking for input and result.
Nil means that `cider-repl-input-face' and `cider-repl-result-face'
@@ -222,8 +234,7 @@ Currently its only purpose is to facilitate `cider-repl-clear-buffer'.")
(defvar-local cider-repl-ns-cache nil
"A dict holding information about all currently loaded namespaces.
-This cache is stored in the connection buffer. Other buffer's access it
-via `cider-current-connection'.")
+This cache is stored in the connection buffer.")
(defvar cider-mode)
(declare-function cider-refresh-dynamic-font-lock "cider-mode")
@@ -233,8 +244,8 @@ via `cider-current-connection'.")
(with-demoted-errors "Error in `cider-repl--state-handler': %s"
(when (member "state" (nrepl-dict-get response "status"))
(nrepl-dbind-response response (repl-type changed-namespaces)
- (when repl-type
- (cider-repl-set-type repl-type))
+ (when (and repl-type cider-repl-auto-detect-type)
+ (cider-set-repl-type repl-type))
(unless (nrepl-dict-empty-p changed-namespaces)
(setq cider-repl-ns-cache (nrepl-dict-merge cider-repl-ns-cache changed-namespaces))
(dolist (b (buffer-list))
@@ -249,35 +260,6 @@ via `cider-current-connection'.")
ns-dict)))))
(cider-refresh-dynamic-font-lock ns-dict))))))))))
-(declare-function cider-default-err-handler "cider-interaction")
-
-(defun cider-repl-create (endpoint)
- "Create a REPL buffer and install `cider-repl-mode'.
-ENDPOINT is a plist as returned by `nrepl-connect'."
- ;; Connection might not have been set as yet. Please don't send requests here.
- (let* ((reuse-buff (not (eq 'new nrepl-use-this-as-repl-buffer)))
- (buff-name (nrepl-make-buffer-name nrepl-repl-buffer-name-template nil
- (plist-get endpoint :host)
- (plist-get endpoint :port)
- reuse-buff)))
- ;; when reusing, rename the buffer accordingly
- (when (and reuse-buff
- (not (equal buff-name nrepl-use-this-as-repl-buffer)))
- ;; uniquify as it might be Nth connection to the same endpoint
- (setq buff-name (generate-new-buffer-name buff-name))
- (with-current-buffer nrepl-use-this-as-repl-buffer
- (rename-buffer buff-name)))
- (with-current-buffer (get-buffer-create buff-name)
- (unless (derived-mode-p 'cider-repl-mode)
- (cider-repl-mode)
- (cider-repl-set-type "clj"))
- (setq nrepl-err-handler #'cider-default-err-handler)
- (cider-repl-reset-markers)
- (add-hook 'nrepl-response-handler-functions #'cider-repl--state-handler nil 'local)
- (add-hook 'nrepl-connected-hook 'cider--connected-handler nil 'local)
- (add-hook 'nrepl-disconnected-hook 'cider--disconnected-handler nil 'local)
- (current-buffer))))
-
(declare-function cider-set-buffer-ns "cider-mode")
(defun cider-repl-set-initial-ns (buffer)
"Require standard REPL util functions and set the ns of the REPL's BUFFER.
@@ -291,7 +273,7 @@ efficiency."
(let* ((response (nrepl-send-sync-request
(lax-plist-put (nrepl--eval-request "(str *ns*)")
"inhibit-cider-middleware" "true")
- (cider-current-connection)))
+ (cider-current-repl)))
(initial-ns (or (read (nrepl-dict-get response "value"))
"user")))
(cider-set-buffer-ns initial-ns)))))
@@ -305,7 +287,7 @@ efficiency."
"(when (clojure.core/resolve 'clojure.main/repl-requires)
(clojure.core/map clojure.core/require clojure.main/repl-requires))")
"inhibit-cider-middleware" "true")
- (cider-current-connection)))
+ (cider-current-repl)))
(defun cider-repl--build-config-expression ()
"Build the initial config expression."
@@ -324,7 +306,7 @@ efficiency."
(lax-plist-put
(nrepl--eval-request config-expression)
"inhibit-cider-middleware" "true")
- (cider-current-connection))))
+ (cider-current-repl))))
(defun cider-repl-init (buffer &optional no-banner)
"Initialize the REPL in BUFFER.
@@ -356,9 +338,7 @@ client process connection. Unless NO-BANNER is non-nil, insert a banner."
(defun cider-repl--banner ()
"Generate the welcome REPL buffer banner."
- (let ((host (cider--connection-host (current-buffer)))
- (port (cider--connection-port (current-buffer))))
- (format ";; Connected to nREPL server - nrepl://%s:%s
+ (format ";; Connected to nREPL server - nrepl://%s:%s
;; CIDER %s, nREPL %s
;; Clojure %s, Java %s
;; Docs: (doc function-name)
@@ -367,12 +347,12 @@ client process connection. Unless NO-BANNER is non-nil, insert a banner."
;; Javadoc: (javadoc java-object-or-class)
;; Exit: <C-c C-q>
;; Results: Stored in vars *1, *2, *3, an exception in *e;"
- host
- port
- (cider--version)
- (cider--nrepl-version)
- (cider--clojure-version)
- (cider--java-version))))
+ (plist-get nrepl-endpoint :host)
+ (plist-get nrepl-endpoint :port)
+ (cider--version)
+ (cider--nrepl-version)
+ (cider--clojure-version)
+ (cider--java-version)))
(defun cider-repl--help-banner ()
"Generate the help banner."
@@ -697,7 +677,7 @@ If BOL is non-nil insert at the beginning of line. Run
(defun cider-repl--emit-interactive-output (string face)
"Emit STRING as interactive output using FACE."
- (with-current-buffer (cider-current-repl-buffer)
+ (with-current-buffer (cider-current-repl)
(let ((pos (cider-repl--end-of-line-before-input-start))
(string (replace-regexp-in-string "\n\\'" "" string)))
(cider-repl--emit-output-at-pos (current-buffer) string face pos t))))
@@ -710,16 +690,6 @@ If BOL is non-nil insert at the beginning of line. Run
"Emit STRING as interactive err output."
(cider-repl--emit-interactive-output string 'cider-repl-stderr-face))
-(defun cider-repl-manual-warning (section-id format &rest args)
- "Emit a warning to the REPL and link to the online manual.
-SECTION-ID is the section to link to. The link is added on the last line.
-FORMAT is a format string to compile with ARGS and display on the REPL."
- (let ((message (apply #'format format args)))
- (cider-repl-emit-interactive-stderr
- (concat "WARNING: " message "\n "
- (cider--manual-button "More information" section-id)
- "."))))
-
(defun cider-repl--emit-output (buffer string face &optional bol)
"Using BUFFER, emit STRING font-locked with FACE.
If BOL is non-nil, emit at the beginning of the line."
@@ -833,7 +803,6 @@ SHOW-PREFIX and BOL."
(defcustom cider-repl-image-margin 10
"Specifies the margin to be applied to images displayed in the REPL.
-
Either a single number of pixels - interpreted as a symmetric margin, or
pair of numbers `(x . y)' encoding an arbitrary margin."
:type '(choice integer (vector integer integer))
@@ -842,12 +811,10 @@ pair of numbers `(x . y)' encoding an arbitrary margin."
(defun cider-repl--image (data type datap)
"A helper for creating images with CIDER's image options.
-
-DATA is either the path to an image or its base64 coded data. TYPE
-is a symbol indicating the image type. DATAP indicates whether the image is
-the raw image data or a filename.
-
-Returns an image instance with a margin per `cider-repl-image-margin'."
+DATA is either the path to an image or its base64 coded data. TYPE is a
+symbol indicating the image type. DATAP indicates whether the image is the
+raw image data or a filename. Returns an image instance with a margin per
+`cider-repl-image-margin'."
(create-image data type datap
:margin cider-repl-image-margin))
@@ -856,14 +823,14 @@ Returns an image instance with a margin per `cider-repl-image-margin'."
Part of the default `cider-repl-content-type-handler-alist'."
(cider-repl--display-image buffer
(cider-repl--image image 'jpeg t)
- show-prefix bol image))
+ show-prefix bol " "))
(defun cider-repl-handle-png (_type buffer image &optional show-prefix bol)
"A handler for inserting a png IMAGE into a repl BUFFER.
Part of the default `cider-repl-content-type-handler-alist'."
(cider-repl--display-image buffer
(cider-repl--image image 'png t)
- show-prefix bol image))
+ show-prefix bol " "))
(defun cider-repl-handle-external-body (type buffer _ &optional _show-prefix _bol)
"Handler for slurping external content into BUFFER.
@@ -871,9 +838,9 @@ Handles an external-body TYPE by issuing a slurp request to fetch the content."
(if-let* ((args (cadr type))
(access-type (nrepl-dict-get args "access-type")))
(nrepl-send-request
- (list "op" "slurp" "url" (nrepl-dict-get args "URL"))
+ (list "op" "slurp" "url" (nrepl-dict-get args access-type))
(cider-repl-handler buffer)
- (cider-current-connection)))
+ (cider-current-repl)))
nil)
(defvar cider-repl-content-type-handler-alist
@@ -881,7 +848,6 @@ Handles an external-body TYPE by issuing a slurp request to fetch the content."
("image/jpeg" . ,#'cider-repl-handle-jpeg)
("image/png" . ,#'cider-repl-handle-png))
"Association list from content-types to handlers.
-
Handlers must be functions of two required and two optional arguments - the
REPL buffer to insert into, the value of the given content type as a raw
string, the REPL's show prefix as any and an `end-of-line' flag.
@@ -1062,9 +1028,13 @@ text property `cider-old-input'."
(defun cider-repl-switch-to-other ()
"Switch between the Clojure and ClojureScript REPLs for the current project."
(interactive)
- (if-let* ((other-connection (cider-other-connection)))
- (switch-to-buffer other-connection)
- (message "There's no other REPL for the current project")))
+ ;; FIXME: implement cycling as session can hold more than two REPLs
+ (let* ((this-repl (cider-current-repl nil 'ensure))
+ (other-repl (car (seq-remove (lambda (r) (eq r this-repl)) (cider-repls nil t)))))
+ (if other-repl
+ (switch-to-buffer other-repl)
+ (user-error "No other REPL in current session (%s)"
+ (car (sesman-current-session 'CIDER))))))
(defvar cider-repl-clear-buffer-hook)
@@ -1075,7 +1045,6 @@ text property `cider-old-input'."
(defun cider-repl-clear-buffer ()
"Clear the currently visited REPL buffer completely.
-
See also the related commands `cider-repl-clear-output' and
`cider-find-and-clear-repl-output'."
(interactive)
@@ -1162,12 +1131,9 @@ With a prefix argument CLEAR-REPL it will clear the entire REPL buffer instead."
(defun cider-repl-set-ns (ns)
"Switch the namespace of the REPL buffer to NS.
-
-If called from a cljc buffer act on both the Clojure and
-ClojureScript REPL if there are more than one REPL present.
-
-If invoked in a REPL buffer the command will prompt for the name of the
-namespace to switch to."
+If called from a cljc buffer act on both the Clojure and ClojureScript REPL
+if there are more than one REPL present. If invoked in a REPL buffer the
+command will prompt for the name of the namespace to switch to."
(interactive (list (if (or (derived-mode-p 'cider-repl-mode)
(null (cider-ns-form)))
(completing-read "Switch to namespace: "
@@ -1175,23 +1141,10 @@ namespace to switch to."
(cider-current-ns))))
(when (or (not ns) (equal ns ""))
(user-error "No namespace selected"))
- (cider-map-connections
- (lambda (connection)
- (cider-nrepl-request:eval (format "(in-ns '%s)" ns)
- (cider-repl-switch-ns-handler connection)))
- :both))
-
-(defun cider-repl-set-type (&optional type)
- "Set REPL TYPE to \"clj\" or \"cljs\"."
- (interactive)
- (let ((type (or type (completing-read
- (format "Set REPL type (currently `%s') to: "
- cider-repl-type)
- '("clj" "cljs")))))
- (setq cider-repl-type type)
- (if (equal type "cljs")
- (setq mode-name "REPL[cljs]")
- (setq mode-name "REPL[clj]"))))
+ (cider-map-repls :auto
+ (lambda (connection)
+ (cider-nrepl-request:eval (format "(in-ns '%s)" ns)
+ (cider-repl-switch-ns-handler connection)))))
;;; Location References
@@ -1200,7 +1153,9 @@ namespace to switch to."
'((stdout-stacktrace "[ \t]\\(at \\([^$(]+\\).*(\\([^:()]+\\):\\([0-9]+\\))\\)" 1 2 3 4)
(aviso-stacktrace "^[ \t]*\\(\\([^$/ \t]+\\).*? +\\([^:]+\\): +\\([0-9]+\\)\\)" 1 2 3 4)
(print-stacktrace "\\[\\([^][$ \t]+\\).* +\\([^ \t]+\\) +\\([0-9]+\\)\\]" 0 1 2 3)
- (timbre-log "\\(TRACE\\|INFO\\|DEBUG\\|WARN\\|ERROR\\) +\\(\\[\\([^:]+\\):\\([0-9]+\\)\\]\\)" 2 3 nil 4))
+ (timbre-log "\\(TRACE\\|INFO\\|DEBUG\\|WARN\\|ERROR\\) +\\(\\[\\([^:]+\\):\\([0-9]+\\)\\]\\)" 2 3 nil 4)
+ (cljs-message "at line \\([0-9]+\\) +\\(.*\\)$" 0 nil 2 1)
+ (reflection "Reflection warning, +\\(\\([^\n:]+\\):\\([0-9]+\\):[0-9]+\\)" 1 nil 2 3))
"Alist holding regular expressions for inline location references.
Each element in the alist has the form (NAME REGEXP HIGHLIGHT VAR FILE
LINE), where NAME is the identifier of the regexp, REGEXP - regexp matching
@@ -1258,7 +1213,12 @@ regexes from `cider-locref-regexp-alist' to infer locations at point."
(or (cider-sync-request:ns-path var)
(nrepl-dict-get (cider-sync-request:info var) "file")))
;; when not found, return the file detected by regexp
- (plist-get loc :file))))
+ (when-let* ((file (plist-get loc :file)))
+ (if (file-name-absolute-p file)
+ file
+ ;; when not absolute, expand within the current project
+ (when-let* ((proj (clojure-project-dir)))
+ (expand-file-name file proj)))))))
(if file
(cider--jump-to-loc-from-info (nrepl-dict "file" file "line" line) t)
(error "No source location for %s" var)))
@@ -1522,15 +1482,13 @@ constructs."
"Add a REPL shortcut command, defined by NAME and HANDLER."
(puthash name handler cider-repl-shortcuts))
-(declare-function cider-restart "cider-interaction")
-(declare-function cider-quit "cider-interaction")
-(declare-function cider-toggle-trace-ns "cider-interaction")
-(declare-function cider-undef "cider-interaction")
+(declare-function cider-toggle-trace-ns "cider-tracing")
+(declare-function cider-undef "cider-mode")
(declare-function cider-browse-ns "cider-browse-ns")
(declare-function cider-classpath "cider-classpath")
(declare-function cider-repl-history "cider-repl-history")
-(declare-function cider-run "cider-interaction")
-(declare-function cider-refresh "cider-interaction")
+(declare-function cider-run "cider-mode")
+(declare-function cider-ns-refresh "cider-ns")
(declare-function cider-version "cider")
(declare-function cider-test-run-loaded-tests "cider-test")
(declare-function cider-test-run-project-tests "cider-test")
@@ -1545,7 +1503,7 @@ constructs."
(cider-repl-add-shortcut "history" #'cider-repl-history)
(cider-repl-add-shortcut "trace-ns" #'cider-toggle-trace-ns)
(cider-repl-add-shortcut "undef" #'cider-undef)
-(cider-repl-add-shortcut "refresh" #'cider-refresh)
+(cider-repl-add-shortcut "refresh" #'cider-ns-refresh)
(cider-repl-add-shortcut "help" #'cider-repl-shortcuts-help)
(cider-repl-add-shortcut "test-ns" #'cider-test-run-ns-tests)
(cider-repl-add-shortcut "test-all" #'cider-test-run-loaded-tests)
@@ -1555,8 +1513,7 @@ constructs."
(cider-repl-add-shortcut "test-project-with-filters" (lambda () (interactive) (cider-test-run-project-tests 'prompt-for-filters)))
(cider-repl-add-shortcut "test-report" #'cider-test-show-report)
(cider-repl-add-shortcut "run" #'cider-run)
-(cider-repl-add-shortcut "conn-info" #'cider-display-connection-info)
-(cider-repl-add-shortcut "conn-rotate" #'cider-rotate-default-connection)
+(cider-repl-add-shortcut "conn-info" #'cider-describe-connection)
(cider-repl-add-shortcut "hasta la vista" #'cider-quit)
(cider-repl-add-shortcut "adios" #'cider-quit)
(cider-repl-add-shortcut "sayonara" #'cider-quit)
@@ -1608,18 +1565,21 @@ constructs."
(defvar cider-repl-mode-syntax-table
(copy-syntax-table clojure-mode-syntax-table))
-(declare-function cider-eval-last-sexp "cider-interaction")
-(declare-function cider-refresh "cider-interaction")
-(declare-function cider-toggle-trace-ns "cider-interaction")
-(declare-function cider-toggle-trace-var "cider-interaction")
-(declare-function cider-find-resource "cider-interaction")
-(declare-function cider-restart "cider-interaction")
-(declare-function cider-find-ns "cider-interaction")
-(declare-function cider-find-keyword "cider-interaction")
+(declare-function cider-eval-last-sexp "cider-eval")
+(declare-function cider-toggle-trace-ns "cider-tracing")
+(declare-function cider-toggle-trace-var "cider-tracing")
+(declare-function cider-find-resource "cider-find")
+(declare-function cider-find-ns "cider-find")
+(declare-function cider-find-keyword "cider-find")
+(declare-function cider-find-var "cider-find")
(declare-function cider-switch-to-last-clojure-buffer "cider-mode")
(declare-function cider-macroexpand-1 "cider-macroexpansion")
(declare-function cider-macroexpand-all "cider-macroexpansion")
(declare-function cider-selector "cider-selector")
+(declare-function cider-jack-in-clj "cider")
+(declare-function cider-jack-in-cljs "cider")
+(declare-function cider-connect-clj "cider")
+(declare-function cider-connect-cljs "cider")
(defvar cider-repl-mode-map
(let ((map (make-sparse-keymap)))
@@ -1652,19 +1612,26 @@ constructs."
(define-key map (kbd "C-c C-c") #'cider-interrupt)
(define-key map (kbd "C-c C-m") #'cider-macroexpand-1)
(define-key map (kbd "C-c M-m") #'cider-macroexpand-all)
+ (define-key map (kbd "C-c C-s") #'sesman-map)
(define-key map (kbd "C-c C-z") #'cider-switch-to-last-clojure-buffer)
(define-key map (kbd "C-c M-o") #'cider-repl-switch-to-other)
(define-key map (kbd "C-c M-s") #'cider-selector)
- (define-key map (kbd "C-c M-d") #'cider-display-connection-info)
+ (define-key map (kbd "C-c M-d") #'cider-describe-connection)
(define-key map (kbd "C-c C-q") #'cider-quit)
+ (define-key map (kbd "C-c M-r") #'cider-restart)
(define-key map (kbd "C-c M-i") #'cider-inspect)
(define-key map (kbd "C-c M-p") #'cider-repl-history)
(define-key map (kbd "C-c M-t v") #'cider-toggle-trace-var)
(define-key map (kbd "C-c M-t n") #'cider-toggle-trace-ns)
- (define-key map (kbd "C-c C-x") #'cider-refresh)
+ (define-key map (kbd "C-c C-x") 'cider-start-map)
(define-key map (kbd "C-x C-e") #'cider-eval-last-sexp)
(define-key map (kbd "C-c C-r") 'clojure-refactor-map)
(define-key map (kbd "C-c C-v") 'cider-eval-commands-map)
+ (define-key map (kbd "C-c M-j") #'cider-jack-in-clj)
+ (define-key map (kbd "C-c M-J") #'cider-jack-in-cljs)
+ (define-key map (kbd "C-c M-c") #'cider-connect-clj)
+ (define-key map (kbd "C-c M-C") #'cider-connect-cljs)
+
(define-key map (string cider-repl-shortcut-dispatch-char) #'cider-repl-handle-shortcut)
(easy-menu-define cider-repl-mode-menu map
"Menu for CIDER's REPL mode"
@@ -1693,10 +1660,9 @@ constructs."
["Inspect" cider-inspect]
["Toggle var tracing" cider-toggle-trace-var]
["Toggle ns tracing" cider-toggle-trace-ns]
- ["Refresh loaded code" cider-refresh]
+ ["Refresh loaded code" cider-ns-refresh]
"--"
["Set REPL ns" cider-repl-set-ns]
- ["Set REPL type" cider-repl-set-type]
["Toggle pretty printing" cider-repl-toggle-pretty-printing]
["Require REPL utils" cider-repl-require-repl-utils]
"--"
@@ -1717,7 +1683,7 @@ constructs."
"--"
["Interrupt evaluation" cider-interrupt]
"--"
- ["Connection info" cider-display-connection-info]
+ ["Connection info" cider-describe-connection]
"--"
["Close ancillary buffers" cider-close-ancillary-buffers]
["Quit" cider-quit]
@@ -1732,6 +1698,8 @@ constructs."
["Version info" cider-version]))
map))
+(sesman-install-menu cider-repl-mode-map)
+
(defun cider-repl-wrap-fontify-function (func)
"Return a function that will call FUNC narrowed to input region."
(lambda (beg end &rest rest)
@@ -1742,7 +1710,7 @@ constructs."
(let ((font-lock-dont-widen t))
(apply func (max beg cider-repl-input-start-mark) end rest))))))
-(declare-function cider-complete-at-point "cider-interaction")
+(declare-function cider-complete-at-point "cider-completion")
(defvar cider--static-font-lock-keywords)
(define-derived-mode cider-repl-mode fundamental-mode "REPL"
@@ -1752,6 +1720,7 @@ constructs."
(clojure-mode-variables)
(clojure-font-lock-setup)
(font-lock-add-keywords nil cider--static-font-lock-keywords)
+ (setq-local sesman-system 'CIDER)
(setq-local font-lock-fontify-region-function
(cider-repl-wrap-fontify-function font-lock-fontify-region-function))
(setq-local font-lock-unfontify-region-function