6464(defcustom cider-show-error-buffer t
6565 " Control the popup behavior of cider stacktraces.
6666The following values are possible t or 'always, 'except-in-repl,
67- 'only-in-repl. Any other value, including nil, will cause the stacktrace
67+ 'only-in-repl. Any other value, including nil, will cause the stacktrace
6868not to be automatically shown.
6969
7070Irespective of the value of this variable, the `cider-error-buffer' is
71- always generated in the background. Use `cider-visit-error-buffer' to
71+ always generated in the background. Use `cider-visit-error-buffer' to
7272navigate to this buffer."
7373 :type '(choice (const :tag " always" t )
7474 (const except-in-repl)
@@ -79,6 +79,12 @@ navigate to this buffer."
7979(define-obsolete-variable-alias 'cider-popup-stacktraces
8080 'cider-show-error-buffer " 0.7.0" )
8181
82+ (defcustom cider-auto-jump-to-error t
83+ " When non-nill automatically jump to error location during interactive compilation."
84+ :type 'boolean
85+ :group 'cider
86+ :package-version '(cider . " 0.7.0" ))
87+
8288(defcustom cider-auto-select-error-buffer t
8389 " Controls whether to auto-select the error popup buffer."
8490 :type 'boolean
@@ -219,7 +225,7 @@ endpoint and Clojure version."
219225 (or (match-string 1 repl-buffer-name) " <no designation>" )))
220226
221227(defun cider-change-buffers-designation ()
222- " Changes the designation in cider buffer names.
228+ " Change the designation in cider buffer names.
223229Buffer names changed are cider-repl, nrepl-connection and nrepl-server."
224230 (interactive )
225231 (cider-ensure-connected)
@@ -551,8 +557,8 @@ If no local or remote file exists, return nil."
551557
552558(defun cider--url-to-file (url )
553559 " Return the filename from the resource URL.
554- Uses `url-generic-parse-url' to parse the url. The filename is extracted and
555- then url decoded. If the decoded filename has a Windows device letter followed
560+ Uses `url-generic-parse-url' to parse the url. The filename is extracted and
561+ then url decoded. If the decoded filename has a Windows device letter followed
556562by a colon immediately after the leading '/' then the leading '/' is dropped to
557563create a valid path."
558564 (let ((filename (url-unhex-string (url-filename (url-generic-parse-url url)))))
@@ -770,9 +776,8 @@ The handler simply inserts the result value in BUFFER."
770776 (lambda (_buffer out )
771777 (cider-repl-emit-interactive-output out))
772778 (lambda (buffer err )
773- (message " %s " err)
774- (cider-highlight-compilation-errors
775- buffer err))
779+ (cider-highlight-compilation-errors buffer err)
780+ (cider-jump-to-error-maybe buffer err))
776781 '()))
777782
778783(defun cider-emit-interactive-eval-output (output )
@@ -799,8 +804,8 @@ This is controlled via `cider-interactive-eval-output-destination'."
799804 (cider-emit-interactive-eval-output out))
800805 (lambda (buffer err )
801806 (cider-emit-interactive-eval-output err)
802- (cider-highlight-compilation-errors
803- buffer err))
807+ (cider-highlight-compilation-errors buffer err)
808+ (cider-jump-to-error-maybe buffer err))
804809 '()))
805810
806811(defun cider-load-file-handler (buffer )
@@ -815,8 +820,8 @@ This is controlled via `cider-interactive-eval-output-destination'."
815820 (cider-emit-interactive-eval-output value))
816821 (lambda (buffer err )
817822 (cider-emit-interactive-eval-output err)
818- (cider-highlight-compilation-errors
819- buffer err))
823+ (cider-highlight-compilation-errors buffer err)
824+ (cider-jump-to-error-maybe buffer err))
820825 '()
821826 (lambda (buffer ex root-ex session )
822827 (funcall nrepl-err-handler
@@ -919,19 +924,23 @@ They exist for compatibility with `next-error'."
919924 (status (when causes
920925 (cider-stacktrace-render buffer (reverse causes))))))))))
921926
927+ (defun cider--show-error-buffer-p (buffer )
928+ " Return non-nil if stacktrace buffer must be shown on error.
929+ Takes into account the current BUFFER and the value of `cider-show-error-buffer' ."
930+ (let ((replp (with-current-buffer buffer (derived-mode-p 'cider-repl-mode ))))
931+ (memq cider-show-error-buffer
932+ (if replp
933+ '(t always only-in-repl)
934+ '(t always except-in-repl)))))
935+
922936(defun cider-default-err-handler (buffer ex root-ex session )
923937 " Make an error handler for BUFFER, EX, ROOT-EX and SESSION.
924938This function determines how the error buffer is shown, and then delegates
925939the actual error content to the eval or op handler."
926- (let* ((replp (with-current-buffer buffer (derived-mode-p 'cider-repl-mode )))
927- (showp (memq cider-show-error-buffer
928- (if replp
929- '(t always only-in-repl)
930- '(t always except-in-repl))))
931- (error-buffer (if (not showp)
932- (cider-make-popup-buffer cider-error-buffer)
933- (cider-popup-buffer cider-error-buffer
934- cider-auto-select-error-buffer))))
940+ (let* ((error-buffer (if (cider--show-error-buffer-p buffer)
941+ (cider-popup-buffer cider-error-buffer
942+ cider-auto-select-error-buffer)
943+ (cider-make-popup-buffer cider-error-buffer))))
935944 (if (nrepl-op-supported-p " stacktrace" )
936945 (cider-default-err-op-handler error-buffer session)
937946 (cider-default-err-eval-handler error-buffer session))))
@@ -972,43 +981,60 @@ See `compilation-error-regexp-alist' for help on their format.")
972981 (or type 2 ))
973982 message))))
974983
975- (defun cider--find -expression-start ()
976- " Find the beginning a list, vector, map or set outside of a string.
984+ (defun cider--goto -expression-start ()
985+ " Go to the beginning a list, vector, map or set outside of a string.
977986
978987We do so by starting and the current position and proceeding backwards
979988until we find a delimiters that's not inside a string."
980- (while (or (not (looking-at " [({[]" )) (eq 'font-lock-string-face (get-text-property (point ) 'face )))
989+ (while (or (not (looking-at " [({[]" ))
990+ (eq 'font-lock-string-face
991+ (get-text-property (point ) 'face )))
981992 (backward-char )))
982993
994+ (defun cider--find-last-error-location (buffer message )
995+ " Return the location (begin . end) in BUFFER from the clojure error MESSAGE.
996+ If location could not be found, return nil."
997+ (save-excursion
998+ (with-current-buffer buffer
999+ (let ((info (cider-extract-error-info cider-compilation-regexp message)))
1000+ (when info
1001+ (let ((file (nth 0 info))
1002+ (line (nth 1 info))
1003+ (col (nth 2 info)))
1004+ (save-excursion
1005+ ; ; when we don't have a filename or it's different from the one of
1006+ ; ; the current buffer, the line number is relative to form start
1007+ (if (and file (equal (file-truename file)
1008+ (file-truename (buffer-file-name ))))
1009+ (goto-char (point-min )) ; start of file
1010+ (beginning-of-defun ))
1011+ (forward-line (1- line))
1012+ (move-to-column (or col 0 ))
1013+ (let ((begin (progn (if col (cider--goto-expression-start) (back-to-indentation ))
1014+ (point )))
1015+ (end (progn (if col (forward-list ) (move-end-of-line nil ))
1016+ (point ))))
1017+ (cons begin end)))))))))
1018+
9831019(defun cider-highlight-compilation-errors (buffer message )
9841020 " Highlight compilation error line in BUFFER, using MESSAGE."
985- (with-current-buffer buffer
986- (let ((info (cider-extract-error-info cider-compilation-regexp message)))
987- (when info
988- (let ((file (nth 0 info))
989- (line (nth 1 info))
990- (col (nth 2 info))
991- (face (nth 3 info))
992- (note (nth 4 info)))
993- (save-excursion
994- ; ; when we don't have a filename or it's different from the one of
995- ; ; the current buffer, the line number is relative to form start
996- (if (and file (equal (file-truename file)
997- (file-truename (buffer-file-name ))))
998- (goto-char (point-min )) ; start of file
999- (beginning-of-defun ))
1000- (forward-line (1- line))
1001- ; ; if have column, highlight sexp at that point otherwise whole line.
1002- (move-to-column (or col 0 ))
1003- ; ; we need to select a region to which to apply the error overlay
1004- ; ; we try to select the encompassing list, vector, set or map literal
1005- (let ((begin (progn (if col (cider--find-expression-start) (back-to-indentation )) (point )))
1006- (end (progn (if col (forward-list ) (move-end-of-line nil )) (point ))))
1007- (let ((overlay (make-overlay begin end)))
1008- (overlay-put overlay 'cider-note-p t )
1009- (overlay-put overlay 'face face)
1010- (overlay-put overlay 'cider-note note)
1011- (overlay-put overlay 'help-echo note)))))))))
1021+ (-when-let* ((pos (cider--find-last-error-location buffer message))
1022+ (overlay (make-overlay (car pos) (cdr pos) buffer))
1023+ (info (cider-extract-error-info cider-compilation-regexp message)))
1024+ (let ((face (nth 3 info))
1025+ (note (nth 4 info)))
1026+ (overlay-put overlay 'cider-note-p t )
1027+ (overlay-put overlay 'face face)
1028+ (overlay-put overlay 'cider-note note)
1029+ (overlay-put overlay 'help-echo note))))
1030+
1031+ (defun cider-jump-to-error-maybe (buffer err )
1032+ " If `cider-auto-jump-to-error' is non-nil, retrieve error location from ERR and jump to it."
1033+ (-when-let (pos (and cider-auto-jump-to-error
1034+ (cider--find-last-error-location buffer err)))
1035+ (with-current-buffer buffer
1036+ (goto-char (car pos)))))
1037+
10121038
10131039(defun cider-need-input (buffer )
10141040 " Handle an need-input request from BUFFER."
0 commit comments