summaryrefslogtreecommitdiff
path: root/lisp/textmodes/tildify.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/textmodes/tildify.el')
-rw-r--r--lisp/textmodes/tildify.el263
1 files changed, 132 insertions, 131 deletions
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index 9732e7fa649..50fee2f4b84 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -3,7 +3,8 @@
;; Copyright (C) 1997-2014 Free Software Foundation, Inc.
;; Author: Milan Zamazal <pdm@zamazal.org>
-;; Version: 4.5
+;; Michal Nazarewicz <mina86@mina86.com>
+;; Version: 4.5.3
;; Keywords: text, TeX, SGML, wp
;; This file is part of GNU Emacs.
@@ -77,15 +78,22 @@ by the hard space character.
The form (MAJOR-MODE . SYMBOL) defines alias item for MAJOR-MODE. For this
mode, the item for the mode SYMBOL is looked up in the alist instead."
:group 'tildify
- :type '(repeat (choice (list symbol regexp integer) (cons symbol symbol))))
+ :type '(repeat (cons :tag "Entry for major mode"
+ (choice (const :tag "Default" t)
+ (symbol :tag "Major mode"))
+ (choice (list :tag "Regexp"
+ regexp
+ (integer :tag "Group "))
+ (symbol :tag "Like other")))))
(defcustom tildify-string-alist
'((latex-mode . "~")
(tex-mode . latex-mode)
(plain-tex-mode . latex-mode)
(sgml-mode . "&nbsp;")
- (xml-mode . sgml-mode)
(html-mode . sgml-mode)
+ (xml-mode . "&#160;") ; XML does not define &nbsp; use numeric reference
+ (nxml-mode . xml-mode)
(t . " "))
"Alist specifying what is a hard space in the current major mode.
@@ -104,41 +112,43 @@ for SGML.
The form (MAJOR-MODE . SYMBOL) defines alias item for MAJOR-MODE. For this
mode, the item for the mode SYMBOL is looked up in the alist instead."
:group 'tildify
- :type '(repeat (cons symbol (choice string symbol))))
+ :type '(repeat (cons :tag "Entry for major mode"
+ (choice (const :tag "Default" t)
+ (symbol :tag "Major mode"))
+ (choice (const :tag "No-break space (U+00A0)" "\u00A0")
+ (string :tag "String ")
+ (symbol :tag "Like other")))))
(defcustom tildify-ignored-environments-alist
- '((latex-mode
+ `((latex-mode
("\\\\\\\\" . "") ; do not remove this
- ("\\\\begin{verbatim}" . "\\\\end{verbatim}")
+ (,(eval-when-compile (concat
+ "\\\\begin{\\("
+ (regexp-opt '("verbatim" "math" "displaymath"
+ "equation" "eqnarray" "eqnarray*"))
+ "\\)}"))
+ . ("\\\\end{" 1 "}"))
("\\\\verb\\*?\\(.\\)" . (1))
- ("\\$\\$" . "\\$\\$")
- ("\\$" . "\\$")
+ ("\\$\\$?" . (0))
("\\\\(" . "\\\\)")
("\\\\[[]" . "\\\\[]]")
- ("\\\\begin{math}" . "\\\\end{math}")
- ("\\\\begin{displaymath}" . "\\\\end{displaymath}")
- ("\\\\begin{equation}" . "\\\\end{equation}")
- ("\\\\begin{eqnarray\\*?}" . "\\\\end{eqnarray\\*?}")
("\\\\[a-zA-Z]+\\( +\\|{}\\)[a-zA-Z]*" . "")
("%" . "$"))
(plain-tex-mode . latex-mode)
(html-mode
- ("<pre[^>]*>" . "</pre>")
- ("<dfn>" . "</dfn>")
- ("<code>" . "</code>")
- ("<samp>" . "</samp>")
- ("<kbd>" . "</kbd>")
- ("<var>" . "</var>")
- ("<PRE[^>]*>" . "</PRE>")
- ("<DFN>" . "</DFN>")
- ("<CODE>" . "</CODE>")
- ("<SAMP>" . "</SAMP>")
- ("<KBD>" . "</KBD>")
- ("<VAR>" . "</VAR>")
+ (,(eval-when-compile (concat
+ "<\\("
+ (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var"
+ "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR"))
+ "\\)\\>[^>]*>"))
+ . ("</" 1 ">"))
("<! *--" . "-- *>")
("<" . ">"))
(sgml-mode . html-mode)
- (t nil))
+ (xml-mode
+ ("<! *--" . "-- *>")
+ ("<" . ">"))
+ (nxml-mode . xml-mode))
"Alist specifying ignored structured text environments.
Parts of text defined in this alist are skipped without performing hard space
insertion on them. These setting allow skipping text parts like verbatim or
@@ -160,133 +170,123 @@ END-REGEX defines end of the corresponding text part and can be either:
subexpressions of BEG-REGEX (this is used to solve cases like
\\\\verb<character> in TeX)."
:group 'tildify
- :type '(repeat (cons symbol (choice symbol (repeat sexp)))))
-
-
-;;; *** Internal variables ***
-
-(defvar tildify-count nil
- "Counter for replacements.")
+ :type '(repeat
+ (cons :tag "Entry for major mode"
+ (choice (const :tag "Default" t)
+ (symbol :tag "Major mode"))
+ (choice
+ (const :tag "None")
+ (repeat
+ :tag "Environments"
+ (cons :tag "Regexp pair"
+ (regexp :tag "Open ")
+ (choice :tag "Close"
+ (regexp :tag "Regexp")
+ (list :tag "Regexp and groups (concatenated)"
+ (choice (regexp :tag "Regexp")
+ (integer :tag "Group "))))))
+ (symbol :tag "Like other")))))
;;; *** Interactive functions ***
;;;###autoload
-(defun tildify-region (beg end)
+(defun tildify-region (beg end &optional dont-ask)
"Add hard spaces in the region between BEG and END.
See variables `tildify-pattern-alist', `tildify-string-alist', and
`tildify-ignored-environments-alist' for information about configuration
parameters.
-This function performs no refilling of the changed text."
- (interactive "*r")
- (setq tildify-count 0)
- (let (a
- z
- (marker-end (copy-marker end))
- end-env
- finish
- (ask t)
- (case-fold-search nil)
- (regexp (tildify-build-regexp)) ; beginnings of environments
- aux)
- (if regexp
- ;; Yes, ignored environments exist for the current major mode,
- ;; tildify just texts outside them
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (while (not finish)
- (setq a (point))
- (setq end-env (tildify-find-env regexp))
- (setq z (copy-marker (if end-env (1- (point)) (point-max))))
- (if (>= (marker-position z) beg)
- (progn
- (or (>= a beg) (setq a beg))
- (or (<= (marker-position z) (marker-position marker-end))
- (setq z marker-end))
- (setq aux (tildify-tildify a (marker-position z) ask))
- (if (eq aux 'force)
- (setq ask nil)
- (if (eq aux nil)
- (setq finish t)))))
- (if (>= (marker-position z) (marker-position marker-end))
- (setq finish t))
- (or (>= (point) (marker-position z))
- (goto-char (marker-position z)))
- (if (not finish)
- (if (re-search-forward end-env nil t)
- (if (> (point) (marker-position marker-end))
- (setq finish t))
- (message
- "End of environment not found: %s" end-env)
- (setq finish t))))))
- ;; No ignored environments, tildify directly
- (tildify-tildify beg end ask)))
- (message "%d spaces replaced." tildify-count))
+This function performs no refilling of the changed text.
+If DONT-ASK is set, or called interactively with prefix argument, user
+won't be prompted for confirmation of each substitution."
+ (interactive "*rP")
+ (let (case-fold-search (count 0) (ask (not dont-ask)))
+ (tildify-foreach-region-outside-env beg end
+ (lambda (beg end)
+ (let ((aux (tildify-tildify beg end ask)))
+ (setq count (+ count (car aux)))
+ (if (not (eq (cdr aux) 'force))
+ (cdr aux)
+ (setq ask nil)
+ t))))
+ (message "%d spaces replaced." count)))
;;;###autoload
-(defun tildify-buffer ()
+(defun tildify-buffer (&optional dont-ask)
"Add hard spaces in the current buffer.
See variables `tildify-pattern-alist', `tildify-string-alist', and
`tildify-ignored-environments-alist' for information about configuration
parameters.
-This function performs no refilling of the changed text."
- (interactive "*")
- (tildify-region (point-min) (point-max)))
+This function performs no refilling of the changed text.
+If DONT-ASK is set, or called interactively with prefix argument, user
+won't be prompted for confirmation of each substitution."
+ (interactive "*P")
+ (tildify-region (point-min) (point-max) dont-ask))
;;; *** Auxiliary functions ***
-(defun tildify-build-regexp ()
- "Build start of environment regexp."
- (let ((alist (tildify-mode-alist tildify-ignored-environments-alist))
- regexp)
- (when alist
- (setq regexp (caar alist))
- (setq alist (cdr alist))
- (while alist
- (setq regexp (concat regexp "\\|" (caar alist)))
- (setq alist (cdr alist)))
- regexp)))
-
(defun tildify-mode-alist (mode-alist &optional mode)
"Return alist item for the MODE-ALIST in the current major MODE."
- (if (null mode)
- (setq mode major-mode))
- (let ((alist (cdr (or (assoc mode mode-alist)
+ (let ((alist (cdr (or (assoc (or mode major-mode) mode-alist)
(assoc t mode-alist)))))
(if (and alist
(symbolp alist))
(tildify-mode-alist mode-alist alist)
alist)))
-(defun tildify-find-env (regexp)
+(defun tildify-foreach-region-outside-env (beg end callback)
+ "Scan region from BEG to END calling CALLBACK on portions out of environments.
+Call CALLBACK on each region outside of environment to ignore.
+CALLBACK will only be called for regions which have intersection
+with [BEG END]. It must be a function that takes two point
+arguments specifying the region to operate on. Stop scanning the
+region as soon as CALLBACK returns nil. Environments to ignore
+are determined from `tildify-ignored-environments-alist'."
+ (declare (indent 2))
+ (let ((pairs (tildify-mode-alist tildify-ignored-environments-alist)))
+ (if (not pairs)
+ (funcall callback beg end)
+ (let ((func (lambda (b e)
+ (let ((b (max b beg)) (e (min e end)))
+ (if (< b e) (funcall callback b e) t))))
+ (beg-re (concat "\\(?:"
+ (mapconcat 'car pairs "\\)\\|\\(?:")
+ "\\)"))
+ p end-re)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (while (and (< (setq p (point)) end)
+ (if (not (setq end-re
+ (tildify-find-env beg-re pairs)))
+ (progn (funcall func p end) nil)
+ (funcall func p (match-beginning 0))
+ (when (< (point) end)
+ (setq p (point))
+ (re-search-forward end-re nil t)))))))))))
+
+(defun tildify-find-env (regexp pairs)
"Find environment using REGEXP.
-Return regexp for the end of the environment or nil if no environment was
-found."
+Return regexp for the end of the environment found in PAIRS or nil if
+no environment was found."
;; Find environment
- (if (re-search-forward regexp nil t)
- ;; Build end-env regexp
- (let ((match (match-string 0))
- (alist (tildify-mode-alist tildify-ignored-environments-alist))
- expression)
- (save-match-data
- (while (not (eq (string-match (caar alist) match) 0))
- (setq alist (cdr alist))))
- (if (stringp (setq expression (cdar alist)))
- expression
- (let ((result "")
- aux)
- (while expression
- (setq result (concat result
- (if (stringp (setq aux (car expression)))
- expression
- (regexp-quote (match-string aux)))))
- (setq expression (cdr expression)))
- result)))
- ;; Return nil if not found
- nil))
+ (when (re-search-forward regexp nil t)
+ (save-match-data
+ (let ((match (match-string 0)))
+ (while (not (eq (string-match (caar pairs) match) 0))
+ (setq pairs (cdr pairs)))
+ (let ((expression (cdar pairs)))
+ (if (stringp expression)
+ expression
+ (mapconcat
+ (lambda (expr)
+ (if (stringp expr)
+ expr
+ (regexp-quote (match-string expr match))))
+ expression
+ "")))))))
(defun tildify-tildify (beg end ask)
"Add tilde characters in the region between BEG and END.
@@ -295,8 +295,9 @@ macros.
If ASK is nil, perform replace without asking user for confirmation.
-Returns one of symbols: t (all right), nil (quit), force (replace without
-further questions)."
+Returns (count . response) cons where count is number of string
+replacements done and response is one of symbols: t (all right), nil
+(quit), force (replace without further questions)."
(save-excursion
(goto-char beg)
(let* ((alist (tildify-mode-alist tildify-pattern-alist))
@@ -308,7 +309,8 @@ further questions)."
bad-answer
replace
quit
- (message-log-max nil))
+ (message-log-max nil)
+ (count 0))
(while (and (not quit)
(re-search-forward regexp (marker-position end-marker) t))
(when (or (not ask)
@@ -335,12 +337,11 @@ further questions)."
(setq bad-answer t)))
replace))
(replace-match tilde t t nil match-number)
- (setq tildify-count (1+ tildify-count))))
+ (setq count (1+ count))))
;; Return value
- (cond
- (quit nil)
- ((not ask) 'force)
- (t t)))))
+ (cons count (cond (quit nil)
+ ((not ask) 'force)
+ (t t))))))
;;; *** Announce ***