diff options
| author | Tom Tromey | 2018-06-24 11:18:19 -0600 |
|---|---|---|
| committer | Tom Tromey | 2018-06-24 11:33:02 -0600 |
| commit | cd5bb4bf3dbad8941d25823f398b595b8f0edbb9 (patch) | |
| tree | 09ad146d785847a05fb96a998a357165176b5402 | |
| parent | eaa054a94b786ce7dc4169c9b14893f50335f657 (diff) | |
| download | emacs-cd5bb4bf3dbad8941d25823f398b595b8f0edbb9.tar.gz emacs-cd5bb4bf3dbad8941d25823f398b595b8f0edbb9.zip | |
Fix two tcl-mode defun-related bugs
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.
| -rw-r--r-- | lisp/progmodes/tcl.el | 49 | ||||
| -rw-r--r-- | test/lisp/progmodes/tcl-tests.el | 68 |
2 files changed, 111 insertions, 6 deletions
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el index 0d9322359c9..fad62e100a4 100644 --- a/lisp/progmodes/tcl.el +++ b/lisp/progmodes/tcl.el | |||
| @@ -611,6 +611,9 @@ already exist." | |||
| 611 | (set (make-local-variable 'add-log-current-defun-function) | 611 | (set (make-local-variable 'add-log-current-defun-function) |
| 612 | 'tcl-add-log-defun) | 612 | 'tcl-add-log-defun) |
| 613 | 613 | ||
| 614 | (setq-local beginning-of-defun-function #'tcl-beginning-of-defun-function) | ||
| 615 | (setq-local end-of-defun-function #'tcl-end-of-defun-function) | ||
| 616 | |||
| 614 | (easy-menu-add tcl-mode-menu) | 617 | (easy-menu-add tcl-mode-menu) |
| 615 | ;; Append Tcl menu to popup menu for XEmacs. | 618 | ;; Append Tcl menu to popup menu for XEmacs. |
| 616 | (if (boundp 'mode-popup-menu) | 619 | (if (boundp 'mode-popup-menu) |
| @@ -993,15 +996,49 @@ Returns nil if line starts inside a string, t if in a comment." | |||
| 993 | ;; Interfaces to other packages. | 996 | ;; Interfaces to other packages. |
| 994 | ;; | 997 | ;; |
| 995 | 998 | ||
| 996 | ;; FIXME Definition of function is very ad-hoc. Should use | 999 | (defun tcl-beginning-of-defun-function (&optional arg) |
| 997 | ;; beginning-of-defun. Also has incestuous knowledge about the | 1000 | "`beginning-of-defun-function' for Tcl mode." |
| 998 | ;; format of tcl-proc-regexp. | 1001 | (when (or (not arg) (= arg 0)) |
| 1002 | (setq arg 1)) | ||
| 1003 | (let* ((search-fn (if (> arg 0) | ||
| 1004 | ;; Positive arg means to search backward. | ||
| 1005 | #'re-search-backward | ||
| 1006 | #'re-search-forward)) | ||
| 1007 | (arg (abs arg)) | ||
| 1008 | (result t)) | ||
| 1009 | (while (and (> arg 0) result) | ||
| 1010 | (unless (funcall search-fn tcl-proc-regexp nil t) | ||
| 1011 | (setq result nil)) | ||
| 1012 | (setq arg (1- arg))) | ||
| 1013 | result)) | ||
| 1014 | |||
| 1015 | (defun tcl-end-of-defun-function () | ||
| 1016 | "`end-of-defun-function' for Tcl mode." | ||
| 1017 | ;; Because we let users redefine tcl-proc-list, we don't really know | ||
| 1018 | ;; too much about the exact arguments passed to the "proc"-defining | ||
| 1019 | ;; command. Instead we just skip words and lists until we see | ||
| 1020 | ;; either a ";" or a newline, either of which terminates a command. | ||
| 1021 | (skip-syntax-forward "-") | ||
| 1022 | (while (and (not (eobp)) | ||
| 1023 | (not (looking-at-p "[\n;]"))) | ||
| 1024 | (condition-case nil | ||
| 1025 | (forward-sexp) | ||
| 1026 | (scan-error | ||
| 1027 | (goto-char (point-max)))) | ||
| 1028 | ;; Note that here we do not want to skip \n. | ||
| 1029 | (skip-chars-forward " \t"))) | ||
| 1030 | |||
| 999 | (defun tcl-add-log-defun () | 1031 | (defun tcl-add-log-defun () |
| 1000 | "Return name of Tcl function point is in, or nil." | 1032 | "Return name of Tcl function point is in, or nil." |
| 1001 | (save-excursion | 1033 | (save-excursion |
| 1002 | (end-of-line) | 1034 | (let ((orig-point (point))) |
| 1003 | (if (re-search-backward (concat tcl-proc-regexp "\\([^ \t\n{]+\\)") nil t) | 1035 | (when (beginning-of-defun) |
| 1004 | (match-string 2)))) | 1036 | ;; Only return the name when in the body of the function. |
| 1037 | (when (save-excursion | ||
| 1038 | (end-of-defun) | ||
| 1039 | (>= (point) orig-point)) | ||
| 1040 | (when (looking-at (concat tcl-proc-regexp "\\([^ \t\n{]+\\)")) | ||
| 1041 | (match-string 2))))))) | ||
| 1005 | 1042 | ||
| 1006 | (defun tcl-outline-level () | 1043 | (defun tcl-outline-level () |
| 1007 | (save-excursion | 1044 | (save-excursion |
diff --git a/test/lisp/progmodes/tcl-tests.el b/test/lisp/progmodes/tcl-tests.el new file mode 100644 index 00000000000..55211b70be2 --- /dev/null +++ b/test/lisp/progmodes/tcl-tests.el | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | ;;; tcl-tests.el --- Test suite for tcl-mode | ||
| 2 | |||
| 3 | ;; Copyright (C) 2018 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ;;; Commentary: | ||
| 21 | |||
| 22 | ;;; Code: | ||
| 23 | |||
| 24 | (require 'ert) | ||
| 25 | (require 'tcl) | ||
| 26 | |||
| 27 | ;; From bug#23565 | ||
| 28 | (ert-deftest tcl-mode-beginning-of-defun-1 () | ||
| 29 | (with-temp-buffer | ||
| 30 | (tcl-mode) | ||
| 31 | (insert "proc bad {{value \"\"}} {\n # do something\n}") | ||
| 32 | (should (beginning-of-defun)) | ||
| 33 | (should (= (point) (point-min))) | ||
| 34 | (end-of-defun) | ||
| 35 | (should (= (point) (point-max))))) | ||
| 36 | |||
| 37 | ;; From bug#23565 | ||
| 38 | (ert-deftest tcl-mode-beginning-of-defun-2 () | ||
| 39 | (with-temp-buffer | ||
| 40 | (tcl-mode) | ||
| 41 | (insert "proc good {{value}} {\n # do something\n}") | ||
| 42 | (should (beginning-of-defun)) | ||
| 43 | (should (= (point) (point-min))) | ||
| 44 | (end-of-defun) | ||
| 45 | (should (= (point) (point-max))))) | ||
| 46 | |||
| 47 | (ert-deftest tcl-mode-function-name () | ||
| 48 | (with-temp-buffer | ||
| 49 | (tcl-mode) | ||
| 50 | (insert "proc notinthis {} {\n # nothing\n}\n\n") | ||
| 51 | (should-not (add-log-current-defun)))) | ||
| 52 | |||
| 53 | (ert-deftest tcl-mode-function-name () | ||
| 54 | (with-temp-buffer | ||
| 55 | (tcl-mode) | ||
| 56 | (insert "proc simple {} {\n # nothing\n}") | ||
| 57 | (backward-char 3) | ||
| 58 | (should (equal "simple" (add-log-current-defun))))) | ||
| 59 | |||
| 60 | (ert-deftest tcl-mode-function-name () | ||
| 61 | (with-temp-buffer | ||
| 62 | (tcl-mode) | ||
| 63 | (insert "proc inthis {} {\n # nothing\n") | ||
| 64 | (should (equal "inthis" (add-log-current-defun))))) | ||
| 65 | |||
| 66 | (provide 'tcl-tests) | ||
| 67 | |||
| 68 | ;;; tcl-tests.el ends here | ||