]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix two tcl-mode defun-related bugs
authorTom Tromey <tom@tromey.com>
Sun, 24 Jun 2018 17:18:19 +0000 (11:18 -0600)
committerTom Tromey <tom@tromey.com>
Sun, 24 Jun 2018 17:33:02 +0000 (11:33 -0600)
Fixes bug#23565
* lisp/progmodes/tcl.el (tcl-mode): Set beginning-of-defun-function
and end-of-defun-function.
(tcl-beginning-of-defun-function, tcl-end-of-defun-function): New
defuns.
* test/lisp/progmodes/tcl-tests.el: New file.

lisp/progmodes/tcl.el
test/lisp/progmodes/tcl-tests.el [new file with mode: 0644]

index 0d9322359c92909567bfb3aa3b6f128885fae9ea..fad62e100a4b01025b12ffee365d8a023c5db42e 100644 (file)
@@ -611,6 +611,9 @@ already exist."
   (set (make-local-variable 'add-log-current-defun-function)
        'tcl-add-log-defun)
 
+  (setq-local beginning-of-defun-function #'tcl-beginning-of-defun-function)
+  (setq-local end-of-defun-function #'tcl-end-of-defun-function)
+
   (easy-menu-add tcl-mode-menu)
   ;; Append Tcl menu to popup menu for XEmacs.
   (if (boundp 'mode-popup-menu)
@@ -993,15 +996,49 @@ Returns nil if line starts inside a string, t if in a comment."
 ;; Interfaces to other packages.
 ;;
 
-;; FIXME Definition of function is very ad-hoc.  Should use
-;; beginning-of-defun.  Also has incestuous knowledge about the
-;; format of tcl-proc-regexp.
+(defun tcl-beginning-of-defun-function (&optional arg)
+  "`beginning-of-defun-function' for Tcl mode."
+  (when (or (not arg) (= arg 0))
+    (setq arg 1))
+  (let* ((search-fn (if (> arg 0)
+                        ;; Positive arg means to search backward.
+                        #'re-search-backward
+                      #'re-search-forward))
+         (arg (abs arg))
+         (result t))
+    (while (and (> arg 0) result)
+      (unless (funcall search-fn tcl-proc-regexp nil t)
+        (setq result nil))
+      (setq arg (1- arg)))
+    result))
+
+(defun tcl-end-of-defun-function ()
+  "`end-of-defun-function' for Tcl mode."
+  ;; Because we let users redefine tcl-proc-list, we don't really know
+  ;; too much about the exact arguments passed to the "proc"-defining
+  ;; command.  Instead we just skip words and lists until we see
+  ;; either a ";" or a newline, either of which terminates a command.
+  (skip-syntax-forward "-")
+  (while (and (not (eobp))
+              (not (looking-at-p "[\n;]")))
+    (condition-case nil
+        (forward-sexp)
+      (scan-error
+       (goto-char (point-max))))
+    ;; Note that here we do not want to skip \n.
+    (skip-chars-forward " \t")))
+
 (defun tcl-add-log-defun ()
   "Return name of Tcl function point is in, or nil."
   (save-excursion
-    (end-of-line)
-    (if (re-search-backward (concat tcl-proc-regexp "\\([^ \t\n{]+\\)") nil t)
-       (match-string 2))))
+    (let ((orig-point (point)))
+      (when (beginning-of-defun)
+        ;; Only return the name when in the body of the function.
+        (when (save-excursion
+                (end-of-defun)
+                (>= (point) orig-point))
+          (when (looking-at (concat tcl-proc-regexp "\\([^ \t\n{]+\\)"))
+            (match-string 2)))))))
 
 (defun tcl-outline-level ()
   (save-excursion
diff --git a/test/lisp/progmodes/tcl-tests.el b/test/lisp/progmodes/tcl-tests.el
new file mode 100644 (file)
index 0000000..55211b7
--- /dev/null
@@ -0,0 +1,68 @@
+;;; tcl-tests.el --- Test suite for tcl-mode
+
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'tcl)
+
+;; From bug#23565
+(ert-deftest tcl-mode-beginning-of-defun-1 ()
+  (with-temp-buffer
+    (tcl-mode)
+    (insert "proc bad {{value \"\"}} {\n    # do something\n}")
+    (should (beginning-of-defun))
+    (should (= (point) (point-min)))
+    (end-of-defun)
+    (should (= (point) (point-max)))))
+
+;; From bug#23565
+(ert-deftest tcl-mode-beginning-of-defun-2 ()
+  (with-temp-buffer
+    (tcl-mode)
+    (insert "proc good {{value}} {\n    # do something\n}")
+    (should (beginning-of-defun))
+    (should (= (point) (point-min)))
+    (end-of-defun)
+    (should (= (point) (point-max)))))
+
+(ert-deftest tcl-mode-function-name ()
+  (with-temp-buffer
+    (tcl-mode)
+    (insert "proc notinthis {} {\n  # nothing\n}\n\n")
+    (should-not (add-log-current-defun))))
+
+(ert-deftest tcl-mode-function-name ()
+  (with-temp-buffer
+    (tcl-mode)
+    (insert "proc simple {} {\n  # nothing\n}")
+    (backward-char 3)
+    (should (equal "simple" (add-log-current-defun)))))
+
+(ert-deftest tcl-mode-function-name ()
+  (with-temp-buffer
+    (tcl-mode)
+    (insert "proc inthis {} {\n  # nothing\n")
+    (should (equal "inthis" (add-log-current-defun)))))
+
+(provide 'tcl-tests)
+
+;;; tcl-tests.el ends here