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.
291 lines
11 KiB
291 lines
11 KiB
;; Copyright (C) 2015-2016, 2018 Free Software Foundation, Inc
|
|
|
|
;; Author: Rocky Bernstein <rocky@gnu.org>
|
|
|
|
;; 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 'comint)
|
|
(require 'eshell)
|
|
(require 'load-relative)
|
|
(require-relative-list '("utils" "window") "realgud-")
|
|
(require-relative-list '("buffer/helper") "realgud-buffer-")
|
|
|
|
(declare-function realgud-get-cmdbuf 'realgud-buffer-helper)
|
|
(declare-function realgud-get-srcbuf 'realgud-buffer-helper)
|
|
(declare-function realgud-cmdbuf-info-in-debugger?= 'realgud-command)
|
|
(declare-function realgud-window-cmd-undisturb-src 'realgud-window)
|
|
(declare-function comint-goto-process-mark 'comint)
|
|
(declare-function comint-send-input 'comint)
|
|
(declare-function realgud:canonic-major-mode 'realgud-utils)
|
|
|
|
(defun realgud:send-input ()
|
|
"Sends command buffer line either to comint or eshell"
|
|
(interactive)
|
|
(let ((mode (realgud:canonic-major-mode)))
|
|
(ignore-errors
|
|
(cond ((eq mode 'eshell)
|
|
(eshell-send-input))
|
|
((eq mode 'comint)
|
|
(comint-send-input))
|
|
))))
|
|
|
|
(defun realgud:send-command-common (process command-str)
|
|
"Assume we are in a comint buffer. Insert COMMAND-STR and
|
|
send that input onto the process."
|
|
(if (eq 'run (process-status process))
|
|
(let ((mode (realgud:canonic-major-mode)))
|
|
(cond ((eq mode 'eshell)
|
|
(goto-char eshell-last-output-end)
|
|
(setq eshell-last-output-start
|
|
(setq realgud-last-output-start (point-marker))))
|
|
((eq mode 'comint)
|
|
(comint-check-proc (current-buffer))
|
|
(comint-goto-process-mark)
|
|
(setq comint-last-output-start
|
|
(setq realgud-last-output-start (point-marker)))))
|
|
(insert command-str)
|
|
(realgud:send-input)
|
|
)
|
|
;; else
|
|
(message "Process %s not in `run' state; not issuing %s"
|
|
process command-str)
|
|
)
|
|
)
|
|
|
|
(defalias 'comint-output-filter-orig
|
|
(symbol-function 'comint-output-filter))
|
|
|
|
(defvar realgud-last-output-start)
|
|
(defun fake-output-filter(process string)
|
|
"A process output filter that saves the results into a temporary buffer."
|
|
(with-current-buffer (get-buffer-create "*realgud-process-output-temp*")
|
|
(goto-char (point-max))
|
|
(set (make-local-variable 'realgud-last-output-start)
|
|
(point-marker))
|
|
(insert (concat "\n" string))
|
|
(goto-char (point-max))))
|
|
|
|
(defun realgud-send-command-process (process command-str)
|
|
"Invoke debugger COMMAND adding that command and the
|
|
results into the command buffer."
|
|
(fset 'comint-output-filter (symbol-function 'fake-output-filter))
|
|
(apply comint-input-sender (list process command-str))
|
|
(sit-for 0.25) ;; FIXME with something better
|
|
(fset 'comint-output-filter (symbol-function 'comint-output-filter-orig))
|
|
)
|
|
|
|
;; Here are some other possibilities for functions.
|
|
;; Comint-specific: doesn't insert input into the buffer which is
|
|
;; what gud-call does.
|
|
;; (apply comint-input-sender (list proc command))
|
|
;;
|
|
;; Works on any process-oriented buffer, not just comint.
|
|
;; (process-send-string (get-buffer-process (current-buffer))
|
|
;; (concat command "\n"))
|
|
|
|
|
|
(defun realgud-send-command (command &optional opt-send-fn opt-buffer)
|
|
"Invoke the debugger COMMAND adding that command and the
|
|
results into the command buffer."
|
|
(let* ((cmdbuf (realgud-get-cmdbuf opt-buffer))
|
|
(send-command-fn (or opt-send-fn (function realgud:send-command-common)))
|
|
)
|
|
(if cmdbuf
|
|
(with-current-buffer cmdbuf
|
|
(let ((process (get-buffer-process cmdbuf)))
|
|
(unless process
|
|
(realgud-cmdbuf-info-in-debugger?= nil)
|
|
(error "Command process buffer is not running")
|
|
)
|
|
(if (realgud-sget 'cmdbuf-info 'in-debugger?)
|
|
(funcall send-command-fn process command)
|
|
(error "Command buffer doesn't think a debugger is running - Use `realgud-cmdbuf-toggle-in-debugger?' to toggle")
|
|
)
|
|
))
|
|
(error "Can't find command process buffer")
|
|
)))
|
|
|
|
(defun realgud-send-command-invisible (command-str)
|
|
(realgud-send-command command-str (function realgud-send-command-process)))
|
|
|
|
(defvar realgud-expand-format-overrides nil
|
|
"An alist of overrides for `realgud-expand-format'.
|
|
Each element should have the form (KEY . VALUE). Key should be a
|
|
single-character escape accepted by `realgud-expand-format';
|
|
value should be a string. Every time %KEY is encountered in te
|
|
string, it will be replaced by VALUE instead of being processed
|
|
as usual. If VALUE is nil, the override is ignored.")
|
|
|
|
(defun realgud-expand-format (fmt-str &optional opt-str opt-buffer)
|
|
"Expands commands format characters inside FMT-STR.
|
|
OPT-STR is an optional string (used with %p and %s). Values are
|
|
taken from current buffer, or OPT-BUFFER if non-nil. Some
|
|
%-escapes in the string arguments are expanded. These are:
|
|
|
|
%f -- Name without directory of current source file.
|
|
%F -- Name without directory or extension of current source file.
|
|
%x -- Name of current source file.
|
|
%X -- Expanded name of current source file.
|
|
%U -- Expanded name of current source file stripping file://.
|
|
%d -- Directory of current source file.
|
|
%l -- Number of current source line.
|
|
%c -- Fully qualified class name derived from the expression
|
|
surrounding point.
|
|
%p -- Value of OPT-STR, converted to string using `int-to-string'
|
|
%q -- Value of OPT-STR with string escapes (as ksh, bash, and zsh do).
|
|
%s -- Value of OPT-STR.
|
|
|
|
%p and %s are replaced by an empty string if OPT-STR is nil."
|
|
(let* ((buffer (or opt-buffer (current-buffer)))
|
|
(srcbuf (realgud-get-srcbuf buffer))
|
|
(src-file-name (and srcbuf (buffer-file-name srcbuf)))
|
|
result)
|
|
(while (and fmt-str
|
|
(let ((case-fold-search nil))
|
|
(string-match "\\([^%]*\\)%\\([dfFlpqxUXs]\\)" fmt-str)))
|
|
(let* ((key-str (match-string 2 fmt-str))
|
|
(key (string-to-char key-str)))
|
|
(setq result
|
|
(concat
|
|
result (match-string 1 fmt-str)
|
|
(cond
|
|
((cdr (assq key realgud-expand-format-overrides)))
|
|
((eq key ?d)
|
|
(or (and src-file-name
|
|
(file-name-directory src-file-name))
|
|
"*source-file-not-found-for-%d"))
|
|
((eq key ?f)
|
|
(or (and src-file-name
|
|
(file-name-nondirectory src-file-name))
|
|
"*source-file-not-found-for-%f*"))
|
|
((eq key ?F)
|
|
(or (and src-file-name
|
|
(file-name-sans-extension
|
|
(file-name-nondirectory src-file-name)))
|
|
"*source-file-not-found-for-%F"))
|
|
((eq key ?l)
|
|
(if srcbuf
|
|
(with-current-buffer srcbuf
|
|
(int-to-string
|
|
(save-restriction
|
|
(widen)
|
|
(+ (count-lines (point-min) (point))
|
|
(if (bolp) 1 0)))))
|
|
"source-buffer-not-found-for-%l"))
|
|
|
|
((eq key ?p) (if opt-str (int-to-string opt-str) ""))
|
|
|
|
;; String with escapes. %q follows shell (ksh, bash, zsh)
|
|
;; The other possibility was Python's %r, !r or "repr".
|
|
;; That isn't as perfect a fit though.
|
|
((eq key ?q) (if opt-str
|
|
(let ((print-escape-newlines t))
|
|
(prin1-to-string opt-str))
|
|
""))
|
|
|
|
;; String
|
|
((eq key ?s) (or opt-str ""))
|
|
|
|
((eq key ?x)
|
|
(or (and src-file-name src-file-name)
|
|
"*source-file-not-found-for-%x"))
|
|
|
|
((eq key ?X)
|
|
(or (and src-file-name (expand-file-name src-file-name))
|
|
"*source-file-not-found-for-%X"))
|
|
|
|
((eq key ?U)
|
|
(if (string-match src-file-name "^file://")
|
|
(setq src-file-name (substring src-file-name 7)))
|
|
(or (and src-file-name (expand-file-name src-file-name))
|
|
"*source-file-not-found-for-%X"))
|
|
|
|
;; ((eq key ?e)
|
|
;; (gud-find-expr))
|
|
;; ((eq key ?a)
|
|
;; (gud-read-address))
|
|
;; ((eq key ?c)
|
|
;; (gud-find-class srcbuf))
|
|
|
|
(t key)))))
|
|
(setq fmt-str (substring fmt-str (match-end 2))))
|
|
;; There might be text left in FMT-STR when the loop ends.
|
|
(concat result fmt-str)))
|
|
|
|
(defun realgud-command (fmt &optional arg no-record? frame-switch? realgud-prompts?)
|
|
"Sends a command to the process associated with the command
|
|
buffer of the current buffer. A bit of checking is done before
|
|
sending the command to make sure that we can find a command
|
|
buffer, and that it has a running process associated with it.
|
|
|
|
FMT is a string which may contain format characters that are
|
|
expanded. See `realgud-expand-format' for a list of the format
|
|
characters and their meanings.
|
|
|
|
If NO-RECORD? is set, the command won't be recorded in the
|
|
position history. This is often done in status and information
|
|
gathering or frame setting commands and is generally *not* done
|
|
in commands that continue execution.
|
|
|
|
If FRAME-SWITCH? is set, the fringe overlay array icon is set to
|
|
indicate the depth of the frame.
|
|
|
|
If REALGUD-PROMPTS? is set, then then issuing the command will cause a
|
|
debugger prompt.
|
|
"
|
|
(interactive "sCommand (may contain format chars): ")
|
|
(let* ((command-str (realgud-expand-format fmt arg))
|
|
(cmd-buff (realgud-get-cmdbuf))
|
|
)
|
|
(unless cmd-buff
|
|
(error "Can't find command buffer for buffer %s" (current-buffer)))
|
|
|
|
;; Display the expanded command in the message area unless the
|
|
;; current buffer is the command buffer.
|
|
(unless (realgud-cmdbuf?)
|
|
(message "Command: %s" command-str))
|
|
|
|
(with-current-buffer cmd-buff
|
|
(let* ((process (get-buffer-process cmd-buff))
|
|
(last-output-end (point-marker))
|
|
(in-srcbuf? (realgud-sget 'cmdbuf-info 'in-srcbuf?))
|
|
)
|
|
(unless process
|
|
(error "Can't find process for command buffer %s" cmd-buff))
|
|
(unless (eq 'run (process-status process))
|
|
(error "Process %s isn't running; status %s" process
|
|
(process-status process)))
|
|
|
|
(realgud-cmdbuf-info-no-record?= no-record?)
|
|
(realgud-cmdbuf-info-frame-switch?= frame-switch?)
|
|
|
|
;; Down the line we may handle prompting in a more
|
|
;; sophisticated way. But for now, we handle this by forcing
|
|
;; display of the command buffer.
|
|
(if realgud-prompts? (realgud-window-cmd-undisturb-src nil 't))
|
|
|
|
(realgud-send-command command-str (function realgud:send-command-common))
|
|
|
|
;; Wait for the process-mark to change before changing variables
|
|
;; that effect the hook processing.
|
|
(while (and (eq 'run (process-status process))
|
|
(equal last-output-end (process-mark process)))
|
|
(sit-for 0))
|
|
|
|
;; Reset temporary hook-processing variables to their default state.
|
|
(realgud-cmdbuf-info-no-record?= nil)
|
|
(realgud-cmdbuf-info-frame-switch?= nil)
|
|
))))
|
|
|
|
(provide-me "realgud-")
|