branch: elpa/caml commit 744333dc4c4bd8b93e037efa8f7362b0903b96a2 Author: Stefan Monnier <monn...@iro.umontreal.ca> Commit: Stefan Monnier <monn...@iro.umontreal.ca>
camldebug.el: Partially sync with Tuareg's `ocamldebug.el` Use standard formatting for first and last lines. Mention `ocamldebug` in the title since that's what we run by default. Align license version with that of `caml.el`. Add copyright for my contributions. Group historical info together. Add new commands for `open` and `close`. (camldebug-overlay-event, camldebug-overlay-under): Improve docstring and disconnect from the current buffer. (camldebug-event, camldebug-underline): Add docstring. (camldebug-prefix-map): New map. (def-camldebug): Add entries to it. (caml-mode-map): Add it under the `C-x C-a` prefix here, so `def-camldebug` doesn't need to touch `caml-mode-map` any more. (camldebug-mode-map): Define it explicitly. (comint-input-sentinel): Delete, this was an XEmacs-ism. (camldebug-mode): Use `setq-local`. Hook into `comint-input-filter-functions` rather than `comint-input-sentinel`. (current-camldebug-buffer): Rename to `camldebug-current-buffer` to obey the prefix naming convention. (camldebug-goto-filter): Use `when`. (camldebug-goto): Use `unless`. (camldebug-capf): Simplify a bit. (camldebug--get-completions): Rename arg `command-word` to `str`. (camldebug-command-name): Don't autoload. (camldebug-marker-filter): Use `unless`. (camldebug-filter): Prefer `let` over `setq`. Use `when`. (camldebug-display-line): Use `filepos-to-bufferpos` when available. (camldebug-set-current-event): Use `1-`. (camldebug-module-name): Prefer \' to match end of string. (camldebug-format-command): Prefer `let` over `setq`. Use `bufferpos-to-filepos` when available. (camldebug-call-1): Use `save-excursion` to avoid "point jumping in ocamldebug completion". (camldebug-event): Use `:invert-video` to avoid compiler warning. --- camldebug.el | 375 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 191 insertions(+), 184 deletions(-) diff --git a/camldebug.el b/camldebug.el index 3cf8fd61ac..c0ac4c5c43 100644 --- a/camldebug.el +++ b/camldebug.el @@ -1,29 +1,25 @@ -;****************************************** -*- lexical-binding: t; -*- *** -;* * -;* OCaml * -;* * -;* Jacques Garrigue and Ian T Zimmerman * -;* * -;* Copyright 1997 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; Run camldebug under Emacs -;; Derived from gdb.el. -;; gdb.el is Copyright (C) 1988 Free Software Foundation, Inc, and is part -;; of GNU Emacs -;; Modified by Jerome Vouillon, 1994. -;; Modified by Ian T. Zimmerman, 1996. -;; Modified by Xavier Leroy, 1997. +;;; camldebug.el --- Run ocamldebug / camldebug under Emacs -*- lexical-binding:t -*- + +;;************************************************************************** +;;* * +;;* OCaml * +;;* * +;;* Jacques Garrigue and Ian T Zimmerman * +;;* * +;;* Copyright 1997 Institut National de Recherche en Informatique et * +;;* en Automatique. * +;;* * +;;* All rights reserved. This file is distributed under the terms of * +;;* the GNU General Public License. * +;;* * +;;************************************************************************** + +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This file 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 1, or (at your option) -;; any later version. +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -40,8 +36,17 @@ ;;assume that a sane person doesn't use gdb and dbx at the same time, ;;it's not so OK (IMHO) for gdb and camldebug. +;; Derived from gdb.el. +;; gdb.el is Copyright (C) 1988 Free Software Foundation, Inc, and is part +;; of GNU Emacs +;; Modified by Jerome Vouillon, 1994. +;; Modified by Ian T. Zimmerman, 1996. +;; Modified by Xavier Leroy, 1997. + ;; Xavier Leroy, 21/02/97: adaptation to ocamldebug. +;;; Code: + (require 'comint) (require 'shell) (require 'caml) @@ -60,15 +65,17 @@ "A regexp to recognize the prompt for ocamldebug.") (defvar camldebug-overlay-event - (let ((ol (make-overlay (point-min) (point-min)))) + (let ((ol (make-overlay (point) (point)))) (overlay-put ol 'face 'camldebug-event) + (delete-overlay ol) ;; Disconnect it from current buffer. ol) - "Overlay for displaying the current event.") + "Overlay for displaying the first/last char of current event.") (defvar camldebug-overlay-under - (let ((ol (make-overlay (point-min) (point-min)))) + (let ((ol (make-overlay (point) (point)))) (overlay-put ol 'face 'camldebug-underline) + (delete-overlay ol) ;; Disconnect it from current buffer. ol) - "Overlay for displaying the current event.") + "Overlay for displaying the rest of current event.") (defvar camldebug-event-marker (make-marker) "Marker for displaying the current event.") @@ -76,31 +83,47 @@ "*If non-nil, always display current frame position in another window.") (defface camldebug-event - '((t :invert t)) - "?FIXME?") + '((t :inverse-video t)) + "Face to highlight the first/last char of current event.") (defface camldebug-underline + ;; FIXME: The name should describe what it's used for, not what it looks + ;; like by default! '((t :underline t)) - "?FIXME?") + "Face to highlight the rest of current event.") ;;; Camldebug mode. -(defvar comint-input-sentinel) +(defvar camldebug-prefix-map (make-sparse-keymap) + "Keymap bound to prefix keys in `camldebug-mode' and `caml-mode'.") + +(define-key caml-mode-map "\C-x\C-a" camldebug-prefix-map) + +(defvar camldebug-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-c" camldebug-prefix-map) + (define-key map "\C-l" #'camldebug-refresh) + ;; This is already the default anyway! + ;;(define-key map "\t" #'comint-dynamic-complete) + ;; FIXME: This binding is wrong since `comint-dynamic-list-completions' + ;; is a function, not a command. + ;;(define-key camldebug-mode-map "\M-?" #'comint-dynamic-list-completions) + map)) (define-derived-mode camldebug-mode comint-mode "Inferior CDB" - "Major mode for interacting with an inferior ocamldebug process. + "Major mode for interacting with an ocamldebug process. The following commands are available: -\\{camldebug-mode-map} +\\<camldebug-mode-map>\\{camldebug-mode-map} \\[camldebug-display-frame] displays in the other window the last line referred to in the camldebug buffer. -\\[camldebug-step], \\[camldebug-back] and \\[camldebug-next], in the camldebug -window, call camldebug to step, backstep or next and then update the other -window with the current file and position. +\\[camldebug-step], \\[camldebug-back] and \\[camldebug-next], in the camldebug window, +call camldebug to step, backstep or next and then update the other window +with the current file and position. If you are in a source file, you may select a point to break at, by doing \\[camldebug-break]. @@ -112,23 +135,16 @@ Additionally we have: \\[camldebug-display-frame] display frames file in other window \\[camldebug-step] advance one line in program C-x SPACE sets break point at current line." - - (mapc #'make-local-variable - '(camldebug-last-frame-displayed-p camldebug-last-frame - camldebug-delete-prompt-marker camldebug-filter-function - camldebug-filter-accumulator paragraph-start)) - (setq - camldebug-last-frame nil - camldebug-delete-prompt-marker (make-marker) - camldebug-filter-accumulator "" - camldebug-filter-function #'camldebug-marker-filter - comint-prompt-regexp camldebug-prompt-pattern - paragraph-start comint-prompt-regexp - camldebug-last-frame-displayed-p t) - (add-hook 'comint-dynamic-complete-functions #'camldebug-capf nil t) - (make-local-variable 'shell-dirtrackp) - (setq shell-dirtrackp t) - (setq comint-input-sentinel #'shell-directory-tracker)) + (setq-local camldebug-last-frame nil) + (setq-local camldebug-delete-prompt-marker (make-marker)) + (setq-local camldebug-filter-accumulator "") + (setq-local camldebug-filter-function #'camldebug-marker-filter) + (setq-local comint-prompt-regexp camldebug-prompt-pattern) + (setq-local paragraph-start comint-prompt-regexp) + (setq-local camldebug-last-frame-displayed-p t) + (add-hook 'comint-dynamic-complete-functions #'camldebug-capf nil 'local) + (setq-local shell-dirtrackp t) + (add-hook 'comint-input-filter-functions #'shell-directory-tracker nil t)) ;;; Keymaps. @@ -144,10 +160,10 @@ interpreted specially if present. These are: %m module name of current module. %d directory of current source file. %c number of current character position - %e text of the caml variable surrounding point. + %e text of the Caml variable surrounding point. The `current' source file is the file of the current buffer (if -we're in a caml buffer) or the source file current at the last break +we're in a Caml buffer) or the source file current at the last break or step (if we're in the camldebug buffer), and the `current' module name is the filename stripped of any *.ml* suffixes (this assumes the usual correspondence between module and file naming is observed). The @@ -166,8 +182,7 @@ representation is simply concatenated with the COMMAND." (interactive "P") (camldebug-call ,name ,args (camldebug-numeric-arg arg)))) - (define-key camldebug-mode-map ,(concat "\C-c" key) #',fun) - (define-key caml-mode-map ,(concat "\C-x\C-a" key) #',fun)))) + (define-key camldebug-prefix-map ,key #',fun)))) (def-camldebug "step" "\C-s" "Step one event forward.") (def-camldebug "backstep" "\C-k" "Step one event backward.") @@ -175,6 +190,8 @@ representation is simply concatenated with the COMMAND." (def-camldebug "reverse" "\C-v" "Run the program in reverse.") (def-camldebug "last" "\C-l" "Go to latest time in execution history.") (def-camldebug "backtrace" "\C-t" "Print the call stack.") +(def-camldebug "open" "\C-o" "Open the current module." "%m") +(def-camldebug "close" "\C-c" "Close the current module." "%m") (def-camldebug "finish" "\C-f" "Finish executing current function.") (def-camldebug "print" "\C-p" "Print value of symbol at point." "%e") (def-camldebug "display" "\C-d" "Display value of symbol at point." "%e") @@ -203,7 +220,7 @@ representation is simply concatenated with the COMMAND." (defvar camldebug-kill-output) (defun camldebug-kill-filter (string) - ;gob up stupid questions :-) + ;; Gob up stupid questions :-) (setq camldebug-filter-accumulator (concat camldebug-filter-accumulator string)) (when (string-match "\\(.* \\)(y or n) " camldebug-filter-accumulator) @@ -222,7 +239,7 @@ representation is simply concatenated with the COMMAND." (def-camldebug "kill" "\C-k") -(defvar current-camldebug-buffer nil) +(defvar camldebug-current-buffer nil) (defvar camldebug-goto-output) (defvar camldebug-goto-position) @@ -230,7 +247,7 @@ representation is simply concatenated with the COMMAND." "Kill the program." (interactive) (let ((camldebug-kill-output)) - (with-current-buffer current-camldebug-buffer + (with-current-buffer camldebug-current-buffer (let ((proc (get-buffer-process (current-buffer))) (camldebug-filter-function #'camldebug-kill-filter)) (camldebug-call "kill") @@ -244,7 +261,7 @@ representation is simply concatenated with the COMMAND." ;;FIXME: camldebug doesn't output the Hide marker on kill (defun camldebug-goto-filter (string) - ;accumulate onto previous output + ;; Accumulate onto previous output (setq camldebug-filter-accumulator (concat camldebug-filter-accumulator string)) ;; Address Characters Kind Repr. @@ -272,31 +289,29 @@ representation is simply concatenated with the COMMAND." (when (string-match comint-prompt-regexp camldebug-filter-accumulator) (setq camldebug-goto-output (or camldebug-goto-output 'fail)) (setq camldebug-filter-accumulator "")) - (if (string-match "\n\\(.*\\)\\'" camldebug-filter-accumulator) - (setq camldebug-filter-accumulator - (match-string 1 camldebug-filter-accumulator))) + (when (string-match "\n\\(.*\\)\\'" camldebug-filter-accumulator) + (setq camldebug-filter-accumulator + (match-string 1 camldebug-filter-accumulator))) "") (def-camldebug "goto" "\C-g") (defun camldebug-goto (&optional time) - "Go to the execution time TIME. Without TIME, the command behaves as follows: In the camldebug buffer, -if the point at buffer end, goto time 0\; otherwise, try to obtain the -time from context around point. In a caml mode buffer, try to find the +if the point at buffer end, goto time 0; otherwise, try to obtain the +time from context around point. In a Caml mode buffer, try to find the time associated in execution history with the current point location. With a negative TIME, move that many lines backward in the camldebug buffer, then try to obtain the time from context around point." - (interactive "P") (cond (time (let ((ntime (camldebug-numeric-arg time))) (if (>= ntime 0) (camldebug-call "goto" nil ntime) (save-selected-window - (select-window (get-buffer-window current-camldebug-buffer)) + (select-window (get-buffer-window camldebug-current-buffer)) (save-excursion (if (re-search-backward "^Time *: [0-9]+ - pc *: [0-9]+\\(?::[0-9]+\\)? " @@ -304,7 +319,7 @@ buffer, then try to obtain the time from context around point." (camldebug-goto nil) (error "I don't have %d times in my history" (- 1 ntime)))))))) - ((eq (current-buffer) current-camldebug-buffer) + ((eq (current-buffer) camldebug-current-buffer) (let ((time (cond ((eobp) 0) ((save-excursion @@ -318,15 +333,15 @@ buffer, then try to obtain the time from context around point." (let ((module (camldebug-module-name (buffer-file-name))) (camldebug-goto-position (int-to-string (1- (point)))) (camldebug-goto-output) (address)) - ;get a list of all events in the current module - (with-current-buffer current-camldebug-buffer + ;; Get a list of all events in the current module + (with-current-buffer camldebug-current-buffer (let* ((proc (get-buffer-process (current-buffer))) (camldebug-filter-function #'camldebug-goto-filter)) (camldebug-call-1 (concat "info events " module)) (while (not (and camldebug-goto-output (zerop (length camldebug-filter-accumulator)))) (accept-process-output proc)) - (setq address (if (eq camldebug-goto-output 'fail) nil + (setq address (unless (eq camldebug-goto-output 'fail) (re-search-backward (concat "^Time *: \\([0-9]+\\) - pc *: " camldebug-goto-output @@ -373,27 +388,25 @@ buffer, then try to obtain the time from context around point." "Delete the breakpoint numbered ARG. Without ARG, the command behaves as follows: In the camldebug buffer, -try to obtain the time from context around point. In a caml mode -buffer, try to find the breakpoint associated with the current point -location. +try to obtain the time from context around point. In a Caml buffer, +try to find the breakpoint associated with the current point location. With a negative ARG, look for the -ARGth breakpoint pattern in the camldebug buffer, then try to obtain the breakpoint info from context around point." - (interactive "P") (cond (arg (let ((narg (camldebug-numeric-arg arg))) (if (> narg 0) (camldebug-call "delete" nil narg) - (with-current-buffer current-camldebug-buffer + (with-current-buffer camldebug-current-buffer (if (re-search-backward "^Breakpoint [0-9]+ at [0-9]+\\(?::[0-9]+\\)? *: file " nil t (- 1 narg)) (camldebug-delete nil) (error "I don't have %d breakpoints in my history" (- 1 narg))))))) - ((eq (current-buffer) current-camldebug-buffer) + ((eq (current-buffer) camldebug-current-buffer) (let* ((bpline "^Breakpoint \\([0-9]+\\) at [0-9]+\\(?::[0-9]+\\)? *: file ") (arg (cond @@ -410,7 +423,7 @@ around point." (let ((camldebug-delete-file (concat (camldebug-format-command "%m") ".ml")) (camldebug-delete-position (camldebug-format-command "%c"))) - (with-current-buffer current-camldebug-buffer + (with-current-buffer camldebug-current-buffer (let ((proc (get-buffer-process (current-buffer))) (camldebug-filter-function #'camldebug-delete-filter) (camldebug-delete-output)) @@ -458,38 +471,35 @@ around point." #'string-lessp)))) (defun camldebug-capf () + ;; FIXME: Use an `end' after point when applicable. (let* ((end (point)) (cmd-start (save-excursion - (beginning-of-line) - (and (looking-at comint-prompt-regexp) - (goto-char (match-end 0))) - (point))) - (command (buffer-substring cmd-start end)) - ;; Find the word break. This match will always succeed. - (_ (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command)) - (command-word (match-string 2 command)) - (word-end end) - (word-beg (- word-end (length command-word)))) - - `(,word-beg ,word-end - ,(completion-table-dynamic - (apply-partially - #'camldebug--get-completions - (buffer-substring cmd-start word-beg)))))) - -(defun camldebug--get-completions (command-prefix command-word) + (beginning-of-line) + (if (looking-at comint-prompt-regexp) + (match-end 0) (point)))) + (start (save-excursion + (skip-chars-backward "^ \n" cmd-start) + (point)))) + + `(,start ,end + ,(completion-table-dynamic + (apply-partially #'camldebug--get-completions + (buffer-substring cmd-start start)))))) + +(defun camldebug--get-completions (command-prefix str) + ;; FIXME: Add some caching? (let ((camldebug-complete-list nil)) - ;;itz 04-21-96 if we are trying to complete a word of nonzero - ;;length, chop off the last character. This is a nasty hack, but it - ;;works - in general, not just for this set of words: the comint - ;;call below will weed out false matches - and it avoids further - ;;mucking with camldebug's lexer. + ;; itz 04-21-96 If we are trying to complete a word of nonzero + ;; length, chop off the last character. This is a nasty hack, but it + ;; works - in general, not just for this set of words: the completion + ;; code will weed out false matches - and it avoids further + ;; mucking with camldebug's lexer. ;; FIXME: Which problem is this trying to fix/avoid/circumvent? - (when (> (length command-word) 0) - (setq command-word (substring command-word 0 (1- (length command-word))))) + (when (> (length str) 0) + (setq str (substring str 0 (1- (length str))))) (let ((camldebug-filter-function #'camldebug-complete-filter)) - (camldebug-call-1 (concat "complete " command-prefix command-word)) + (camldebug-call-1 (concat "complete " command-prefix str)) (set-marker camldebug-delete-prompt-marker nil) (while (not (and camldebug-complete-list (zerop (length camldebug-filter-accumulator)))) @@ -499,17 +509,8 @@ around point." nil (sort camldebug-complete-list #'string-lessp)))) -(define-key camldebug-mode-map "\C-l" #'camldebug-refresh) -;; This is already the default anyway! -;;(define-key camldebug-mode-map "\t" #'comint-dynamic-complete) -;; FIXME: This binding is wrong since `comint-dynamic-list-completions' -;; is a function, not a command. -;;(define-key camldebug-mode-map "\M-?" #'comint-dynamic-list-completions) - (define-key caml-mode-map "\C-x " #'camldebug-break) - -;;;###autoload (defvar camldebug-command-name "ocamldebug" "*Pathname for executing camldebug.") @@ -540,8 +541,8 @@ the camldebug commands `cd DIR' and `directory'." (defun camldebug-set-buffer () (if (eq major-mode 'camldebug-mode) - (setq current-camldebug-buffer (current-buffer)) - (save-selected-window (pop-to-buffer current-camldebug-buffer)))) + (setq camldebug-current-buffer (current-buffer)) + (save-selected-window (pop-to-buffer camldebug-current-buffer)))) ;;; Filter and sentinel. @@ -555,9 +556,8 @@ the camldebug commands `cd DIR' and `directory'." "\032\032\\(H\\|M\\(.+\\):\\(.+\\):\\(.+\\):\\(before\\|after\\)\\)\n" camldebug-filter-accumulator)) (setq camldebug-last-frame - (if (char-equal ?H (aref camldebug-filter-accumulator - (1+ (1+ begin)))) - nil + (unless (char-equal ?H (aref camldebug-filter-accumulator + (1+ (1+ begin)))) (let ((isbefore (string= "before" (match-string 5 camldebug-filter-accumulator))) @@ -580,7 +580,6 @@ the camldebug commands `cd DIR' and `directory'." (match-end 0)) camldebug-last-frame-displayed-p nil)) - ;; Does the remaining text look like it might end with the ;; beginning of another marker? If it does, then keep it in ;; camldebug-filter-accumulator until we receive the rest of it. Since we @@ -602,37 +601,35 @@ the camldebug commands `cd DIR' and `directory'." output)) (defun camldebug-filter (proc string) - (let ((output)) - (if (buffer-name (process-buffer proc)) - (let ((process-window)) - ;; it does not seem necessary to save excursion here, - ;; since set-buffer as a temporary effect. - ;; comint-output-filter explicitly avoids it. - ;; in version 23, it prevents the marker to stay at end of buffer - (with-current-buffer (process-buffer proc) - ;; If we have been so requested, delete the debugger prompt. - (if (marker-buffer camldebug-delete-prompt-marker) - (progn - (delete-region (process-mark proc) - camldebug-delete-prompt-marker) - (set-marker camldebug-delete-prompt-marker nil))) - (setq output (funcall camldebug-filter-function string)) - ;; Don't display the specified file unless - ;; (1) point is at or after the position where output appears - ;; and (2) this buffer is on the screen. - (setq process-window (and camldebug-track-frame - (not camldebug-last-frame-displayed-p) - (>= (point) (process-mark proc)) - (get-buffer-window (current-buffer)))) - ;; Insert the text, moving the process-marker. - (comint-output-filter proc output)) - ;; if save-excursion is used (comint-next-prompt 1) would be needed - ;; to move the mark past then next prompt, but this is not as good - ;; as solution. - (if process-window - (save-selected-window - (select-window process-window) - (camldebug-display-frame))))))) + (when (buffer-name (process-buffer proc)) + (let ((process-window)) + ;; it does not seem necessary to save excursion here, + ;; since set-buffer as a temporary effect. + ;; comint-output-filter explicitly avoids it. + ;; in version 23, it prevents the marker to stay at end of buffer + (with-current-buffer (process-buffer proc) + ;; If we have been so requested, delete the debugger prompt. + (when (marker-buffer camldebug-delete-prompt-marker) + (delete-region (process-mark proc) + camldebug-delete-prompt-marker) + (set-marker camldebug-delete-prompt-marker nil)) + (let ((output (funcall camldebug-filter-function string))) + ;; Don't display the specified file unless + ;; (1) point is at or after the position where output appears + ;; and (2) this buffer is on the screen. + (setq process-window (and camldebug-track-frame + (not camldebug-last-frame-displayed-p) + (>= (point) (process-mark proc)) + (get-buffer-window (current-buffer)))) + ;; Insert the text, moving the process-marker. + (comint-output-filter proc output))) + ;; if save-excursion is used (comint-next-prompt 1) would be needed + ;; to move the mark past then next prompt, but this is not as good + ;; as solution. + (when process-window + (save-selected-window + (select-window process-window) + (camldebug-display-frame)))))) (defun camldebug-sentinel (proc msg) (cond ((null (buffer-name (process-buffer proc))) @@ -694,7 +691,7 @@ Obeying it means displaying in another window the specified file and line." ;; and that its character CHARACTER is visible. ;; Put the mark on this character in that buffer. -(defvar pre-display-buffer-function) +(defvar pre-display-buffer-function) ;XEmacs variable. (defun camldebug-display-line (true-file schar echar kind) (let* ((pre-display-buffer-function nil) ; screw it, put it all in one screen @@ -705,8 +702,12 @@ Obeying it means displaying in another window the specified file and line." (with-current-buffer buffer (save-restriction (widen) - (setq spos (+ (point-min) schar)) - (setq epos (+ (point-min) echar)) + (setq spos (if (fboundp 'filepos-to-bufferpos) ;Emacs-25 + (filepos-to-bufferpos schar 'approximate) + (+ (point-min) schar))) + (setq epos (if (fboundp 'filepos-to-bufferpos) + (filepos-to-bufferpos echar 'approximate) + (+ (point-min) echar))) (setq pos (if kind spos epos)) (camldebug-set-current-event spos epos (current-buffer) kind)) (cond ((or (< pos (point-min)) (> pos (point-max))) @@ -729,7 +730,7 @@ Obeying it means displaying in another window the specified file and line." (move-overlay camldebug-overlay-under (+ spos 1) epos buffer)) (move-overlay camldebug-overlay-event (1- epos) epos buffer) - (move-overlay camldebug-overlay-under spos (- epos 1) buffer)) + (move-overlay camldebug-overlay-under spos (1- epos) buffer)) (with-current-buffer buffer (goto-char spos) (beginning-of-line) @@ -739,7 +740,7 @@ Obeying it means displaying in another window the specified file and line." ;;; Miscellaneous. (defun camldebug-module-name (filename) - (substring filename (string-match "\\([^/]*\\)\\.ml$" filename) + (substring filename (string-match "\\([^/]*\\)\\.ml\\'" filename) (match-end 1))) ;; The camldebug-call function must do the right thing whether its @@ -748,25 +749,31 @@ Obeying it means displaying in another window the specified file and line." ;; to supply data from camldebug-last-frame. Here's how we do it: (defun camldebug-format-command (str) - (let* ((insource (not (eq (current-buffer) current-camldebug-buffer))) - (frame (if insource nil camldebug-last-frame)) (result)) + (let* ((insource (not (eq (current-buffer) camldebug-current-buffer))) + (frame (if insource nil camldebug-last-frame)) + (result "")) (while (and str (string-match "\\([^%]*\\)%\\([mdcep]\\)" str)) - (let ((key (string-to-char (substring str (match-beginning 2)))) - (cmd (substring str (match-beginning 1) (match-end 1))) - (subst)) - (setq str (substring str (match-end 2))) - (cond - ((eq key ?m) - (setq subst (camldebug-module-name - (if insource (buffer-file-name) (nth 0 frame))))) - ((eq key ?d) - (setq subst (file-name-directory - (if insource (buffer-file-name) (nth 0 frame))))) - ((eq key ?c) - (setq subst (int-to-string - (if insource (1- (point)) (nth 1 frame))))) - ((eq key ?e) - (setq subst (thing-at-point 'symbol)))) + (let* ((key (aref str (match-beginning 2))) + (cmd (match-string 1 str)) + (end (match-end 0)) + (subst + (cond + ((eq key ?m) + (camldebug-module-name + (if insource buffer-file-name (nth 0 frame)))) + ((eq key ?d) + (file-name-directory + (if insource buffer-file-name (nth 0 frame)))) + ((eq key ?c) + (int-to-string + (if insource + (if (fboundp 'bufferpos-to-filepos) + (bufferpos-to-filepos (point)) + (1- (point))) + (nth 1 frame)))) + ((eq key ?e) + (thing-at-point 'symbol))))) + (setq str (substring str end)) (setq result (concat result cmd subst)))) ;; There might be text left in STR when the loop ends. (concat result str))) @@ -780,10 +787,10 @@ These are: %m module name of current module. %d directory of current source file. %c number of current character position - %e text of the caml variable surrounding point. + %e text of the Caml variable surrounding point. The `current' source file is the file of the current buffer (if -we're in a caml buffer) or the source file current at the last break +we're in a Caml buffer) or the source file current at the last break or step (if we're in the camldebug buffer), and the `current' module name is the filename stripped of any *.ml* suffixes (this assumes the usual correspondence between module and file naming is observed). The @@ -799,22 +806,22 @@ representation is simply concatenated with the COMMAND." (message "Command: %s" (camldebug-call-1 command fmt arg))) (defun camldebug-call-1 (command &optional fmt arg) - ;; Record info on the last prompt in the buffer and its position. - (with-current-buffer current-camldebug-buffer - (goto-char (process-mark (get-buffer-process current-camldebug-buffer))) - (let () ;;(pt (point)) + (with-current-buffer camldebug-current-buffer + (save-excursion + (goto-char (process-mark (get-buffer-process camldebug-current-buffer))) (beginning-of-line) - (if (looking-at comint-prompt-regexp) - (set-marker camldebug-delete-prompt-marker (point))))) + (when (looking-at comint-prompt-regexp) + (set-marker camldebug-delete-prompt-marker (point))))) (let ((cmd (cond (arg (concat command " " (int-to-string arg))) (fmt (camldebug-format-command (concat command " " fmt))) (command)))) - (process-send-string (get-buffer-process current-camldebug-buffer) + (process-send-string (get-buffer-process camldebug-current-buffer) (concat cmd "\n")) cmd)) (provide 'camldebug) +;;; camldebug.el ends here