diff options
| author | Michal Nazarewicz | 2014-06-05 16:42:07 +0200 |
|---|---|---|
| committer | Michal Nazarewicz | 2014-06-05 16:42:07 +0200 |
| commit | 03d7d160c3c7f31f1fee84b1bdcd252a8cec7b99 (patch) | |
| tree | a173a51f3eee0e4ab48b6770961819a95ebb9af1 | |
| parent | df344ab435c04aea5bb9261e6d2c349ab8f4fcea (diff) | |
| download | emacs-03d7d160c3c7f31f1fee84b1bdcd252a8cec7b99.tar.gz emacs-03d7d160c3c7f31f1fee84b1bdcd252a8cec7b99.zip | |
tildify.el: Rewrite `tildify-region' and co., add foreach function.
* lisp/textmodes/tildify.el (tildify-foreach-region-outside-env): New
function which calls a callback on portions of the buffer that are
outside of ignored environments.
(tildify-build-regexp): Remove function since it is now
incorporated in `tildify-foreach-region-outside-env' where it is
optimised and simplified by the use of `mapconcat'.
(tildify-tildify): Return number of substitutions made so that…
(tildify-count): …can be removed.
(tildify-find-env): Accept a new PAIRS argument which was
previously looked up in `tildify-ignored-environments-alist' each
time the function was called. With this change, the lookup is
performed only once in `tildify-foreach-region-outside-env'.
(tildify-region): Greatly simplify the function since now most of
the work is done by `tildify-foreach-region-outside-env'.
(tildify-mode-alist): Simplify slightly by avoiding if and setq
and instead using or.
* tests/automated/tildify-tests.el (tildify-test-find-env-end-re-bug)
(tildify-test-find-env-group-index-bug): Update to support new
signature of the `tildify-foreach-region-outside-env' function.
Namely, it now takes pairs as an argument instead of looking it up in
`tildify-ignored-environments-alist'.
| -rw-r--r-- | lisp/ChangeLog | 17 | ||||
| -rw-r--r-- | lisp/textmodes/tildify.el | 145 | ||||
| -rw-r--r-- | test/ChangeLog | 6 | ||||
| -rw-r--r-- | test/automated/tildify-tests.el | 17 |
4 files changed, 92 insertions, 93 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1a6b1cd517c..0abb367f5b8 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,22 @@ | |||
| 1 | 2014-06-05 Michal Nazarewicz <mina86@mina86.com> | 1 | 2014-06-05 Michal Nazarewicz <mina86@mina86.com> |
| 2 | 2 | ||
| 3 | * textmodes/tildify.el (tildify-foreach-region-outside-env): New | ||
| 4 | function which calls a callback on portions of the buffer that are | ||
| 5 | outside of ignored environments. | ||
| 6 | (tildify-build-regexp): Remove function since it is now | ||
| 7 | incorporated in `tildify-foreach-region-outside-env' where it is | ||
| 8 | optimised and simplified by the use of `mapconcat'. | ||
| 9 | (tildify-tildify): Return number of substitutions made so that… | ||
| 10 | (tildify-count): …can be removed. | ||
| 11 | (tildify-find-env): Accept a new PAIRS argument which was | ||
| 12 | previously looked up in `tildify-ignored-environments-alist' each | ||
| 13 | time the function was called. With this change, the lookup is | ||
| 14 | performed only once in `tildify-foreach-region-outside-env'. | ||
| 15 | (tildify-region): Greatly simplify the function since now most of | ||
| 16 | the work is done by `tildify-foreach-region-outside-env'. | ||
| 17 | (tildify-mode-alist): Simplify slightly by avoiding if and setq | ||
| 18 | and instead using or. | ||
| 19 | |||
| 3 | * textmodes/tildify.el (tildify-ignored-environments-alist): | 20 | * textmodes/tildify.el (tildify-ignored-environments-alist): |
| 4 | Optimise environments regexes | 21 | Optimise environments regexes |
| 5 | 22 | ||
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el index 39ccad717d4..50fee2f4b84 100644 --- a/lisp/textmodes/tildify.el +++ b/lisp/textmodes/tildify.el | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | ;; Copyright (C) 1997-2014 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1997-2014 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Milan Zamazal <pdm@zamazal.org> | 5 | ;; Author: Milan Zamazal <pdm@zamazal.org> |
| 6 | ;; Version: 4.5.2 | 6 | ;; Michal Nazarewicz <mina86@mina86.com> |
| 7 | ;; Version: 4.5.3 | ||
| 7 | ;; Keywords: text, TeX, SGML, wp | 8 | ;; Keywords: text, TeX, SGML, wp |
| 8 | 9 | ||
| 9 | ;; This file is part of GNU Emacs. | 10 | ;; This file is part of GNU Emacs. |
| @@ -187,12 +188,6 @@ END-REGEX defines end of the corresponding text part and can be either: | |||
| 187 | (symbol :tag "Like other"))))) | 188 | (symbol :tag "Like other"))))) |
| 188 | 189 | ||
| 189 | 190 | ||
| 190 | ;;; *** Internal variables *** | ||
| 191 | |||
| 192 | (defvar tildify-count nil | ||
| 193 | "Counter for replacements.") | ||
| 194 | |||
| 195 | |||
| 196 | ;;; *** Interactive functions *** | 191 | ;;; *** Interactive functions *** |
| 197 | 192 | ||
| 198 | ;;;###autoload | 193 | ;;;###autoload |
| @@ -205,51 +200,16 @@ This function performs no refilling of the changed text. | |||
| 205 | If DONT-ASK is set, or called interactively with prefix argument, user | 200 | If DONT-ASK is set, or called interactively with prefix argument, user |
| 206 | won't be prompted for confirmation of each substitution." | 201 | won't be prompted for confirmation of each substitution." |
| 207 | (interactive "*rP") | 202 | (interactive "*rP") |
| 208 | (setq tildify-count 0) | 203 | (let (case-fold-search (count 0) (ask (not dont-ask))) |
| 209 | (let (a | 204 | (tildify-foreach-region-outside-env beg end |
| 210 | z | 205 | (lambda (beg end) |
| 211 | (marker-end (copy-marker end)) | 206 | (let ((aux (tildify-tildify beg end ask))) |
| 212 | end-env | 207 | (setq count (+ count (car aux))) |
| 213 | finish | 208 | (if (not (eq (cdr aux) 'force)) |
| 214 | (ask (not dont-ask)) | 209 | (cdr aux) |
| 215 | (case-fold-search nil) | 210 | (setq ask nil) |
| 216 | (regexp (tildify-build-regexp)) ; beginnings of environments | 211 | t)))) |
| 217 | aux) | 212 | (message "%d spaces replaced." count))) |
| 218 | (if regexp | ||
| 219 | ;; Yes, ignored environments exist for the current major mode, | ||
| 220 | ;; tildify just texts outside them | ||
| 221 | (save-excursion | ||
| 222 | (save-restriction | ||
| 223 | (widen) | ||
| 224 | (goto-char (point-min)) | ||
| 225 | (while (not finish) | ||
| 226 | (setq a (point)) | ||
| 227 | (setq end-env (tildify-find-env regexp)) | ||
| 228 | (setq z (copy-marker (if end-env (1- (point)) (point-max)))) | ||
| 229 | (if (>= (marker-position z) beg) | ||
| 230 | (progn | ||
| 231 | (or (>= a beg) (setq a beg)) | ||
| 232 | (or (<= (marker-position z) (marker-position marker-end)) | ||
| 233 | (setq z marker-end)) | ||
| 234 | (setq aux (tildify-tildify a (marker-position z) ask)) | ||
| 235 | (if (eq aux 'force) | ||
| 236 | (setq ask nil) | ||
| 237 | (if (eq aux nil) | ||
| 238 | (setq finish t))))) | ||
| 239 | (if (>= (marker-position z) (marker-position marker-end)) | ||
| 240 | (setq finish t)) | ||
| 241 | (or (>= (point) (marker-position z)) | ||
| 242 | (goto-char (marker-position z))) | ||
| 243 | (if (not finish) | ||
| 244 | (if (re-search-forward end-env nil t) | ||
| 245 | (if (> (point) (marker-position marker-end)) | ||
| 246 | (setq finish t)) | ||
| 247 | (message | ||
| 248 | "End of environment not found: %s" end-env) | ||
| 249 | (setq finish t)))))) | ||
| 250 | ;; No ignored environments, tildify directly | ||
| 251 | (tildify-tildify beg end ask))) | ||
| 252 | (message "%d spaces replaced." tildify-count)) | ||
| 253 | 213 | ||
| 254 | ;;;###autoload | 214 | ;;;###autoload |
| 255 | (defun tildify-buffer (&optional dont-ask) | 215 | (defun tildify-buffer (&optional dont-ask) |
| @@ -266,42 +226,58 @@ won't be prompted for confirmation of each substitution." | |||
| 266 | 226 | ||
| 267 | ;;; *** Auxiliary functions *** | 227 | ;;; *** Auxiliary functions *** |
| 268 | 228 | ||
| 269 | (defun tildify-build-regexp () | ||
| 270 | "Build start of environment regexp." | ||
| 271 | (let ((alist (tildify-mode-alist tildify-ignored-environments-alist)) | ||
| 272 | regexp) | ||
| 273 | (when alist | ||
| 274 | (setq regexp (caar alist)) | ||
| 275 | (setq alist (cdr alist)) | ||
| 276 | (while alist | ||
| 277 | (setq regexp (concat regexp "\\|" (caar alist))) | ||
| 278 | (setq alist (cdr alist))) | ||
| 279 | regexp))) | ||
| 280 | |||
| 281 | (defun tildify-mode-alist (mode-alist &optional mode) | 229 | (defun tildify-mode-alist (mode-alist &optional mode) |
| 282 | "Return alist item for the MODE-ALIST in the current major MODE." | 230 | "Return alist item for the MODE-ALIST in the current major MODE." |
| 283 | (if (null mode) | 231 | (let ((alist (cdr (or (assoc (or mode major-mode) mode-alist) |
| 284 | (setq mode major-mode)) | ||
| 285 | (let ((alist (cdr (or (assoc mode mode-alist) | ||
| 286 | (assoc t mode-alist))))) | 232 | (assoc t mode-alist))))) |
| 287 | (if (and alist | 233 | (if (and alist |
| 288 | (symbolp alist)) | 234 | (symbolp alist)) |
| 289 | (tildify-mode-alist mode-alist alist) | 235 | (tildify-mode-alist mode-alist alist) |
| 290 | alist))) | 236 | alist))) |
| 291 | 237 | ||
| 292 | (defun tildify-find-env (regexp) | 238 | (defun tildify-foreach-region-outside-env (beg end callback) |
| 239 | "Scan region from BEG to END calling CALLBACK on portions out of environments. | ||
| 240 | Call CALLBACK on each region outside of environment to ignore. | ||
| 241 | CALLBACK will only be called for regions which have intersection | ||
| 242 | with [BEG END]. It must be a function that takes two point | ||
| 243 | arguments specifying the region to operate on. Stop scanning the | ||
| 244 | region as soon as CALLBACK returns nil. Environments to ignore | ||
| 245 | are determined from `tildify-ignored-environments-alist'." | ||
| 246 | (declare (indent 2)) | ||
| 247 | (let ((pairs (tildify-mode-alist tildify-ignored-environments-alist))) | ||
| 248 | (if (not pairs) | ||
| 249 | (funcall callback beg end) | ||
| 250 | (let ((func (lambda (b e) | ||
| 251 | (let ((b (max b beg)) (e (min e end))) | ||
| 252 | (if (< b e) (funcall callback b e) t)))) | ||
| 253 | (beg-re (concat "\\(?:" | ||
| 254 | (mapconcat 'car pairs "\\)\\|\\(?:") | ||
| 255 | "\\)")) | ||
| 256 | p end-re) | ||
| 257 | (save-excursion | ||
| 258 | (save-restriction | ||
| 259 | (widen) | ||
| 260 | (goto-char (point-min)) | ||
| 261 | (while (and (< (setq p (point)) end) | ||
| 262 | (if (not (setq end-re | ||
| 263 | (tildify-find-env beg-re pairs))) | ||
| 264 | (progn (funcall func p end) nil) | ||
| 265 | (funcall func p (match-beginning 0)) | ||
| 266 | (when (< (point) end) | ||
| 267 | (setq p (point)) | ||
| 268 | (re-search-forward end-re nil t))))))))))) | ||
| 269 | |||
| 270 | (defun tildify-find-env (regexp pairs) | ||
| 293 | "Find environment using REGEXP. | 271 | "Find environment using REGEXP. |
| 294 | Return regexp for the end of the environment or nil if no environment was | 272 | Return regexp for the end of the environment found in PAIRS or nil if |
| 295 | found." | 273 | no environment was found." |
| 296 | ;; Find environment | 274 | ;; Find environment |
| 297 | (when (re-search-forward regexp nil t) | 275 | (when (re-search-forward regexp nil t) |
| 298 | (save-match-data | 276 | (save-match-data |
| 299 | ;; Build end-env regexp | 277 | (let ((match (match-string 0))) |
| 300 | (let ((match (match-string 0)) | 278 | (while (not (eq (string-match (caar pairs) match) 0)) |
| 301 | (alist (tildify-mode-alist tildify-ignored-environments-alist))) | 279 | (setq pairs (cdr pairs))) |
| 302 | (while (not (eq (string-match (caar alist) match) 0)) | 280 | (let ((expression (cdar pairs))) |
| 303 | (setq alist (cdr alist))) | ||
| 304 | (let ((expression (cdar alist))) | ||
| 305 | (if (stringp expression) | 281 | (if (stringp expression) |
| 306 | expression | 282 | expression |
| 307 | (mapconcat | 283 | (mapconcat |
| @@ -319,8 +295,9 @@ macros. | |||
| 319 | 295 | ||
| 320 | If ASK is nil, perform replace without asking user for confirmation. | 296 | If ASK is nil, perform replace without asking user for confirmation. |
| 321 | 297 | ||
| 322 | Returns one of symbols: t (all right), nil (quit), force (replace without | 298 | Returns (count . response) cons where count is number of string |
| 323 | further questions)." | 299 | replacements done and response is one of symbols: t (all right), nil |
| 300 | (quit), force (replace without further questions)." | ||
| 324 | (save-excursion | 301 | (save-excursion |
| 325 | (goto-char beg) | 302 | (goto-char beg) |
| 326 | (let* ((alist (tildify-mode-alist tildify-pattern-alist)) | 303 | (let* ((alist (tildify-mode-alist tildify-pattern-alist)) |
| @@ -332,7 +309,8 @@ further questions)." | |||
| 332 | bad-answer | 309 | bad-answer |
| 333 | replace | 310 | replace |
| 334 | quit | 311 | quit |
| 335 | (message-log-max nil)) | 312 | (message-log-max nil) |
| 313 | (count 0)) | ||
| 336 | (while (and (not quit) | 314 | (while (and (not quit) |
| 337 | (re-search-forward regexp (marker-position end-marker) t)) | 315 | (re-search-forward regexp (marker-position end-marker) t)) |
| 338 | (when (or (not ask) | 316 | (when (or (not ask) |
| @@ -359,12 +337,11 @@ further questions)." | |||
| 359 | (setq bad-answer t))) | 337 | (setq bad-answer t))) |
| 360 | replace)) | 338 | replace)) |
| 361 | (replace-match tilde t t nil match-number) | 339 | (replace-match tilde t t nil match-number) |
| 362 | (setq tildify-count (1+ tildify-count)))) | 340 | (setq count (1+ count)))) |
| 363 | ;; Return value | 341 | ;; Return value |
| 364 | (cond | 342 | (cons count (cond (quit nil) |
| 365 | (quit nil) | 343 | ((not ask) 'force) |
| 366 | ((not ask) 'force) | 344 | (t t)))))) |
| 367 | (t t))))) | ||
| 368 | 345 | ||
| 369 | 346 | ||
| 370 | ;;; *** Announce *** | 347 | ;;; *** Announce *** |
diff --git a/test/ChangeLog b/test/ChangeLog index 38a4feb528f..6248d6cb9a6 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,5 +1,11 @@ | |||
| 1 | 2014-06-05 Michal Nazarewicz <mina86@mina86.com> | 1 | 2014-06-05 Michal Nazarewicz <mina86@mina86.com> |
| 2 | 2 | ||
| 3 | * automated/tildify-tests.el (tildify-test-find-env-end-re-bug) | ||
| 4 | (tildify-test-find-env-group-index-bug): Update to support new | ||
| 5 | signature of the `tildify-foreach-region-outside-env' function. | ||
| 6 | Namely, it now takes pairs as an argument instead of looking it up in | ||
| 7 | `tildify-ignored-environments-alist'. | ||
| 8 | |||
| 3 | * automated/tildify-tests.el (tildify-test--example-html): Add support | 9 | * automated/tildify-tests.el (tildify-test--example-html): Add support |
| 4 | for generating XML code, so that… | 10 | for generating XML code, so that… |
| 5 | (tildify-test-xml) …test can be added to check handling of XML | 11 | (tildify-test-xml) …test can be added to check handling of XML |
diff --git a/test/automated/tildify-tests.el b/test/automated/tildify-tests.el index dd404fcac22..cf18320030d 100644 --- a/test/automated/tildify-tests.el +++ b/test/automated/tildify-tests.el | |||
| @@ -114,23 +114,22 @@ latter is missing, SENTENCE will be used in all placeholder positions." | |||
| 114 | (ert-deftest tildify-test-find-env-end-re-bug () | 114 | (ert-deftest tildify-test-find-env-end-re-bug () |
| 115 | "Tests generation of end-regex using mix of indexes and strings" | 115 | "Tests generation of end-regex using mix of indexes and strings" |
| 116 | (with-temp-buffer | 116 | (with-temp-buffer |
| 117 | (let ((tildify-ignored-environments-alist | 117 | (insert "foo whatever end-foo") |
| 118 | `((,major-mode ("foo\\|bar" . ("end-" 0)))))) | 118 | (goto-char (point-min)) |
| 119 | (insert "foo whatever end-foo") | 119 | (should (string-equal "end-foo" |
| 120 | (goto-char (point-min)) | 120 | (tildify-find-env "foo\\|bar" |
| 121 | (should (string-equal "end-foo" (tildify-find-env "foo\\|bar")))))) | 121 | '(("foo\\|bar" . ("end-" 0)))))))) |
| 122 | 122 | ||
| 123 | 123 | ||
| 124 | (ert-deftest tildify-test-find-env-group-index-bug () | 124 | (ert-deftest tildify-test-find-env-group-index-bug () |
| 125 | "Tests generation of match-string indexes" | 125 | "Tests generation of match-string indexes" |
| 126 | (with-temp-buffer | 126 | (with-temp-buffer |
| 127 | (let ((tildify-ignored-environments-alist | 127 | (let ((pairs '(("start-\\(foo\\|bar\\)" . ("end-" 1)) |
| 128 | `((,major-mode ("start-\\(foo\\|bar\\)" . ("end-" 1)) | 128 | ("open-\\(foo\\|bar\\)" . ("close-" 1)))) |
| 129 | ("open-\\(foo\\|bar\\)" . ("close-" 1))))) | ||
| 130 | (beg-re "start-\\(foo\\|bar\\)\\|open-\\(foo\\|bar\\)")) | 129 | (beg-re "start-\\(foo\\|bar\\)\\|open-\\(foo\\|bar\\)")) |
| 131 | (insert "open-foo whatever close-foo") | 130 | (insert "open-foo whatever close-foo") |
| 132 | (goto-char (point-min)) | 131 | (goto-char (point-min)) |
| 133 | (should (string-equal "close-foo" (tildify-find-env beg-re)))))) | 132 | (should (string-equal "close-foo" (tildify-find-env beg-re pairs)))))) |
| 134 | 133 | ||
| 135 | 134 | ||
| 136 | (provide 'tildify-tests) | 135 | (provide 'tildify-tests) |