28
28
(require 'nrepl-client )
29
29
(require 'cider-interaction )
30
30
31
- (defvar cider--current-debug-value nil
32
- " Last value received from the debugger.
33
- Is printed by `cider--debug-read-command' while stepping through
34
- code." )
35
-
36
31
(defconst cider--instrument-format
37
32
(concat " (cider.nrepl.middleware.debug/instrument-and-eval"
38
33
; ; filename and point are passed in a map. Eventually, this should be
@@ -46,14 +41,13 @@ code.")
46
41
" Initialize a connection with clj-debugger."
47
42
(nrepl-send-request
48
43
'(" op" " init-debugger" )
49
- (let ((connection-buffer (nrepl-current-connection-buffer)))
50
- (lambda (response )
51
- (nrepl-dbind-response response (debug-value coor filename point status id)
52
- (if (not (member " done" status))
53
- (cider--handle-debug debug-value coor filename point connection-buffer)
54
- (puthash id (gethash id nrepl-pending-requests)
55
- nrepl-completed-requests)
56
- (remhash id nrepl-pending-requests)))))))
44
+ (lambda (response )
45
+ (nrepl-dbind-response response (status id)
46
+ (if (not (member " done" status))
47
+ (cider--handle-debug response)
48
+ (puthash id (gethash id nrepl-pending-requests)
49
+ nrepl-completed-requests)
50
+ (remhash id nrepl-pending-requests))))))
57
51
58
52
(defun cider--forward-sexp (n )
59
53
" Move forward N logical sexps.
@@ -68,64 +62,61 @@ This will skip over sexps that don't represent objects, such as ^{}."
68
62
(forward-sexp 1 )
69
63
(setq n (1- n))))
70
64
71
- (defun cider--handle-debug (value coordinates file point connection-buffer )
72
- " Handle debugging notification.
73
- VALUE is saved in `cider--current-debug-value' to be printed
74
- while waiting for user input.
75
- COORDINATES, FILE and POINT are used to place point at the instrumented sexp.
76
- CONNECTION-BUFFER is the nrepl buffer."
77
- ; ; Be ready to prompt the user when debugger.core/break is
78
- ; ; triggers a need-input request.
79
- (nrepl-push-input-handler #'cider--need-debug-input connection-buffer)
80
-
65
+ (defun cider--debug-move-point (file pos coordinates )
66
+ " Place point on POS in FILE, then navigate into the next sexp.
67
+ COORDINATES is a list of integers that specify how to navigate into the
68
+ sexp."
81
69
; ; Navigate to the instrumented sexp, wherever we might be.
82
70
(find-file file)
83
71
; ; Position of the sexp.
84
- (goto-char point )
72
+ (goto-char pos )
85
73
(condition-case nil
86
74
; ; Make sure it is a list.
87
- ( let ((coordinates ( append coordinates nil )))
88
- ; ; Navigate through sexps inside the sexp.
75
+ ; ; Navigate through sexps inside the sexp.
76
+ ( progn
89
77
(while coordinates
90
78
(down-list )
91
79
(cider--forward-sexp (pop coordinates)))
92
80
; ; Place point at the end of instrumented sexp.
93
81
(cider--forward-sexp 1 ))
94
82
; ; Avoid throwing actual errors, since this happens on every breakpoint.
95
- (error (message " Can't find instrumented sexp, did you edit the source? " )))
96
- ; ; Prepare to notify the user.
97
- (setq cider--current-debug-value value))
98
-
99
- (defun cider--debug-read-command ()
100
- " Receive input from the user representing a command to do."
101
- (let ((cider-interactive-eval-result-prefix
102
- " (n)ext (c)ontinue (i)nject => " ))
103
- (cider--display-interactive-eval-result
104
- (or cider--current-debug-value " #unknown#" )))
105
- (let ((input
106
- (cl-case (read-char )
107
- ; ; These keys were chosen to match edebug rather than clj-debugger.
108
- (?n " (c)" )
109
- (?c " (q)" )
110
- ; ; Inject
111
- (?i (condition-case nil
112
- (concat (read-from-minibuffer " Expression to inject (non-nil): " )
113
- " \n (c)" )
114
- (quit nil ))))))
115
- (if (and input (not (string= " " input)))
116
- (progn (setq cider--current-debug-value nil )
117
- input)
118
- (cider--debug-read-command))))
119
-
120
- (defun cider--need-debug-input (buffer )
121
- " Handle an need-input request from BUFFER."
122
- (with-current-buffer buffer
123
- (nrepl-request:stdin
124
- ; ; For now we immediately try to read-char. Ideally, this will
125
- ; ; be done in a minor-mode (like edebug does) so that the user
126
- ; ; isn't blocked from doing anything else.
127
- (concat (cider--debug-read-command) " \n " )
128
- (cider-stdin-handler buffer))))
83
+ (error (message " Can't find instrumented sexp, did you edit the source? " ))))
84
+
85
+ (defun cider--handle-debug (response )
86
+ " Handle debugging notification.
87
+ RESPONSE is a message received form the nrepl describing the input
88
+ needed. It is expected to contain at least \" key\" , \" input-type\" , and
89
+ \" prompt\" , and possibly other entries depending on the input-type."
90
+ (nrepl-dbind-response response (debug-value key coor filename point input-type prompt)
91
+ (let ((input))
92
+ (unwind-protect
93
+ (setq input
94
+ (pcase input-type
95
+ (" expression" (cider-read-from-minibuffer
96
+ (or prompt " Expression: " )))
97
+ ((pred sequencep)
98
+ (when (and filename point)
99
+ (cider--debug-move-point filename point coor))
100
+ (cider--debug-read-command input-type debug-value prompt))))
101
+ ; ; No matter what, we want to send this request or the session will stay
102
+ ; ; hanged.
103
+ (nrepl-send-request
104
+ (list " op" " debug-input" " key" key
105
+ ; ; If the user somehow managed to trigger an error or not input
106
+ ; ; anything send :quit to avoid getting an exception.
107
+ " input" (or input " :quit" ))
108
+ #'ignore )))))
109
+
110
+ (defun cider--debug-read-command (command-list value prompt )
111
+ " Receive input from the user representing a command to do.
112
+ VALUE is displayed to the user as the output of last evaluated sexp."
113
+ (let ((cider-interactive-eval-result-prefix (concat prompt " \n => " )))
114
+ (cider--display-interactive-eval-result (or value " #unknown#" )))
115
+ (let ((alist `((?\C -\[ . " :quit" ) (?\C -g . " :quit" )
116
+ ,@(mapcar (lambda (k ) (cons (string-to-char k) (concat " :" k)))
117
+ command-list))))
118
+ (or (cdr (assq (read-char ) alist))
119
+ (cider--debug-read-command command-list value))))
129
120
130
121
131
122
; ;; User commands
@@ -137,10 +128,7 @@ immediately evaluate the instrumented expression.
137
128
138
129
While debugged code is being evaluated, the user is taken through the
139
130
source code and displayed the value of various expressions. At each step,
140
- the following keys are available:
141
- n: Next step
142
- c: Continue without stopping
143
- i: Inject a value at this point"
131
+ a number of keys will be prompted to the user."
144
132
(interactive )
145
133
(cider--debug-init-connection)
146
134
(let* ((expression (cider-defun-at-point))
0 commit comments