Personal emacs config
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.

326 lines
12 KiB

  1. ;; Copyright (C) 2010-2016 Free Software Foundation, Inc
  2. ;; Author: Rocky Bernstein <rocky@gnu.org>
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;; This program is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; (require 'term)
  12. (require 'comint)
  13. (require 'load-relative)
  14. (require 'loc-changes)
  15. (require-relative-list '("fringe" "helper" "lang" "reset")
  16. "realgud-")
  17. (require-relative-list '("buffer/command" "buffer/source") "realgud-buffer-")
  18. (declare-function comint-exec 'comint)
  19. (declare-function comint-mode 'comint)
  20. (declare-function realgud-bp-remove-icons 'realgud-bp)
  21. (declare-function realgud:suggest-file-from-buffer 'realgud-lang)
  22. (declare-function realgud-cmdbuf-args= 'realgud-buffer-command)
  23. (declare-function realgud-cmdbuf-command-string 'realgud-buffer-command)
  24. (declare-function realgud-cmdbuf-debugger-name 'realgud-buffer-command)
  25. (declare-function realgud-cmdbuf-info-bp-list= 'realgud-buffer-command)
  26. (declare-function realgud-cmdbuf-info-in-debugger?= 'realgud-buffer-command)
  27. (declare-function realgud-cmdbuf-info-starting-directory= 'realgud-buffer-command)
  28. (declare-function realgud-cmdbuf-mode-line-update 'realgud-buffer-command)
  29. (declare-function realgud-cmdbuf? 'realgud-helper)
  30. (declare-function realgud-command-string 'realgud-buffer-command)
  31. (declare-function realgud-fringe-erase-history-arrows 'realgud-buffer-command)
  32. (declare-function realgud-get-cmdbuf 'realgud-helper)
  33. (declare-function realgud:reset 'realgud-reset)
  34. (declare-function realgud-short-key-mode-setup 'realgud-shortkey)
  35. (declare-function realgud-srcbuf-command-string 'realgud-buffer-source)
  36. (declare-function realgud-srcbuf-debugger-name 'realgud-buffer-source)
  37. (declare-function realgud-srcbuf-init 'realgud-buffer-source)
  38. (declare-function realgud-srcbuf? 'realgud-buffer-source)
  39. (declare-function realgud-suggest-lang-file 'realgud-lang)
  40. (defvar realgud-srcbuf-info)
  41. (defvar starting-directory)
  42. (defun realgud:expand-file-name-if-exists (filename)
  43. "Return FILENAME expanded using `expand-file-name' if that name exists.
  44. Otherwise, just return FILENAME."
  45. (let* ((expanded-filename (expand-file-name filename))
  46. (result (cond ((file-exists-p expanded-filename)
  47. expanded-filename)
  48. ('t filename))))
  49. result)
  50. )
  51. (defun realgud-suggest-invocation
  52. (debugger-name _minibuffer-history lang-str lang-ext-regexp
  53. &optional last-resort)
  54. "Suggest a debugger command invocation. If the current buffer
  55. is a source file or process buffer previously set, then use the
  56. value of that the command invocations found by buffer-local
  57. variables. Otherwise, we try to find a suitable program file
  58. using LANG-STR and LANG-EXT-REGEXP."
  59. (let* ((buf (current-buffer))
  60. (filename)
  61. (cmd-str-cmdbuf (realgud-cmdbuf-command-string buf))
  62. )
  63. (cond
  64. ((and cmd-str-cmdbuf (equal debugger-name (realgud-cmdbuf-debugger-name buf)))
  65. cmd-str-cmdbuf)
  66. ((setq filename (realgud:suggest-file-from-buffer lang-str))
  67. (concat debugger-name " " (shell-quote-argument filename)))
  68. (t (concat debugger-name " "
  69. (shell-quote-argument
  70. (realgud-suggest-lang-file lang-str lang-ext-regexp last-resort))))
  71. )))
  72. (defun realgud-query-cmdline
  73. (suggest-invocation-fn
  74. minibuffer-local-map
  75. minibuffer-history
  76. &optional opt-debugger)
  77. "Prompt for a debugger command invocation to run.
  78. Analogous to `gud-query-cmdline'.
  79. If you happen to be in a debugger process buffer, the last command invocation
  80. for that first one suggested. Failing that, some amount of guessing is done
  81. to find a suitable file via SUGGEST-INVOCATION-FN.
  82. We also set filename completion and use a history of the prior
  83. dbgr invocations "
  84. (let ((debugger (or opt-debugger
  85. (realgud-sget 'srcbuf-info 'debugger-name))))
  86. (read-shell-command
  87. (format "Run %s (like this): " debugger) ;; prompt string
  88. (funcall suggest-invocation-fn debugger) ;; initial value
  89. minibuffer-history ;; history variable
  90. )))
  91. (defun realgud-parse-command-arg (args two-args opt-two-args)
  92. "Return a cons node where the car is a list containing the
  93. entire first option and the cdr is the remaining arguments from ARGS.
  94. We determine if an option has length one or two using the lists
  95. TWO-ARGS and OPT-TWO-ARGS. Both of these are list of 'options',
  96. that is strings without the leading dash. TWO-ARGS takes a
  97. mandatory additional argument. OPT-TWO-ARGS might take two
  98. arguments. The rule for an optional argument that we use is if
  99. the next parameter starts with a dash ('-'), it is not part of
  100. the preceeding parameter when that parameter is optional.
  101. NOTE: we don't check whether the first arguments of ARGS is an
  102. option by testing to see if it starts say with a dash. So on
  103. return the first argument is always removed.
  104. "
  105. (let ((arg (car args))
  106. (d-two-args (mapcar (lambda(x) (concat "-" x)) two-args))
  107. (d-opt-two-args (mapcar (lambda(x) (concat "-" x)) opt-two-args))
  108. (remaining (cdr args)))
  109. (cond
  110. ((member arg d-two-args)
  111. (if (not remaining)
  112. (progn
  113. (message "Expecting an argument after %s. Continuing anyway."
  114. arg)
  115. (cons (list arg) (list remaining)))
  116. (cons (list arg (car remaining)) (list (cdr remaining)))))
  117. ((member arg d-opt-two-args)
  118. (if (and remaining (not (string-match "^-" (car remaining))))
  119. (cons (list arg (car remaining)) (list (cdr remaining)))
  120. (cons (list arg) (list remaining))))
  121. (t (cons (list arg) (list remaining))))))
  122. (defun realgud:terminate-srcbuf (&optional srcbuf)
  123. "Resets source buffer."
  124. (interactive "bsource buffer: ")
  125. (if (stringp srcbuf) (setq srcbuf (get-buffer srcbuf)))
  126. (with-current-buffer srcbuf
  127. (realgud-fringe-erase-history-arrows)
  128. (realgud-bp-remove-icons (point-min) (point-max))
  129. (when (realgud-srcbuf?)
  130. (realgud-short-key-mode-setup nil)
  131. (redisplay)
  132. )
  133. (loc-changes-clear-buffer)
  134. ))
  135. (defun realgud:terminate (&optional buf)
  136. "Resets state in all buffers associated with source or command
  137. buffer BUF) This does things like remove fringe arrows breakpoint
  138. icons and resets short-key mode."
  139. (interactive "bbuffer: ")
  140. (if (stringp buf) (setq buf (get-buffer buf)))
  141. (let ((cmdbuf (realgud-get-cmdbuf buf)))
  142. (if cmdbuf
  143. (with-current-buffer cmdbuf
  144. (realgud-cmdbuf-info-in-debugger?= nil)
  145. (realgud-cmdbuf-info-bp-list= '())
  146. (realgud-cmdbuf-mode-line-update)
  147. (realgud-fringe-erase-history-arrows)
  148. (if realgud-cmdbuf-info
  149. (dolist (srcbuf (realgud-cmdbuf-info-srcbuf-list realgud-cmdbuf-info))
  150. (if (realgud-srcbuf? srcbuf)
  151. (with-current-buffer srcbuf
  152. (realgud:terminate-srcbuf srcbuf)
  153. ))
  154. )
  155. )
  156. )
  157. (error "Buffer %s does not seem to be attached to a debugger"
  158. (buffer-name))
  159. )
  160. )
  161. )
  162. (defun realgud:kill-buffer-hook ()
  163. "When a realgud command buffer is killed, call `realgud:terminate' to
  164. clean up.
  165. Note that `realgud-term-sentinel' is not helpful here because
  166. the buffer and data associated with it are already gone."
  167. (when (realgud-cmdbuf?) (realgud:terminate (current-buffer)))
  168. )
  169. (add-hook 'kill-buffer-hook 'realgud:kill-buffer-hook)
  170. (defun realgud-term-sentinel (process string)
  171. "Called when PROCESS dies. We call `realgud:terminate' to clean up."
  172. (let ((cmdbuf (realgud-get-cmdbuf)))
  173. (if cmdbuf (realgud:terminate cmdbuf)))
  174. (message "That's all folks.... %s" string))
  175. (defun realgud:binary (file-name)
  176. "Return a whether FILE-NAME is executable or not or very large"
  177. (let* ((truename (file-chase-links file-name))
  178. (output (shell-command-to-string
  179. (format "file %s" truename)))
  180. (filesize (nth 7 (file-attributes truename)))
  181. )
  182. (cond
  183. ((string-match "ELF" output) t)
  184. ((and large-file-warning-threshold filesize
  185. (> filesize large-file-warning-threshold)) t)
  186. ('t nil))))
  187. (defun realgud-exec-shell (debugger-name script-filename program
  188. &optional no-reset &rest args)
  189. "Run the specified SCRIPT-FILENAME in under debugger DEBUGGER-NAME a
  190. comint process buffer. ARGS are the arguments passed to the
  191. PROGRAM. At the moment, no piping of input is allowed.
  192. SCRIPT-FILENAME will have local variable `realgud-script-info' set
  193. which contains the debugger name and debugger process-command
  194. buffer.
  195. Normally command buffers are reused when the same debugger is
  196. reinvoked inside a command buffer with a similar command. If we
  197. discover that the buffer has prior command-buffer information and
  198. NO-RESET is nil, then that information which may point into other
  199. buffers and source buffers which may contain marks and fringe or
  200. marginal icons is reset."
  201. (let* ((non-nil-filename (or script-filename "+No filename+"))
  202. (current-directory
  203. (or (file-name-directory non-nil-filename)
  204. default-directory "./"))
  205. (cmdproc-buffer-name
  206. (replace-regexp-in-string
  207. "\s+" "\s"
  208. (format "*%s %s shell*"
  209. (file-name-nondirectory debugger-name)
  210. (file-name-nondirectory non-nil-filename))))
  211. (cmdproc-buffer (get-buffer-create cmdproc-buffer-name))
  212. (realgud-buf (current-buffer))
  213. (cmd-args (cons program args))
  214. (process (get-buffer-process cmdproc-buffer)))
  215. (with-current-buffer cmdproc-buffer
  216. ;; If the found command buffer isn't for the same debugger
  217. ;; invocation command, rename that and start a new one.
  218. ;;
  219. ;; For example: "bashdb /tmp/foo" does not match "bashdb
  220. ;; /etc/foo" even though they both canonicalize to the buffer
  221. ;; "*bashdb foo shell*"
  222. (when (and (realgud-cmdbuf?)
  223. (not
  224. (equal cmd-args
  225. (realgud-cmdbuf-info-cmd-args realgud-cmdbuf-info))
  226. ))
  227. (rename-uniquely)
  228. (setq cmdproc-buffer (get-buffer-create cmdproc-buffer-name))
  229. (setq process nil)
  230. ))
  231. (if (and process (eq 'run (process-status process)))
  232. cmdproc-buffer
  233. (with-current-buffer cmdproc-buffer
  234. (and (realgud-cmdbuf?) (not no-reset) (realgud:reset))
  235. (make-local-variable 'starting-directory)
  236. (setq starting-directory current-directory)
  237. (insert "Current directory: " current-directory "\n")
  238. (insert "Command: " (mapconcat 'identity cmd-args " ") "\n")
  239. ;; For term.el
  240. ;; (term-mode)
  241. ;; (set (make-local-variable 'term-term-name) realgud-term-name)
  242. ;; (make-local-variable 'realgud-parent-buffer)
  243. ;; (setq realgud-parent-buffer realgud-buf)
  244. ;; For comint.el.
  245. (comint-mode)
  246. ;; Making overlay-arrow-variable-list buffer local has to be
  247. ;; done after running commint mode. FIXME: find out why and if
  248. ;; this reason is justifyable. Also consider moving this somewhere
  249. ;; else.
  250. (make-local-variable 'overlay-arrow-variable-list)
  251. (make-local-variable 'realgud-overlay-arrow1)
  252. (make-local-variable 'realgud-overlay-arrow2)
  253. (make-local-variable 'realgud-overlay-arrow3)
  254. (condition-case failure
  255. (comint-exec cmdproc-buffer debugger-name program nil args)
  256. (error
  257. (let ((text (format "%S\n" failure)))
  258. (insert text)
  259. (message text)(sit-for 1)
  260. text)))
  261. (setq process (get-buffer-process cmdproc-buffer))
  262. (if (and process (eq 'run (process-status process)))
  263. (let ((src-buffer)
  264. (cmdline-list (cons program args)))
  265. ;; is this right?
  266. (when (and script-filename (file-exists-p script-filename)
  267. (not (realgud:binary script-filename)))
  268. (setq src-buffer (find-file-noselect script-filename))
  269. (point-max)
  270. (realgud-srcbuf-init src-buffer cmdproc-buffer))
  271. (process-put process 'buffer cmdproc-buffer))
  272. ;; else
  273. (let ((text
  274. (format
  275. "Failed to invoke debugger %s on program %s with args %s\n"
  276. debugger-name program (mapconcat 'identity args " "))))
  277. (with-current-buffer cmdproc-buffer (insert text))
  278. (message text)
  279. ))
  280. cmdproc-buffer))))
  281. ;; Start of a term-output-filter for term.el
  282. (defun realgud-term-output-filter (process string)
  283. (let ((process-buffer (process-get process 'buffer)))
  284. (if process-buffer
  285. (save-current-buffer
  286. (set-buffer process-buffer)
  287. ;; (insert-before-markers (format "+++1 %s" string))
  288. (insert-before-markers string)))))
  289. (provide-me "realgud-")