forked from abo-abo/matlab-mode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
matlab-debug.el
169 lines (145 loc) · 5.3 KB
/
matlab-debug.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
;;; matlab-debug.el --- Debugger integration
;; Copyright (C) 2016 Oleh Krehel
;; This file 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, or (at your option)
;; any later version.
;; This program 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.
;; For a full copy of the GNU General Public License
;; see <http://www.gnu.org/licenses/>.
;;; Code:
;;* dbstop if error
(defconst matlab-dbstatus-header
(propertize "dbstatus:" 'face 'font-lock-keyword-face))
(defun matlab-dbstatus ()
"Return pretty-printed \"dbstatus\"."
(interactive)
(let ((strs (cdr (split-string (matlab-eval "dbstatus") "\n" t))))
(unless strs
(setq strs '("none")))
(mapconcat #'identity (cons matlab-dbstatus-header strs)
"\n ")))
(defun matlab-dbstop-if-error ()
"Toggle \"dbstop if error\"."
(interactive)
(let ((status (matlab-eval "dbstatus")))
(if (string-match-p "^Stop if error" status)
(matlab-eval "dbclear if error")
(matlab-eval "dbstop if error")))
(when (called-interactively-p 'any)
(message
(matlab-dbstatus))))
(defun matlab-dbstop-if-caught-error ()
"Toggle \"dbstop if caught error\"."
(interactive)
(let ((status (matlab-eval "dbstatus")))
(if (string-match-p "^Stop if caught error" status)
(matlab-eval "dbclear if caught error")
(matlab-eval "dbstop if caught error")))
(when (called-interactively-p 'any)
(message
(matlab-dbstatus))))
(defhydra hydra-matlab-dbstatus (:color pink
:columns 1)
"
%s(matlab-dbstatus)
"
("e" (matlab-dbstop-if-error) "dbstop if error")
("c" (matlab-dbstop-if-caught-error) "dbstop if caught error")
("q" nil "quit"))
;;* Breakpoint in fringe
(defun matlab-dbg-breakpoint-add (point)
(gdb-put-string nil point `(left-fringe breakpoint breakpoint-enabled))
(let ((file (buffer-file-name))
(line (line-number-at-pos)))
(matlab-eval (format "dbstop in %s at %d" file line))))
(defun matlab-dbg-breakpoint-remove (posn)
(with-selected-window (posn-window posn)
(let ((pt (posn-point posn))
(file (buffer-file-name))
(line (line-number-at-pos)))
(gdb-remove-strings pt (1+ pt))
(matlab-eval (format "dbclear in %s at %d" file line)))))
(defun matlab-dbg-breakpoint-toggle (event)
(interactive "e")
(mouse-minibuffer-check event)
(let ((posn (event-end event)))
(with-selected-window (posn-window posn)
(if (buffer-file-name)
(if (numberp (posn-point posn))
(save-excursion
(goto-char (posn-point posn))
(if (or (posn-object posn)
(memq (car (fringe-bitmaps-at-pos (posn-point posn)))
'(breakpoint)))
(matlab-dbg-breakpoint-remove posn)
(matlab-dbg-breakpoint-add (posn-point posn))))))
(posn-set-point posn))))
;;* Misc debug
(defun matlab-debug-goto ()
"When in debugger, to to the top of \"dbstack\"."
(interactive)
(let ((stack (matlab-eval "dbstack")))
(when (string-match "In \\(.*\\) (line \\([0-9]+\\))$" stack)
(let* ((file (match-string 1 stack))
(line (match-string 2 stack))
(full-file (matlab-eval (format "which('%s')" file))))
(if (file-exists-p full-file)
(progn
(setq matlab-debug-current-file full-file)
(find-file-other-window full-file)
(goto-char (point-min))
(forward-line (string-to-number line)))
(error "MATLAB requested file %s but it does not exist" full-file))))))
(defun matlab-debug-dbstep (arg)
"When in debugger, to to the top of \"dbstack\"."
(interactive "p")
(let* ((res (matlab-eval (format "dbstep %d" arg)))
(line-number (read res)))
(with-current-buffer (find-file-noselect matlab-debug-current-file)
(goto-char (point-min))
(forward-line (1- line-number)))))
(defun matlab-dbstep-in ()
(interactive)
(matlab-eval "dbstep in;dbhotlink(1);"))
(defun matlab-dbcont ()
(interactive)
(matlab-eval "dbcont"))
(defun matlab-dbquit ()
(interactive)
(matlab-eval "dbquit"))
(defun matlab-dbup ()
(interactive)
(matlab-eval "dbup"))
(defun matlab-dbdown ()
(interactive)
(matlab-eval "dbdown"))
(defun matlab-eval-variable ()
(interactive)
(let ((vars
(delete
"em_who"
(split-string (matlab-eval "em_who") "\n" t))))
(ivy-read "var: " vars
:action
(lambda (x)
(message (matlab-eval x))))))
(defhydra hydra-matlab (:color pink
:exit t)
"mat"
("e" hydra-matlab-dbstatus/body "on error")
("d" hydra-matlab-debug/body "debug")
("q" nil "quit"))
(defhydra hydra-matlab-debug (:color pink)
"db"
("S" matlab-dbstatus "status")
("l" matlab-debug-goto "goto line")
("j" matlab-debug-dbstep "dbstep")
("e" matlab-eval-variable "eval")
("g" (matlab-eval "dbcont") "dbcont" :exit t)
("Q" (matlab-eval "dbquit") "dbquit" :exit t)
("q" nil "quit"))
(provide 'matlab-debug)