64
64
(defcustom cider-show-error-buffer t
65
65
" Control the popup behavior of cider stacktraces.
66
66
The 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
68
68
not to be automatically shown.
69
69
70
70
Irespective 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
72
72
navigate to this buffer."
73
73
:type '(choice (const :tag " always" t )
74
74
(const except-in-repl)
@@ -79,6 +79,12 @@ navigate to this buffer."
79
79
(define-obsolete-variable-alias 'cider-popup-stacktraces
80
80
'cider-show-error-buffer " 0.7.0" )
81
81
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
+
82
88
(defcustom cider-auto-select-error-buffer t
83
89
" Controls whether to auto-select the error popup buffer."
84
90
:type 'boolean
@@ -219,7 +225,7 @@ endpoint and Clojure version."
219
225
(or (match-string 1 repl-buffer-name) " <no designation>" )))
220
226
221
227
(defun cider-change-buffers-designation ()
222
- " Changes the designation in cider buffer names.
228
+ " Change the designation in cider buffer names.
223
229
Buffer names changed are cider-repl, nrepl-connection and nrepl-server."
224
230
(interactive )
225
231
(cider-ensure-connected)
@@ -551,8 +557,8 @@ If no local or remote file exists, return nil."
551
557
552
558
(defun cider--url-to-file (url )
553
559
" 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
556
562
by a colon immediately after the leading '/' then the leading '/' is dropped to
557
563
create a valid path."
558
564
(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."
770
776
(lambda (_buffer out )
771
777
(cider-repl-emit-interactive-output out))
772
778
(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))
776
781
'()))
777
782
778
783
(defun cider-emit-interactive-eval-output (output )
@@ -799,8 +804,8 @@ This is controlled via `cider-interactive-eval-output-destination'."
799
804
(cider-emit-interactive-eval-output out))
800
805
(lambda (buffer err )
801
806
(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))
804
809
'()))
805
810
806
811
(defun cider-load-file-handler (buffer )
@@ -815,8 +820,8 @@ This is controlled via `cider-interactive-eval-output-destination'."
815
820
(cider-emit-interactive-eval-output value))
816
821
(lambda (buffer err )
817
822
(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))
820
825
'()
821
826
(lambda (buffer ex root-ex session )
822
827
(funcall nrepl-err-handler
@@ -919,19 +924,23 @@ They exist for compatibility with `next-error'."
919
924
(status (when causes
920
925
(cider-stacktrace-render buffer (reverse causes))))))))))
921
926
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
+
922
936
(defun cider-default-err-handler (buffer ex root-ex session )
923
937
" Make an error handler for BUFFER, EX, ROOT-EX and SESSION.
924
938
This function determines how the error buffer is shown, and then delegates
925
939
the 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))))
935
944
(if (nrepl-op-supported-p " stacktrace" )
936
945
(cider-default-err-op-handler error-buffer session)
937
946
(cider-default-err-eval-handler error-buffer session))))
@@ -972,42 +981,62 @@ See `compilation-error-regexp-alist' for help on their format.")
972
981
(or type 2 ))
973
982
message))))
974
983
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.
977
986
978
987
We do so by starting and the current position and proceeding backwards
979
988
until 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 )))
981
992
(backward-char )))
982
993
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
+
983
1019
(defun cider-highlight-compilation-errors (buffer message )
984
1020
" 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 (file-truename (buffer-file-name ))))
997
- (goto-char (point-min )) ; start of file
998
- (beginning-of-defun ))
999
- (forward-line (1- line))
1000
- ; ; if have column, highlight sexp at that point otherwise whole line.
1001
- (move-to-column (or col 0 ))
1002
- ; ; we need to select a region to which to apply the error overlay
1003
- ; ; we try to select the encompassing list, vector, set or map literal
1004
- (let ((begin (progn (if col (cider--find-expression-start) (back-to-indentation )) (point )))
1005
- (end (progn (if col (forward-list ) (move-end-of-line nil )) (point ))))
1006
- (let ((overlay (make-overlay begin end)))
1007
- (overlay-put overlay 'cider-note-p t )
1008
- (overlay-put overlay 'face face)
1009
- (overlay-put overlay 'cider-note note)
1010
- (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
+ (overlay-put overlay 'modification-hooks
1031
+ (list (lambda (o &rest args ) (delete-overlay o)))))))
1032
+
1033
+ (defun cider-jump-to-error-maybe (buffer err )
1034
+ " If `cider-auto-jump-to-error' is non-nil, retrieve error location from ERR and jump to it."
1035
+ (-when-let (pos (and cider-auto-jump-to-error
1036
+ (cider--find-last-error-location buffer err)))
1037
+ (with-current-buffer buffer
1038
+ (goto-char (car pos)))))
1039
+
1011
1040
1012
1041
(defun cider-need-input (buffer )
1013
1042
" Handle an need-input request from BUFFER."
0 commit comments