You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
;;; Breakpoint buffer
;; Author: Rocky Bernstein <rocky@gnu.org>
;; Copyright (C) 2019 Free Software Foundation, Inc
;; This program 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 of the;; License, 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.
;; You should have received a copy of the GNU General Public License;; along with this program. If not, see;; <http://www.gnu.org/licenses/>.
(require 'ansi-color)(require 'ring)(require 'seq)(require 'load-relative)(eval-when-compile (require 'cl-lib))(require-relative-list '("../key" "helper" "../follow" "../loc") "realgud-")
(require-relative-list '("command") "realgud-buffer-")
(declare-function realgud-breakpoint-mode 'realgud-breakpoint-mod)(declare-function realgud-get-buffer-base-name 'realgud-buffer-backtrace)(declare-function realgud-cmdbuf-debugger-name 'realgud-buffer-command)(declare-function realgud-cmdbuf? 'realgud-buffer-command)(declare-function realgud-cmdbuf-info-bkpt-buf= 'realgud-buffer-command)(declare-function realgud-cmdbuf-info-divert-output?= 'realgud-buffer-command)(declare-function realgud-cmdbuf-info-in-srcbuf?= 'realgud-buffer-command)(declare-function realgud:cmd-breakpoint 'realgud-cmds)(declare-function realgud:cmd-info-breakpoints 'realgud-cmds)(declare-function realgud-cmdbuf-pat 'realgud-buffer-command)(declare-function realgud-get-cmdbuf 'realgud-buffer-helper)(declare-function realgud:file-loc-from-line 'realgud-file)(declare-function realgud-loc-goto 'realgud-loc)(declare-function buffer-killed? 'realgud-helper)(declare-function realgud:loc-describe 'realgud-loc)
(cl-defstruct realgud-breakpoint-info "debugger object/structure specific to a (top-level) program to be debugged." (cmdbuf nil) ;; buffer of the associated debugger process (cur-pos 0) ;; beakpoint we are at breakpoint-ring ;; ring of marks in buffer of breakpoint numbers. The ;; text at that marker has additional properties about the ;; breakpoint)
(declare-function realgud:cmd-frame 'realgud-buffer-command)(declare-function realgud-get-cmdbuf(&optional opt-buffer))(declare-function realgud-command 'realgud-send)
(make-variable-buffer-local (defvar realgud-breakpoint-info))
;: FIXME: not picked up from track. Why?(defvar realgud-track-divert-string nil)
(defvar realgud-goto-entry-acc "")
(defun realgud:breakpoint-describe (&optional buffer) (interactive "") (unless buffer (setq buffer (current-buffer))) (with-current-buffer buffer (let ((breakpoints (realgud-breakpoint-info-breakpoint-ring realgud-breakpoint-info)) (brkpt) (loc) (i 0)) (switch-to-buffer (get-buffer-create "*Describe Breakpoints*")) (while (and (< i (ring-length breakpoints)) (setq brkpt (ring-ref breakpoints i))) (insert (format "*** %d\n" i)) (insert (format "%s\n" brkpt)) (when (markerp brkpt) (with-current-buffer (marker-buffer brkpt) (goto-char brkpt) (setq loc (get-text-property (point) 'loc)) ) (when loc (realgud:loc-describe loc))) (setq i (1+ i)) ) ) ))
;; FIXME: create this in a new frame.(defun realgud:breakpoint-init () (interactive) (let ((buffer (current-buffer)) (cmdbuf (realgud-get-cmdbuf)) (process) ) (with-current-buffer-safe cmdbuf (let ((brkpt-pat (realgud-cmdbuf-pat "debugger-breakpoint")) (brkpt-pos-ring) (bp-list (realgud-cmdbuf-info-bp-list realgud-cmdbuf-info)) (sleep-count 0) ) (unless brkpt-pat (error "No 'debugger-breakpoint' regular expression recorded for debugger %s" (realgud-cmdbuf-debugger-name))) (setq process (get-buffer-process (current-buffer))) (realgud-cmdbuf-info-in-srcbuf?= (not (realgud-cmdbuf? buffer))) (realgud-cmdbuf-info-divert-output?= t) (setq realgud-track-divert-string nil) (realgud:cmd-info-breakpoints) (while (and (eq 'run (process-status process)) (null realgud-track-divert-string) (> 1000 (setq sleep-count (1+ sleep-count)))) (sleep-for 0.001) ) (if (>= sleep-count 1000) (message "Timeout on running debugger command") ;; else ;; (message "+++4 %s" realgud-track-divert-string) (let ((brkpt-buffer (get-buffer-create (format "*Breakpoint %s*" (realgud-get-buffer-base-name (buffer-name))))) (divert-string realgud-track-divert-string) ) (realgud-cmdbuf-info-brkpt-buf= brkpt-buffer) (with-current-buffer brkpt-buffer (setq buffer-read-only nil) (delete-region (point-min) (point-max)) (if divert-string (let* ((duple (realgud:breakpoint-add-text-properties brkpt-pat cmdbuf divert-string bp-list)) (string-with-props (ansi-color-filter-apply (car duple))) (brkpt-num-pos-list (cadr duple)) ) (insert string-with-props) ;; add marks for each position (realgud-breakpoint-mode cmdbuf) (setq brkpt-pos-ring (make-ring (length brkpt-num-pos-list))) (dolist (pos brkpt-num-pos-list) (goto-char (1+ pos)) (ring-insert-at-beginning brkpt-pos-ring (point-marker)) ) ) ) ;; realgud-breakpoint-mode kills all local variables so ;; we set this after. Alternatively change realgud-breakpoint-mode. (set (make-local-variable 'realgud-breakpoint-info) (make-realgud-breakpoint-info :cmdbuf cmdbuf :breakpoint-ring brkpt-pos-ring )) ) ) ) ) ) (unless cmdbuf (message "Unable to find debugger command buffer for %s" buffer)) ) )
(defun realgud-breakpoint? ( &optional buffer) "Return true if BUFFER is a debugger command buffer." (with-current-buffer-safe (or buffer (current-buffer)) (realgud-breakpoint-info-set?)))
(defalias 'realgud-breakpoint-info? 'realgud-breakpoint-info-p)
(defun realgud-breakpoint-info-set? () "Return true if realgud-breakpoint-info is set." (and (boundp 'realgud-breakpoint-info) realgud-breakpoint-info (realgud-breakpoint-info? realgud-breakpoint-info)))
(defun realgud-goto-entry-n () "Go to an entry number.
Breakpoints, Display expressions and Stack Frames all havenumbers associated with them which are distinct from linenumbers. In a secondary buffer, this function is usually bound toa numeric key which will position you at that entry number. Togo to an entry above 9, just keep entering the number. Forexample, if you press 1 and then 9, you should jump to entry1 (if it exists) and then 19 (if that exists). Entering anynon-digit will start entry number from the beginning again."
(interactive) (if (not (eq last-command 'realgud-goto-entry-n)) (setq realgud-goto-entry-acc "")) (realgud-goto-entry-n-internal (this-command-keys)))
(defun realgud-goto-breakpoint () "Go to the breakpoint number. We get the breakpoint number from the
'brkpt-num property"
(interactive) (if (realgud-breakpoint?) (let ((loc (get-text-property (point) 'loc))) (if loc (realgud-loc-goto loc) (message "No location property found at this point") ) ) ) )
(defun realgud-goto-breakpoint-mouse (event) (interactive "e") (let* ((pos (posn-point (event-end event))) (loc (get-text-property pos 'loc))) (if (realgud-breakpoint?) (if loc (realgud-loc-goto loc) (message "No location property found at this point") ) ) ))
(defun realgud-goto-breakpoint-n () "Goto breakpoint number indicated by the accumulated numeric keys just entered.
This function is usually bound to a numeric key in a 'frame'secondary buffer. To go to an entry above 9, just keep enteringthe number. For example, if you press 1 and then 9, frame 1 is selected\(if it exists) and then frame 19 (if that exists). Entering anynon-digit will start entry number from the beginning again."
(interactive) (if (not (eq last-command 'realgud-goto-breakpoint-n)) (setq realgud-goto-entry-acc "")) (realgud-goto-breakpoint-n-internal (this-command-keys)))
(defun realgud-goto-breakpoint-n-internal (keys) (if (and (stringp keys) (= (length keys) 1)) (progn (setq realgud-goto-entry-acc (concat realgud-goto-entry-acc keys)) ;; Try to find the longest suffix. (let ((acc realgud-goto-entry-acc)) (while (not (string= acc "")) (if (not (realgud-goto-entry-try acc)) (setq acc (substring acc 1)) (realgud:cmd-frame (string-to-number acc)) ;; Break loop. (setq acc ""))))) (message "`realgud-goto-breakpoint-n' must be bound to a number key")))
(defun realgud:breakpoint-add-text-properties(brkpt-pat cmdbuf string bp-list) "Parse STRING or the current buffer and add frame properties: breakpoint number,
filename, and line number as text properties."
(let* ((stripped-string (ansi-color-filter-apply string)) (brkpt-regexp (realgud-loc-pat-regexp brkpt-pat)) (brkpt-group-pat (realgud-loc-pat-num brkpt-pat)) (file-group-pat (realgud-loc-pat-file-group brkpt-pat)) (line-group-pat (realgud-loc-pat-line-group brkpt-pat)) (alt-brkpt-num -1) (last-pos 0) (selected-brkpt-num nil) (brkpt-num-pos-list '()) ) (while (string-match brkpt-regexp stripped-string last-pos) (let ((brkpt-num-str) (brkpt-num) (line-num) (filename) (loc) ;; From https://github.com/realgud/realgud/pull/192 ;; Each brkpt of breakpoint is searched via string-match ;; invocation and a position of the current brkpt is ;; updated via (setq last-pos (match-end 0)) in the end of ;; the loop. But somewhere in the body of the loop (I do ;; not know exactly where), there is another call to ;; string-match and it messes up all positions. (whole-match-begin (match-beginning 0)) (whole-match-end (match-end 0)) (brkpt-num-pos)
) (if brkpt-group-pat (progn (setq brkpt-num-str (substring stripped-string (match-beginning brkpt-group-pat) (match-end brkpt-group-pat))) (setq brkpt-num (string-to-number brkpt-num-str)) (setq loc (seq-find (lambda (elt) (equal brkpt-num (realgud-loc-num elt))) bp-list)) (setq brkpt-num-pos (match-beginning brkpt-group-pat)) (cl-pushnew brkpt-num-pos brkpt-num-pos-list) (when loc (add-text-properties (match-beginning brkpt-group-pat) (match-end brkpt-group-pat) (list 'mouse-face 'highlight 'help-echo "mouse-2: goto this brkpt" 'mark (realgud-loc-marker loc)) string)) ) ; else (progn (setq brkpt-num-str (substring stripped-string (match-beginning 0) (match-end 0))) (setq brkpt-num (cl-incf alt-brkpt-num)) (setq brkpt-num-pos (match-beginning 0)) (cl-pushnew brkpt-num-pos brkpt-num-pos-list) (add-text-properties (match-beginning 0) (match-end 0) (list 'mouse-face 'highlight 'help-echo "mouse-2: goto this brkpt" 'brkpt brkpt-num) string) ) ) (when file-group-pat (setq filename (substring stripped-string (match-beginning file-group-pat) (match-end file-group-pat))) (add-text-properties (match-beginning file-group-pat) (match-end file-group-pat) (list 'mouse-face 'highlight 'help-echo "mouse-2: goto this file" 'action 'realgud:follow-event 'file filename) string) ) (when line-group-pat (let ((line-num-str (substring stripped-string (match-beginning line-group-pat) (match-end line-group-pat)))) (setq line-num (string-to-number (or line-num-str "1"))) ))
(when (and (stringp filename) (numberp line-num)) (let ((loc (realgud:file-loc-from-line filename line-num cmdbuf))) (put-text-property whole-match-begin whole-match-end 'mark loc string) )) (put-text-property whole-match-begin whole-match-end 'brkpt-num brkpt-num string) (setq last-pos whole-match-end) ))
(list string (nreverse brkpt-num-pos-list)) ) )
(provide-me "realgud-buffer-")
|