From c3167ad05d025aaa8d56d0d2df4a015df74a5734 Mon Sep 17 00:00:00 2001 From: Chris Mann Date: Sun, 14 Dec 2008 17:02:14 +1030 Subject: [PATCH] * wesnoth-mode.el (wesnoth-estimate-element-type): Fixed potential bug. (wesnoth-guess-element-type): Added `bound' argument for more efficiency. (wesnoth-indent-or-complete): Indent single closing element. (wesnoth-insert-missing-closing): Rewritten. No longer uses `wesnoth-check-structure'. (wesnoth-navigate-element): Now a function; not a macro. (wesnoth-jump-to-matching): Support closing element as argument. (wesnoth-element-requires, wesnoth-structure-result, wesnoth-check-structure): Removed. --- wesnoth-mode.el | 222 ++++++++++++++++++-------------------------------------- 1 file changed, 71 insertions(+), 151 deletions(-) diff --git a/wesnoth-mode.el b/wesnoth-mode.el index 104946c..2a22095 100644 --- a/wesnoth-mode.el +++ b/wesnoth-mode.el @@ -34,7 +34,8 @@ ;;; History: ;; 1.3.3 -;; * All warnings found when checking WML are now underlined in the buffer. +;; * Improve performance when inserting missing elements. +;; * All warnings found when checking WML are now underlisned in the buffer. ;; * Next and previous warning can be jumped to using C-c C-f (or C-x `) and ;; C-c C-b, respectively. ;; * Any macro arguments are now prompted for and inserted when performing @@ -373,7 +374,7 @@ of the element." (defun wesnoth-estimate-element-type (point) "Return match data for a partial element at POINT." (save-excursion - (goto-char (point)) + (goto-char point) (let ((element-matches '(("{\\(.*?[/\]\\)+$" . nil) ;; pathnames ("{\\(\\w\\|_\\)*$" . macro) @@ -388,20 +389,23 @@ of the element." (match-beginning 0) (match-end 0))))))))) -(defun wesnoth-guess-element-type (point) +(defun wesnoth-guess-element-type (point &optional bound) "Return details for the the element near POINT. Locate the start of the element before determining details. BOUND is the limit to search backwards." - (save-excursion - (let ((details (wesnoth-estimate-element-type (point)))) - (if (car details) - (and (nth 1 details) - (>= point (nth 1 details)) - (nth 2 details) - (<= point (nth 2 details)) - details) - (unless (bolp) - (wesnoth-guess-element-type (goto-char (1- (point))))))))) + (unless bound (setq bound (save-excursion + (goto-char point) + (beginning-of-line) + (point)))) + (let ((details (wesnoth-estimate-element-type point))) + (if (car details) + (and (nth 1 details) + (>= point (nth 1 details)) + (nth 2 details) + (<= point (nth 2 details)) + details) + (unless (<= point bound) + (wesnoth-guess-element-type (1- point) bound))))) ;;; Insertion and completion @@ -486,10 +490,10 @@ matching tags." (wesnoth-complete-preprocessor elements t)) ((eq (car details) 'tag-closing) (and (wesnoth-insert-missing-closing) - (delete-region (nth 1 details) (save-excursion - (beginning-of-line) - (point)))) - (end-of-line)) + (delete-region (nth 1 details) + (save-excursion (beginning-of-line) (point)))) + (end-of-line) + (wesnoth-indent)) ((eq (car details) 'attribute) (wesnoth-complete-attribute t)) (t @@ -768,34 +772,26 @@ TAGNAME is the name of the tag to be inserted." (open-line 1))) (insert (apply 'concat strings))) -(defun wesnoth-insert-missing-closing (&optional start end) - "Insert the next expected closing element at point. - -START and END define the region to check for missing closing -elements. If function `transient-mark-mode' is enabled, the region -specified will be used as START and END. Otherwise, START and -END will be the minimum and current positions of the buffer, -respectively." +(defun wesnoth-insert-missing-closing () + "Insert the next expected closing element at point." (interactive) - (if (and (boundp 'transient-mark-mode) - (symbol-value 'transient-mark-mode) - (symbol-value 'mark-active)) - (setq start (region-beginning) - end (copy-marker (region-end))) - (setq start (point-min) - end (point-max))) - (let ((element (wesnoth-check-structure start end))) - (cond ((not element) - (message "%s" "Unable to find element to insert") - nil) - ((string= element "Unexpected end of file") - (message "%s" element) - nil) - (t - (wesnoth-insert-element-separately element) - (wesnoth-indent) - (end-of-line) - t)))) + (let ((match nil)) + (save-excursion + (when (wesnoth-search-for-matching-tag + 'search-backward-regexp (wesnoth-element-opening) 'point-min + t) + (setq match (and (looking-at (wesnoth-element-opening)) + (match-string-no-properties 1))))) + (when match + (if (string= (substring match 0 1) "[") + (wesnoth-insert-element-separately + "[/" (substring match 1 (1- (length match))) "]") + (wesnoth-insert-element-separately + (cdr (assoc match '(("#define " . "#enddef") + ("#ifndef " . "#endif") + ("#ifdef " . "#endif")))))))) + (wesnoth-indent) + (end-of-line)) (defun wesnoth-insert-and-indent (&rest args) "Concatenate and insert the given string(s) before indenting. @@ -818,19 +814,18 @@ non-nil." (wesnoth-indent)))) ;;; Movement -(defmacro wesnoth-navigate-element (repeat search-function bound) +(defun wesnoth-navigate-element (repeat search-function bound) "Move point to the tag in the given direction REPEAT times. SEARCH-FUNCTION is the symbol of the function for searching in the required direction, with BOUND marking the furthest point to search." - `(progn - (or ,repeat (setq ,repeat 1)) - (while (> ,repeat 0) - (and (eq ,search-function 'search-forward-regexp) (end-of-line)) - (funcall ,search-function (wesnoth-element-opening) ,bound t) - (back-to-indentation) - (setq repeat (1- ,repeat))))) + (or repeat (setq repeat 1)) + (while (> repeat 0) + (and (eq search-function 'search-forward-regexp) (end-of-line)) + (funcall search-function (wesnoth-element-opening) bound t) + (back-to-indentation) + (setq repeat (1- repeat)))) (defun wesnoth-nth-pair-position (count) "Return `point' after COUNT number of matching element pairs. @@ -892,40 +887,41 @@ If SKIP is non-nil, skip the first element and continue from there." (setq depth (1+ depth)))) (= depth 0)))) -(defun wesnoth-jump-to-matching (&optional opening) +(defun wesnoth-jump-to-matching (&optional element) "Jump point to the matching opening/closing tag. -OPENING is an opening preprocessor statement to attempt to find a match for." +OPENING is an opening element to find a match for." (interactive) (beginning-of-line) (let ((target nil) (first-element nil)) (save-excursion (cond - ((or (and (stringp opening) - (string-match (wesnoth-element-opening) opening)) + ((or (and (stringp element) + (string-match (wesnoth-element-opening) element)) (looking-at (wesnoth-element-opening))) - (progn - (setq first-element (match-string-no-properties 0 opening)) - (when (wesnoth-search-for-matching-tag - 'search-forward-regexp (wesnoth-element-closing) 'point-max - (stringp opening)) - (beginning-of-line) - (if (and (string-match wesnoth-preprocessor-opening-regexp - first-element) - (looking-at (wesnoth-element-closing))) - (when (string= (match-string-no-properties 0) - (cdr (assoc first-element - '(("#define " . "#enddef") - ("#ifndef " . "#endif") - ("#ifdef " . "#endif"))))) - (setq target (point))) - (setq target (point)))))) - ((looking-at (wesnoth-element-closing)) + (setq first-element (match-string-no-properties 0 element)) + (when (wesnoth-search-for-matching-tag + 'search-forward-regexp (wesnoth-element-closing) 'point-max + (stringp element)) + (beginning-of-line) + (if (and (string-match wesnoth-preprocessor-opening-regexp + first-element) + (looking-at (wesnoth-element-closing))) + (when (string= (match-string-no-properties 0) + (cdr (assoc first-element + '(("#define " . "#enddef") + ("#ifndef " . "#endif") + ("#ifdef " . "#endif"))))) + (setq target (point))) + (setq target (point))))) + ((or (and (stringp element) + (string-match (wesnoth-element-closing) element)) + (looking-at (wesnoth-element-closing))) (end-of-line) - (setq first-element (match-string-no-properties 0)) + (setq first-element (match-string-no-properties 0 element)) (when (wesnoth-search-for-matching-tag 'search-backward-regexp (wesnoth-element-opening) - 'wesnoth-wml-start-pos) + 'wesnoth-wml-start-pos (stringp element)) (if (and (string-match wesnoth-preprocessor-closing-regexp first-element) (looking-at (wesnoth-element-opening))) @@ -1379,82 +1375,6 @@ the end of the region to place the overlay." (if (= warnings 1) "." "s.")) warnings))) (message (format "Checking %s...done" buffer)))))) -(defmacro wesnoth-element-requires (element requirement &optional pop) - "Process requirements for corresponding preprocessor elements. -ELEMENT is the current element being tested. -REQUIREMENT is the element required to exist for correct nesting. -POP is an optional argument indicating the element should be -removed from the list of unmatched elements." - `(when (string= ,element (match-string-no-properties 1)) - (if (string-match ,requirement (car unmatched)) - (progn - (and ,pop (setq unmatched (cdr unmatched))) - t) - (setq position (point))))) - -(defmacro wesnoth-structure-result (position element) - "Process results of the structure check. -POSITION is the position of the error or nil, if no error was -found. ELEMENT is the last unmatched element, or nil if all -opening elements have been matched." - `(let ((expected nil)) - (when ,element - (cond ((string= ,element "define ") (setq expected "#enddef")) - ((string-match "ifn?def " ,element) (setq expected "#endif")))) - (if (interactive-p) - (if (or ,element ,position) - (progn - (and ,position (goto-char ,position)) - (message "Expecting %s" (or expected - (concat "[/" ,element "]")))) - (message "%s" "Structure appears consistent.")) - (when (or expected ,element) - (or expected (concat "[/" ,element "]")))))) - -(defun wesnoth-check-structure (&optional start end) - "Check the buffer for correct nesting of elements. -If a problem is found in the structure, point will be placed at -the location which an element was expected and the expected -element will be displayed in the mini-buffer. - -START and END define the region to be checked. If -function `transient-mark-mode' is enabled, the region specified will be -checked. Otherwise START and END will be the minimum and maximum -positions of the buffer, respectively." - (interactive) - (unless (or start end) - (if (and (boundp 'transient-mark-mode) - (symbol-value 'transient-mark-mode) - (symbol-value 'mark-active)) - (setq start (region-beginning) - end (copy-marker (region-end))) - (setq start (point-min) - end (point-max)))) - (let ((unmatched '()) - (position nil)) - (save-excursion - (and start (goto-char start)) - (while (and (search-forward-regexp - (concat "^\\([\t ]*\\[\\(/?\\(\\w\\|_\\)+\\)\\]\\|" - wesnoth-preprocessor-regexp "\\)") end t) - (not position)) - (beginning-of-line) - (if (or (looking-at "^[\t ]*\\[\\(\\(\\w\\|_\\)+\\)\\]") - (looking-at "[\t ]*#\\(define \\|ifdef \\|ifndef \\)")) - (setq unmatched (cons (match-string-no-properties 1) - unmatched)) - (cond - ((wesnoth-element-requires "#else" "ifn?def ")) - ((wesnoth-element-requires "#endif" "ifn?def " t)) - ((wesnoth-element-requires "#enddef" "define " t)) - ((looking-at (concat "^[\t ]*\\[/\\(\\(\\w\\|_\\)+\\)\\]\\|" - wesnoth-preprocessor-closing-regexp)) - (if (string= (match-string-no-properties 1) - (car unmatched)) - (setq unmatched (cdr unmatched)) - (setq position (point)))))) - (end-of-line))) - (wesnoth-structure-result position (car unmatched)))) ;;; wesnoth-mode (define-derived-mode wesnoth-mode fundamental-mode "wesnoth-mode" -- 2.11.4.GIT