matlab-shell-gud.el:
(gud-matlab-marker-filter): Remove old hotlink url output scanning. Replace with evaluating forms sent from MATLAB. When exiting debug mode, also find and close the stack window. (mlg-set-stack-frame-via-gud): New, called from MATLAB. (mlg-stack-quit): New for stack mode. Replaces 'delete-window which sometimes fails. (matlab-shell-gud-minor-mode-map): Add 'v' binding to view stack frame window. (easy-menu-define): Add "Show Stack" menu item to show stack window. toolbox/+emacs/@Stack/Stack.m: Add `StackPending' and `FramePending' flags for when that part changes. (captureStack): New method - uses what was in updateEmacs for computing the part of the stack we will use. (updateEmacs): Remove chunk, put in above. Always post the request to show, as this is used from ebstack, and it should always do something. (updateForHotLinks): New method, called from dbhotlinks. Sends over stack only if needed. (stackEqual): Rename output arg to better indicate what it is. toolbox/dbhotlink.m: Remove most of the content. Replace with use of EmacsStack object, using updateForHotLinks method.
This commit is contained in:
parent
3330f03f3d
commit
aef2037284
|
@ -187,19 +187,6 @@ FILE is ignored, and ARGS is returned."
|
|||
;; DEBUG PROMPTS
|
||||
(when (string-match gud-matlab-marker-regexp-K>> gud-marker-acc)
|
||||
|
||||
;; Look for any frames for case of a debug prompt.
|
||||
(let ((url gud-marker-acc)
|
||||
ef el)
|
||||
|
||||
;; We use dbhotlinks to create the below syntax. If we see it we have a frame,
|
||||
;; and should tell gud to go there.
|
||||
|
||||
(when (string-match "opentoline('\\([^']+\\)',\\([0-9]+\\),\\([0-9]+\\))" url)
|
||||
(setq ef (substring url (match-beginning 1) (match-end 1))
|
||||
el (substring url (match-beginning 2) (match-end 2)))
|
||||
|
||||
(setq frame (cons ef (string-to-number el)))))
|
||||
|
||||
;; Newer MATLAB's don't print useful info. We'll have to
|
||||
;; search backward for the previous line to see if a frame was
|
||||
;; displayed.
|
||||
|
@ -232,7 +219,28 @@ FILE is ignored, and ARGS is returned."
|
|||
|
||||
;; (when matlab-shell-io-testing (message "!!xx [%s]" (substring gud-marker-acc 0 endprompt)))
|
||||
|
||||
;; We're done with the text! Remove it from the accumulator.
|
||||
;; We're done with the text!
|
||||
;; Capture the text that describes the new stack frame.
|
||||
(save-match-data
|
||||
(let* ((expr-end (match-beginning 0))
|
||||
(m1 (string-match "dbhotlink()%%%\n" gud-marker-acc))
|
||||
(expr-start (match-end 0))
|
||||
(expression (substring gud-marker-acc expr-start expr-end)))
|
||||
|
||||
(when (> (length expression) 0)
|
||||
(condition-case ERR
|
||||
(let ((forms (read expression)))
|
||||
(when forms
|
||||
;;(message "About to evaluate forms: \"%S\"" forms)
|
||||
(eval forms)))
|
||||
(error
|
||||
(message "Failed to evaluate dbhotlink expression: \"%s\"" expression)
|
||||
(message "Error is: %S" ERR)
|
||||
)
|
||||
))
|
||||
))
|
||||
|
||||
;;Remove it from the accumulator.
|
||||
(setq gud-marker-acc (substring gud-marker-acc endprompt))
|
||||
;; If we got all this at the same time, push output back onto the accumulator for
|
||||
;; the next code bit to push it out.
|
||||
|
@ -276,9 +284,18 @@ FILE is ignored, and ARGS is returned."
|
|||
(if (and (string-match (concat gud-matlab-marker-regexp->> "\\s-*$") output)
|
||||
gud-last-last-frame)
|
||||
(progn
|
||||
;; Clean up gud stuff.
|
||||
(setq overlay-arrow-position nil
|
||||
gud-last-last-frame nil
|
||||
gud-overlay-arrow-position nil)
|
||||
;; If stack is showing, clean it up.
|
||||
(let* ((buff (mlg-set-stack nil))
|
||||
(win (get-buffer-window buff)))
|
||||
(when win
|
||||
(select-window win)
|
||||
(mlg-stack-quit)
|
||||
))
|
||||
;; Refresh stuff
|
||||
(sit-for 0)
|
||||
))
|
||||
|
||||
|
@ -352,6 +369,7 @@ LONGESTNAME specifies the how long the longest name we can expect is."
|
|||
mlg-stack))
|
||||
(setq mlg-stack (nreverse mlg-stack))
|
||||
(mlg-refresh-stack-buffer)
|
||||
;;(message "Updated Stack")
|
||||
)
|
||||
|
||||
(defun mlg-set-stack-frame (newframe)
|
||||
|
@ -361,6 +379,17 @@ LONGESTNAME specifies the how long the longest name we can expect is."
|
|||
(mlg-show-frame newframe)
|
||||
)
|
||||
|
||||
(defun mlg-set-stack-frame-via-gud (newframe)
|
||||
"Specify a NEWFRAME provided by MATLAB we should visit."
|
||||
(setq mlg-frame newframe)
|
||||
(let ((file (oref (nth (1- newframe) mlg-stack) file))
|
||||
(line (oref (nth (1- newframe) mlg-stack) line)))
|
||||
(if (< line 0) (setq line (- line)))
|
||||
(setq gud-last-frame (cons file line))
|
||||
;;(message "Gud FRAME set to %S" gud-last-frame)
|
||||
)
|
||||
)
|
||||
|
||||
(defun mlg-show-frame (&optional frame)
|
||||
"Setup windows to show FRAME from the current stack frame."
|
||||
(let ((newframe (or frame mlg-frame)))
|
||||
|
@ -431,7 +460,7 @@ LONGESTNAME specifies the how long the longest name we can expect is."
|
|||
(defvar mlg-stack-mode-map
|
||||
(let ((km (make-sparse-keymap)))
|
||||
(define-key km [return] 'mlg-stack-choose)
|
||||
(define-key km "q" 'delete-window)
|
||||
(define-key km "q" 'mlg-stack-quit)
|
||||
(define-key km "n" 'mlg-stack-next)
|
||||
(define-key km "p" 'mlg-stack-prev)
|
||||
(define-key km [mouse-2] 'mlg-stack-click)
|
||||
|
@ -453,6 +482,13 @@ Commands:
|
|||
(setq buffer-read-only t)
|
||||
)
|
||||
|
||||
(defun mlg-stack-quit ()
|
||||
"Quit the MATLAB stack view."
|
||||
(interactive)
|
||||
(if (= (length (window-list)) 1)
|
||||
(bury-buffer)
|
||||
(delete-window (selected-window))))
|
||||
|
||||
(defun mlg-stack-next ()
|
||||
"Visit stack on next line."
|
||||
(interactive)
|
||||
|
@ -682,6 +718,7 @@ Call debug activate/deactivate features."
|
|||
(define-key km "d" 'gud-down)
|
||||
(define-key km "<" 'gud-up)
|
||||
(define-key km ">" 'gud-down)
|
||||
(define-key km "v" 'mlg-show-stack)
|
||||
(define-key km "p" 'matlab-shell-gud-show-symbol-value)
|
||||
;; (define-key km "p" gud-print)
|
||||
|
||||
|
@ -717,8 +754,11 @@ Call debug activate/deactivate features."
|
|||
["dbcont" gud-cont
|
||||
:active (matlab-shell-active-p)
|
||||
:help "When MATLAB debugger is active, run to next break point or finish"]
|
||||
["Show Stack" mlg-show-stack
|
||||
:active (matlab-any-shell-active-p)
|
||||
:help "When MATLAB debugger is active, show value of the symbol under point."]
|
||||
["Show symbol value" matlab-shell-gud-show-symbol-value
|
||||
:active (matlab-shell-active-p)
|
||||
:active (matlab-any-shell-active-p)
|
||||
:help "When MATLAB debugger is active, show value of the symbol under point."]
|
||||
["dbquit" gud-finish
|
||||
:active (matlab-shell-active-p)
|
||||
|
|
|
@ -4,9 +4,12 @@ classdef Stack < handle
|
|||
properties
|
||||
% Stack last sent to Emacs
|
||||
EmacsStack = [];
|
||||
EmacsFrame = [];
|
||||
EmacsFrame = 1;
|
||||
% Netshell object if we should direct that way instead.
|
||||
NetShellObject = [];
|
||||
% Flag - do we need to tell Emacs what changed?
|
||||
StackPending = false;
|
||||
FramePending = false;
|
||||
end
|
||||
|
||||
methods
|
||||
|
@ -17,10 +20,10 @@ classdef Stack < handle
|
|||
es.resetEmacs();
|
||||
end
|
||||
|
||||
function updateEmacs(es, newstack, newframe)
|
||||
% Update Emacs' view of the stack
|
||||
|
||||
if ~isempty(newstack) && strcmp(newstack(1).name, 'ebstack')
|
||||
function captureStack(es, newstack, newframe)
|
||||
if ~isempty(newstack) && ...
|
||||
( strcmp(newstack(1).name, 'ebstack') ||...
|
||||
strcmp(newstack(1).name, 'dbhotlink') )
|
||||
newstack = newstack(2:end);
|
||||
end
|
||||
|
||||
|
@ -40,20 +43,41 @@ classdef Stack < handle
|
|||
|
||||
if ~stackEqual(es.EmacsStack, newstack)
|
||||
es.EmacsStack = newstack;
|
||||
es.StackPending = true;
|
||||
end
|
||||
|
||||
str = [ '(progn ' newline ...
|
||||
stackFrames(newstack) ...
|
||||
newline ...
|
||||
' (mlg-set-stack-frame ' num2str(newframe) ')' ...
|
||||
')'];
|
||||
if newframe ~= es.EmacsFrame
|
||||
es.EmacsFrame = newframe;
|
||||
es.FramePending = true;
|
||||
end
|
||||
end
|
||||
|
||||
if isempty(es.NetShellObject)
|
||||
disp('<EMACSCAP>(eval)');
|
||||
disp(str);
|
||||
disp('</EMACSCAP>')
|
||||
else
|
||||
es.NetShellObject.SendEval(str);
|
||||
end
|
||||
function updateEmacs(es, newstack, newframe)
|
||||
% Update Emacs' view of the stack
|
||||
|
||||
es.captureStack(newstack, newframe);
|
||||
|
||||
str = [ '(progn ' newline ];
|
||||
|
||||
if es.StackPending
|
||||
str = [ str ...
|
||||
stackFrames(es.EmacsStack) ...
|
||||
newline ];
|
||||
end
|
||||
str = [ str ...
|
||||
' (mlg-set-stack-frame ' num2str(es.EmacsFrame) ')' ];
|
||||
|
||||
str = [ str ')'];
|
||||
|
||||
es.StackPending = false;
|
||||
es.FramePending = false;
|
||||
|
||||
if isempty(es.NetShellObject)
|
||||
disp('<EMACSCAP>(eval)');
|
||||
disp(str);
|
||||
disp('</EMACSCAP>')
|
||||
else
|
||||
es.NetShellObject.SendEval(str);
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -61,6 +85,35 @@ classdef Stack < handle
|
|||
function resetEmacs(es)
|
||||
end
|
||||
|
||||
function updateForHotLinks(es, newstack, newframe)
|
||||
|
||||
es.captureStack(newstack, newframe);
|
||||
|
||||
% updateEmacs(es, newstack, newframe);
|
||||
|
||||
str = [ '(progn ' newline ];
|
||||
|
||||
if es.StackPending
|
||||
str = [ str ...
|
||||
stackFrames(es.EmacsStack) ...
|
||||
newline ];
|
||||
end
|
||||
str = [ str ...
|
||||
' (mlg-set-stack-frame-via-gud ' num2str(es.EmacsFrame) ')' ];
|
||||
|
||||
str = [ str ')'];
|
||||
|
||||
es.StackPending = false;
|
||||
es.FramePending = false;
|
||||
|
||||
if isempty(es.NetShellObject)
|
||||
disp(str);
|
||||
else
|
||||
es.NetShellObject.SendEval(str);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -83,18 +136,18 @@ function nf = fixFile(filename)
|
|||
|
||||
end
|
||||
|
||||
function changed = stackEqual(stack1, stack2)
|
||||
changed = true;
|
||||
function thesame = stackEqual(stack1, stack2)
|
||||
thesame = true;
|
||||
|
||||
if length(stack1) ~= length(stack2)
|
||||
changed=false;
|
||||
thesame=false;
|
||||
return;
|
||||
end
|
||||
|
||||
for i=1:length(stack1)
|
||||
if ~strcmp(stack1(i).name, stack2(i).name) || ...
|
||||
stack1(i).line ~= stack2(i).line
|
||||
changed = false;
|
||||
thesame = false;
|
||||
return
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
function dbhotlink(L)
|
||||
function dbhotlink()
|
||||
% Display text that EMACS can interpret as a hotlink
|
||||
% so the debugger can auto move to the right spot.
|
||||
% Input L is the stack frame to specify.
|
||||
|
@ -6,15 +6,6 @@ function dbhotlink(L)
|
|||
|
||||
[ST, I] = dbstack('-completenames');
|
||||
|
||||
if nargin == 0
|
||||
L = I;
|
||||
LINESTR = '';
|
||||
else
|
||||
LINESTR = num2str(L);
|
||||
end
|
||||
|
||||
if L+1 <=numel(ST)
|
||||
fprintf('<a href="matlab: opentoline(''%s'',%i,1)">%i</a>\n', ST(L+1).file, ...
|
||||
ST(L+1).line, LINESTR);
|
||||
end
|
||||
es = getappdata(groot, 'EmacsStack');
|
||||
es.updateForHotLinks(ST, I);
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue