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.

220 lines
8.0 KiB

  1. ;; Copyright (C) 2015-2017 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. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ; (require 'term)
  14. (require 'cl-lib)
  15. (require 'shell)
  16. (require 'load-relative)
  17. (require-relative-list '("core" "track" "utils") "realgud-")
  18. (require-relative-list '("buffer/command") "realgud-buffer-")
  19. (declare-function realgud-cmdbuf-info-in-debugger?= 'realgud-buffer-command)
  20. (declare-function realgud-cmdbuf-info-cmd-args= 'realgud-buffer-command)
  21. (declare-function realgud:track-set-debugger 'realgud-track)
  22. (declare-function realgud-cmdbuf-info-starting-directory= 'realgud-buffer-command)
  23. (declare-function realgud-parse-command-arg 'realgud-core)
  24. (declare-function realgud:expand-file-name-if-exists 'realgud-core)
  25. (declare-function realgud:flatten 'realgud-utils)
  26. (defvar starting-directory)
  27. (defun realgud:parse-cmd-args(args two-args opt-two-args interp-regexp debugger-regexp
  28. path-args-list annotate-args)
  29. "Parse command line ARGS for the annotate level and name of script to debug.
  30. ARGS should contain a tokenized list of the command line to run.
  31. We return the a list containing:
  32. * the command processor (e.g. bash) and it's arguments if any - a list of strings
  33. * the name of the debugger given (e.g. bashdb) and its arguments - a list of strings.
  34. If there is no debugger, for example gdb, nodejs then nil is returned.
  35. * the script name and its arguments - list of strings
  36. * whether the annotate or emacs option was given ('-A', '--annotate' or '--emacs) - a boolean
  37. The script name and options mentioning paths are file expanded
  38. For example for the following input
  39. (map 'list 'symbol-name
  40. '(bash --norc bashdb -l . --emacs ./gcd.sh a b))
  41. we might return:
  42. ((\"bash\" \"--norc\") (\"bashdb\" \"-l\" \"/tmp\" \"--emacs\") (\"/tmp/gcd.sh\" \"a\" \"b\") t)
  43. Note that path elements have been expanded via `expand-file-name'.
  44. "
  45. ;; Parse the following kind of pattern:
  46. ;; [bash bash-options] bashdb bashdb-options script-name script-options
  47. (let (
  48. (pair)
  49. ;; Things returned
  50. (script-name nil)
  51. (debugger-name nil)
  52. (interpreter-args '())
  53. (debugger-args '())
  54. (script-args '())
  55. (annotate-p nil))
  56. (if (not (and args))
  57. ;; Got nothing: return '(nil, nil nil nil)
  58. (list interpreter-args debugger-args script-args annotate-p)
  59. ;; else
  60. ;; Strip off optional interpreter name
  61. (when (and interp-regexp
  62. (string-match interp-regexp
  63. (file-name-sans-extension
  64. (file-name-nondirectory (car args)))))
  65. (setq interpreter-args (list (pop args)))
  66. ;; Strip off compiler/intepreter-specific options
  67. (while (and args
  68. (string-match "^-" (car args)))
  69. (setq pair (realgud-parse-command-arg
  70. args two-args opt-two-args))
  71. (nconc interpreter-args (car pair))
  72. (setq args (cadr pair))))
  73. ;; Skip to the first non-option argument.
  74. (while (and args (not script-name))
  75. (let ((arg (car args)))
  76. (cond
  77. ;; path-like options
  78. ((member arg path-args-list)
  79. (setq arg (pop args))
  80. (nconc debugger-args
  81. (list arg (realgud:expand-file-name-if-exists
  82. (pop args)))))
  83. ;; Other options with arguments.
  84. ((string-match "^-" arg)
  85. (setq pair (realgud-parse-command-arg
  86. args two-args opt-two-args))
  87. (nconc debugger-args (car pair))
  88. (setq args (cadr pair)))
  89. ;; Anything else must be the script to debug.
  90. (t (setq script-name (realgud:expand-file-name-if-exists arg))
  91. (setq script-args (cons script-name (cdr args))))
  92. )))
  93. (list interpreter-args debugger-args script-args annotate-p))))
  94. (defun realgud:run-process(debugger-name script-filename cmd-args
  95. minibuffer-history
  96. &optional no-reset)
  97. "Runs `realgud-exec-shell' with DEBUGGER-NAME SCRIPT-FILENAME
  98. and CMD-ARGS. If this succeeds, we save CMD-ARGS in command-buffer
  99. for use if we want to restart. If we don't succeed in running
  100. the program, we will switch to the command buffer which shows
  101. details of the error. The command buffer or nil is returned.
  102. DEBUGGER-NAME is used in selecting the tracking mode inside the
  103. command buffer. The debugger name and SCRIPT-FILENAME are used in
  104. selecting a buffer name for the command buffer.
  105. Normally command buffers are reused when the same debugger is
  106. reinvoked inside a command buffer with a similar command. If we
  107. discover that the buffer has prior command-buffer information and
  108. NO-RESET is nil, then that information which may point into other
  109. buffers and source buffers which may contain marks and fringe or
  110. marginal icons is reset."
  111. (let ((cmd-buf))
  112. (setq cmd-buf
  113. (apply 'realgud-exec-shell debugger-name script-filename
  114. (car cmd-args) no-reset (cdr cmd-args)))
  115. ;; FIXME: Is there probably is a way to remove the
  116. ;; below test and combine in condition-case?
  117. (let ((process (get-buffer-process cmd-buf)))
  118. (if (and process (eq 'run (process-status process)))
  119. (progn
  120. (switch-to-buffer cmd-buf)
  121. (realgud:track-set-debugger debugger-name)
  122. (realgud-cmdbuf-info-in-debugger?= 't)
  123. (realgud-cmdbuf-info-cmd-args= cmd-args)
  124. (when cmd-buf
  125. (switch-to-buffer cmd-buf)
  126. (when realgud-cmdbuf-info
  127. (let* ((info realgud-cmdbuf-info)
  128. (cmd-args (realgud-cmdbuf-info-cmd-args info))
  129. (cmd-str (mapconcat 'identity cmd-args " ")))
  130. (if (boundp 'starting-directory)
  131. (realgud-cmdbuf-info-starting-directory= starting-directory))
  132. (set minibuffer-history
  133. (cl-remove-duplicates
  134. (cons cmd-str (eval minibuffer-history)) :from-end)
  135. ))
  136. )))
  137. ;; else
  138. (progn
  139. (if cmd-buf (switch-to-buffer cmd-buf))
  140. (message "Error running command: %s" (mapconcat 'identity cmd-args " "))
  141. )
  142. )
  143. )
  144. cmd-buf
  145. )
  146. )
  147. (defun realgud:run-debugger (debugger-name query-cmdline-fn parse-cmd-args-fn
  148. minibuffer-history
  149. &optional opt-command-line
  150. no-reset opt-script-name)
  151. "Invoke the a debugger and start the Emacs user interface.
  152. String OPT-COMMAND-LINE specifies how to run DEBUGGER-NAME. You
  153. will be prompted for a command line using QUERY-CMDLINE-FN is one
  154. isn't supplied.
  155. OPT-COMMAND-LINE is treated like a shell string; arguments are
  156. tokenized by `split-string-and-unquote'. The tokenized string is
  157. parsed by PARSE-CMD-FN and path elements found by that
  158. are expanded using `expand-file-name'.
  159. If successful, The command buffer of the debugger process is returned.
  160. Otherwise nil is returned.
  161. "
  162. (let* ((cmd-str (or opt-command-line (funcall query-cmdline-fn debugger-name)))
  163. (cmd-args (split-string-and-unquote cmd-str))
  164. (parsed-args (funcall parse-cmd-args-fn cmd-args))
  165. (script-args (cl-caddr parsed-args))
  166. (script-name (or opt-script-name (car script-args)))
  167. (parsed-cmd-args
  168. (cl-remove-if 'nil (realgud:flatten parsed-args)))
  169. )
  170. (realgud:run-process debugger-name script-name parsed-cmd-args
  171. minibuffer-history no-reset)
  172. )
  173. )
  174. ;; For name = trepan2 we produce:
  175. ;;
  176. ;; (defalias 'trepan2 'realgud:trepan2)
  177. ;; (defvar realgud:trepan2-delayed-minibuffer-history nil
  178. ;; "minibuffer history list for the command `realgud:trepan2-delayed'.")
  179. (defmacro realgud-deferred-invoke-setup (name)
  180. `(progn
  181. (defalias
  182. ',(intern (concat name "-delayed"))
  183. ',(intern (concat "realgud:" name "-delayed")))
  184. (defvar ,(intern (concat "realgud:" name "-delayed-minibuffer-history")) nil
  185. ,(format "minibuffer history for the command `%s-delayed'" name))
  186. ))
  187. (provide-me "realgud:")
  188. ;; Local Variables:
  189. ;; byte-compile-warnings: (not cl-functions)
  190. ;; End: