branch: externals/tex-parens
commit 145e9eafc4f196714d713f00c3626a17135a9fb8
Author: Paul Nelson <[email protected]>
Commit: Paul Nelson <[email protected]>
lots of cleanup, support for $\text{..$..$..}$, etc
---
tex-parens.el | 663 +++++++++++++++++++++++++++++++++-------------------------
1 file changed, 376 insertions(+), 287 deletions(-)
diff --git a/tex-parens.el b/tex-parens.el
index 0e752f1f2d..74f0eb17c3 100644
--- a/tex-parens.el
+++ b/tex-parens.el
@@ -20,9 +20,16 @@
;;; Commentary:
-;; This package provides sexp and list-based navigation, much like
-;; those in lisp.el, but for tex modes, tailored to my use cases
-;; (cf. https://github.com/Fuco1/smartparens/issues/1193).
+;; This package provides commands for working with lists, sexps and
+;; defuns, much like those in lisp.el, but for tex buffers. Here, the
+;; role of parentheses is played by begin/end blocks, math delimiters
+;; and mathematical parenthesis-like constructions (e.g.,
+;; langle/rangle), together with their tex modifiers (e.g.,
+;; left/right, bigl/bigr). See README.org for more details.
+
+;; There are many packages that aim to provide such features for
+;; general modes, but I was unable to find one that provides the
+;; desired functionality for the special case of tex buffers.
;; Sample configuration:
;;
@@ -31,376 +38,461 @@
;; :depth nil)
;; :bind
;; (:map LaTeX-mode-map
-;; ("C-M-f" . tex-parens-forward-sexp)
-;; ("C-M-b" . tex-parens-backward-sexp)
-;; ("C-M-n" . tex-parens-forward-list)
-;; ("C-M-p" . tex-parens-backward-list)
-;; ("C-M-u" . tex-parens-backward-up-list)
-;; ("M-u" . tex-parens-up-list)
-;; ("C-M-g" . tex-parens-down-list)
-;; ("M-_" . tex-parens-delete-pair)
-;; ("C-M-SPC" . tex-parens-mark-sexp)
-;; ("C-M-k" . tex-parens-kill-sexp)
+;; ("C-M-f" . tp-forward-sexp)
+;; ("C-M-b" . tp-backward-sexp)
+;; ("C-M-n" . tp-forward-list)
+;; ("C-M-p" . tp-backward-list)
+;; ("C-M-u" . tp-backward-up-list)
+;; ("M-u" . tp-up-list)
+;; ("C-M-g" . tp-down-list)
+;; ("M-_" . tp-delete-pair)
+;; ("C-M-SPC" . tp-mark-sexp)
+;; ("C-M-k" . tp-kill-sexp)
;; ("C-M-t" . transpose-sexps)
-;; ("C-M-<backspace>" . tex-parens-backward-kill-sexp)
-;; ("M-+" . tex-parens-raise-sexp))
+;; ("C-M-<backspace>" . tp-backward-kill-sexp)
+;; ("M-+" . tp-raise-sexp))
;; :hook
-;; (LaTeX-mode . tex-parens-setup))
+;; (LaTeX-mode . tp-setup))
;;; Code:
(require 'cl-lib)
-(defun tex-parens--beginning-of-defun ()
+(defgroup tex-parens nil
+ "Like lisp.el but for tex."
+ :group 'tex
+ :prefix "tp-")
+
+(defun tp--beginning-of-defun ()
"Move to the beginning of the current defun.
Here `defun' means top-level environment."
(interactive)
(re-search-backward "^\\\\begin{[^}]+}" nil t))
-(defun tex-parens--end-of-defun ()
+(defun tp--end-of-defun ()
"Move to the end of the current defun.
Here `defun' means top-level environment."
(interactive)
(re-search-forward "^\\\\end{[^}]+}\n" nil t))
-(defun tex-parens--generate-pairs ()
- "Generate list of left/right pairs of delimiters."
- (let ((unambiguous-parens
- '(("(" . ")")
- ("[" . "]")
- ("\\{" . "\\}")
- ("\\langle" . "\\rangle")
- ("\\lvert" . "\\rvert")
- ("\\lVert" . "\\rVert")
- ("\\lfloor" . "\\rfloor")
- ("\\lceil" . "\\rceil")))
- (ambiguous-parens
- '("|" "\\|" "\\vert" "\\Vert"))
- (unambiguous-modifiers
- '(("\\left" . "\\right")
- ("\\bigl" . "\\bigr")
- ("\\Bigl" . "\\Bigr")
- ("\\biggl" . "\\biggr")
- ("\\Biggl" . "\\Biggr")))
- (ambiguous-modifiers
- '("\\big" "\\Big" "\\bigg" "\\Bigg"))
- (other-parens
- '(("``" . "''")
- ("$" . "$")
- ("{" . "}")
- ("$$" . "$$")
- ("\\(" . "\\)")
- ("\\[" . "\\]")
- ("\\left." . "\\right."))))
+(defcustom tp-left-right-delimiter-pairs
+ '(("(" . ")")
+ ("[" . "]")
+ ("\\{" . "\\}")
+ ("\\langle" . "\\rangle")
+ ("\\lvert" . "\\rvert")
+ ("\\lVert" . "\\rVert")
+ ("\\lfloor" . "\\rfloor")
+ ("\\lceil" . "\\rceil"))
+ "Left/right pairs of delimiters."
+ :type '(repeat (cons string string)))
+
+(defcustom tp-solo-delimiters
+ '("|" "\\|" "\\vert" "\\Vert")
+ "Delimiters that do come in pairs."
+ :type '(repeat string))
+
+(defcustom tp-left-right-modifier-pairs
+ '(("\\left" . "\\right")
+ ("\\bigl" . "\\bigr")
+ ("\\Bigl" . "\\Bigr")
+ ("\\biggl" . "\\biggr")
+ ("\\Biggl" . "\\Biggr"))
+ "Left/right pairs of delimiter modifiers."
+ :type '(repeat (cons string string)))
+
+(defcustom tp-solo-modifiers
+ '("\\big" "\\Big" "\\bigg" "\\Bigg")
+ "Delimiter modifiers that do not come in pairs."
+ :type '(repeat string))
+
+(defcustom tp-other-parens
+ '(("``" . "''")
+ ("{" . "}")
+ ("\\(" . "\\)")
+ ("\\[" . "\\]")
+ ("\\left." . "\\right."))
+ "Left/right delimiters not to be combined with modifiers."
+ :type '(repeat (cons string string)))
+
+(defun tp--reduce-append (func list1 list2)
+ "List consisting of FUNC applied to pairs from LIST1 and LIST2."
+ (cl-reduce #'append
+ (mapcar (lambda (item1)
+ (mapcar (lambda (item2)
+ (funcall func item1 item2))
+ list2))
+ list1)))
+
+(defun tp--generate-pairs ()
+ "Generate list of left/right pairs of delimiters.
+With the exception of the math delimiters `$' and `$$', we only
+form delimiters which are visibly `left'/`opening' or
+`right'/`closing'."
+ (let ((unambiguous-parens tp-left-right-delimiter-pairs)
+ (ambiguous-parens tp-solo-delimiters)
+ (unambiguous-modifiers tp-left-right-modifier-pairs)
+ (ambiguous-modifiers tp-solo-modifiers))
(append
- other-parens unambiguous-parens
- (cl-reduce #'append
- (mapcar
- (lambda (unam-par)
- (mapcar
- (lambda (unam-mod)
- (cons (concat (car unam-mod) (car unam-par))
- (concat (cdr unam-mod) (cdr unam-par))))
- unambiguous-modifiers))
- unambiguous-parens))
- (cl-reduce #'append
- (mapcar
- (lambda (unam-par)
- (mapcar
- (lambda (am-mod)
- (cons (concat am-mod (car unam-par))
- (concat am-mod (cdr unam-par))))
- ambiguous-modifiers))
- unambiguous-parens))
- (cl-reduce #'append
- (mapcar
- (lambda (am-par)
- (mapcar
- (lambda (unam-mod)
- (cons (concat (car unam-mod) am-par)
- (concat (cdr unam-mod) am-par)))
- unambiguous-modifiers))
- ambiguous-parens)))))
-
-(defvar tex-parens--pairs nil)
-(defvar tex-parens--pairs-swap nil)
-(defvar tex-parens--delims nil)
-(defvar tex-parens--regexp nil)
-(defvar tex-parens--regexp-reverse nil)
+ tp-other-parens
+ '(("$" . "$")
+ ("$$" . "$$"))
+ unambiguous-parens
+ (tp--reduce-append
+ (lambda (up um)
+ (cons (concat (car um) (car up))
+ (concat (cdr um) (cdr up))))
+ unambiguous-parens unambiguous-modifiers)
+ (tp--reduce-append
+ (lambda (up m)
+ (cons (concat m (car up))
+ (concat m (cdr up))))
+ unambiguous-parens ambiguous-modifiers)
+ (tp--reduce-append
+ (lambda (p um)
+ (cons (concat (car um) p)
+ (concat (cdr um) p)))
+ ambiguous-parens unambiguous-modifiers))))
+
+(defvar tp--pairs nil)
+(defvar tp--pairs-swap nil)
+(defvar tp--delims nil)
+(defvar tp--regexp nil)
+(defvar tp--regexp-reverse nil)
(defvar preview-auto-reveal)
-(defun tex-parens-setup ()
+(defun tp-setup ()
"Set up tex-parens. Intended as a hook for `LaTeX-mode'."
(setq
preview-auto-reveal
'(eval (preview-arrived-via (key-binding [left])
(key-binding [right])
- #'backward-char #'forward-char
#'tex-parens-down-list)))
- (setq-local beginning-of-defun-function #'tex-parens--beginning-of-defun)
- (setq-local transpose-sexps-default-function
#'tex-parens-transpose-sexps-default-function)
- (setq end-of-defun-function #'tex-parens--end-of-defun)
- (setq tex-parens--pairs (tex-parens--generate-pairs))
- (setq tex-parens--pairs-swap
- (mapcar (lambda (x) (cons (cdr x) (car x))) tex-parens--pairs))
- (setq tex-parens--delims (append (mapcar #'car tex-parens--pairs)
- (mapcar #'cdr tex-parens--pairs)))
- (setq tex-parens--regexp
- (concat (regexp-opt tex-parens--delims)
+ #'backward-char #'forward-char #'tp-down-list)))
+ (setq-local beginning-of-defun-function #'tp--beginning-of-defun)
+ (setq-local transpose-sexps-default-function
#'tp-transpose-sexps-default-function)
+ (setq end-of-defun-function #'tp--end-of-defun)
+ (setq tp--pairs (tp--generate-pairs))
+ (setq tp--pairs-swap
+ (mapcar (lambda (x) (cons (cdr x) (car x))) tp--pairs))
+ (setq tp--delims (append (mapcar #'car tp--pairs)
+ (mapcar #'cdr tp--pairs)))
+ (setq tp--regexp
+ (concat (regexp-opt tp--delims)
"\\|\\\\begin{[^}]+}\\|\\\\end{[^}]+}"))
- (setq tex-parens--regexp-reverse
+ (setq tp--regexp-reverse
(concat "}[^{]+{nigeb\\\\\\|}[^{]+{dne\\\\\\|"
- (regexp-opt (mapcar #'reverse tex-parens--delims))))
+ (regexp-opt (mapcar #'reverse tp--delims))))
;; Don't know why, but Emacs freezes with the following line
;; uncommented. For this reason, we have to go through the
;; awkwardness of duplicating several functions near the bottom of
;; this file.
- ;; (setq-local forward-sexp-function #'tex-parens-forward-sexp)
+ ;; (setq-local forward-sexp-function #'tp-forward-sexp)
)
-(defcustom tex-parens-search-limit 10000
+(defcustom tp-search-limit 10000
"How far to search for a delimiter, in either direction.
This should exceed the length, in characters, of the longest
-theorem-like environments that you encounter in practice."
+theorem-like environments to which you care about applying the
+list and sexp-based navigation commands. Longer environments
+typically occur at the top level and are best navigated using the
+defun-based commands."
:type 'integer
:group 'tex-parens)
-(defun tex-parens--forward-bound ()
+(defun tp--math-face-p ()
+ "Check if point is in a math face."
+ (let ((face (plist-get (text-properties-at (point))
+ 'face)))
+ (cond
+ ((memq face '(tex-math font-latex-math-face))
+ 1)
+ ((listp face)
+ (let ((total 0))
+ (dolist (f face)
+ (when (memq f '(tex-math font-latex-math-face))
+ (setq total (1+ total))))
+ total))
+ (t 0))))
+
+(defcustom tp-ignore-comments t
+ "Whether to ignore comments when searching for delimiters."
+ :type 'boolean
+ :group 'tex-parens)
+
+(defun tp--ignore (m-str m-begin m-end)
+ (or
+ (and
+ tp-ignore-comments
+ (let ((face (plist-get (text-properties-at (point))
+ 'face)))
+ (eq face 'font-lock-comment-face)))
+ (and
+ ;; ignore double prime in math-mode
+ (equal m-str "''")
+ (> (tp--math-face-p) 0))
+ ;; (and
+ ;; ;; ignore dollar signs that don't matter for whatever reason
+ ;; (member m-str '("$" "$$"))
+ ;; (equal
+ ;; (save-excursion
+ ;; (goto-char (1- m-begin))
+ ;; (tp--math-face-p))
+ ;; (save-excursion
+ ;; (goto-char m-end)
+ ;; (tp--math-face-p))))
+ ))
+
+(defun tp--search-forward (regexp bound)
+ (let (success done)
+ (while (not done)
+ (if (re-search-forward regexp bound t)
+ (when (not (tp--ignore (match-string 0)
+ (match-beginning 0)
+ (match-end 0)))
+ (setq done t
+ success t))
+ (setq done t)))
+ (when success
+ (match-string 0))))
+
+(defun tp--search-backward (regexp bound)
+ (let* ((text (buffer-substring bound (point)))
+ (buf (current-buffer))
+ result)
+ (with-temp-buffer
+ (insert (reverse text))
+ (goto-char (point-min))
+ (setq result
+ (let (success done)
+ (while (not done)
+ (if (re-search-forward regexp bound t)
+ (when (not
+ (let ((new-point (point))
+ (m-string (match-string 0))
+ (m-begin (match-beginning 0))
+ (m-end (match-end 0)))
+ (with-current-buffer buf
+ (save-excursion
+ (backward-char (1- new-point))
+ (tp--ignore m-string m-begin m-end)))))
+ (setq done t
+ success t))
+ (setq done t)))
+ (when success
+ (cons (point) (match-string 0))))))
+ (when result
+ (let ((new-point (car result))
+ (match (cdr result)))
+ (backward-char (1- new-point))
+ (reverse match)))))
+
+(defun tp--forward-bound ()
"Return the bound for forward search."
(save-excursion
(min
(point-max)
- (+ (point) tex-parens-search-limit))))
+ (+ (point) tp-search-limit))))
-(defun tex-parens--backward-bound ()
+(defun tp--backward-bound ()
"Return the bound for backward search."
(save-excursion
(max
(point-min)
- (- (point) tex-parens-search-limit))))
+ (- (point) tp-search-limit))))
-(defun tex-parens--forward-delim (&optional bound)
- "Search for the next delimiter up to BOUND."
- (interactive)
- (unless bound (setq bound (tex-parens--forward-bound)))
- (when (re-search-forward tex-parens--regexp bound t)
- (match-string 0)))
+(defun tp--forward-delim (&optional bound)
+ "Search for the next delimiter up to BOUND.
+Return the delimiter found, or nil if none is found."
+ (unless bound (setq bound (tp--forward-bound)))
+ (tp--search-forward tp--regexp bound))
-(defun tex-parens--backward-delim (&optional bound)
- "Search for the previous delimiter up to BOUND."
- (interactive)
- (unless bound (setq bound (tex-parens--backward-bound)))
- (let* ((text (buffer-substring-no-properties bound (point)))
- match result)
- (with-temp-buffer
- (insert (reverse text))
- (goto-char (point-min))
- (setq result (re-search-forward tex-parens--regexp-reverse nil t))
- (when result (setq match (match-string 0))))
- (when result
- (backward-char (1- result))
- (reverse match))))
+(defun tp--backward-delim (&optional bound)
+ "Search for the previous delimiter up to BOUND.
+Return the delimiter found, or nil if none is found."
+ (unless bound (setq bound (tp--backward-bound)))
+ (tp--search-backward tp--regexp-reverse bound))
-(defun tex-parens--close-of-open (delim)
+(defun tp--close-of-open (delim)
"Check if DELIM is opening, return the corresponding closing.
If DELIM is an opening delimiter, return the corresponding closing
delimiter. Otherwise, return nil."
(or
- (cdr (assoc delim tex-parens--pairs))
+ (cdr (assoc delim tp--pairs))
(and (stringp delim)
(string-match "\\\\begin{\\([^}]+\\)}" delim)
(let ((type (match-string 1 delim)))
(format "\\end{%s}" type)))))
-(defun tex-parens--open-of-close (delim)
+(defun tp--open-of-close (delim)
"Check if DELIM is closing, return the corresponding opening.
If DELIM is a closing delimiter, return the corresponding opening
delimiter. Otherwise, return nil."
(or
- (cdr (assoc delim tex-parens--pairs-swap))
+ (cdr (assoc delim tp--pairs-swap))
(and (stringp delim)
(string-match "\\\\end{\\([^}]+\\)}" delim)
(let ((type (match-string 1 delim)))
(format "\\begin{%s}" type)))))
-(defun tex-parens--math-face-p ()
- "Check if point is in a math face."
- (let ((face (plist-get (text-properties-at (point))
- 'face)))
- (or (eq face 'font-latex-math-face)
- (and (listp face)
- (memq 'font-latex-math-face face)))))
-
-(defvar tex-parens--debug nil)
-
-(defun tex-parens-forward-list (&optional bound)
+(defvar tp--debug nil)
+
+(defun tp--forward-search-found-open (delim)
+ "Check if DELIM is an opening delimiter found by forward search."
+ (cond
+ ((member delim '("$" "$$"))
+ (>
+ (tp--math-face-p)
+ (save-excursion
+ (backward-char (1+ (length delim)))
+ (tp--math-face-p))
+ ))
+ (t
+ (tp--close-of-open delim))))
+
+(defun tp--backward-search-found-close (delim)
+ "Check if DELIM is a closing delimiter found by backward search."
+ (cond
+ ((member delim '("$" "$$"))
+ (>
+ (save-excursion
+ (backward-char 1)
+ (tp--math-face-p))
+ (save-excursion
+ (forward-char (length delim))
+ (tp--math-face-p))))
+ (t
+ (tp--open-of-close delim))))
+
+(defun tp--check-match (delim other stack-top)
+ "Internal function used for debugging.
+Check that OTHER is non-nil. This should always be the case.
+Then, if debugging is enabled, check whether STACK-TOP and DELIM
+coincide. Sometimes this is intentional (e.g., when `\right.'
+terminates `\left{'), so we do not treat it as an error."
+ (cl-assert other)
+ (when tp--debug
+ (unless (equal other stack-top)
+ (message "Mismatched delimiters: %s %s" stack-top delim))))
+
+(defun tp-forward-list (&optional bound)
"Move forward across one balanced group.
Search up to BOUND."
(interactive)
- (unless bound (setq bound (tex-parens--forward-bound)))
+ (unless bound (setq bound (tp--forward-bound)))
(let ((start (point))
- (delim (tex-parens--forward-delim bound))
- (stack ()))
+ (delim (tp--forward-delim bound))
+ (stack ())
+ success)
(while delim
- (if (or (and (member delim '("$" "$$"))
- (tex-parens--math-face-p))
- (and (not (member delim '("$" "$$")))
- (tex-parens--close-of-open delim)))
+ (if (tp--forward-search-found-open delim)
(push delim stack)
- (let ((other (tex-parens--open-of-close delim)))
- (cl-assert other)
- (if stack
- (progn
- (when tex-parens--debug
- (unless (equal other (car stack))
- (message "Mismatched delimiters: %s %s" (car stack)
delim)))
- (pop stack))
- (backward-char (length delim)))))
- (setq delim (and stack (tex-parens--forward-delim bound))))
- (when stack
+ (if stack
+ (progn
+ (tp--check-match delim (tp--open-of-close delim) (car stack))
+ (pop stack)
+ (unless stack
+ (setq success t)))
+ (backward-char (length delim))
+ (setq success t)))
+ (setq delim (and (not success) (tp--forward-delim bound))))
+ (unless success
(goto-char start)
- (when tex-parens--debug
+ (when tp--debug
(message "Unmatched delimiters: %s" (car stack))))))
-(defun tex-parens-backward-list (&optional bound)
+(defun tp-backward-list (&optional bound)
"Move backward across one balanced group.
Search up to BOUND."
(interactive)
- (unless bound (setq bound (tex-parens--backward-bound)))
+ (unless bound (setq bound (tp--backward-bound)))
(let ((start (point))
- (delim (tex-parens--backward-delim bound))
- (stack ()))
+ (delim (tp--backward-delim bound))
+ (stack ())
+ success)
(while delim
- (if (or (and (member delim '("$" "$$"))
- (save-excursion
- (backward-char (length delim))
- (tex-parens--math-face-p)))
- (and (not (member delim '("$" "$$")))
- (tex-parens--open-of-close delim)))
+ (if (tp--backward-search-found-close delim)
(push delim stack)
- (let ((other (tex-parens--close-of-open delim)))
- (cl-assert other)
- (if stack
- (progn
- (when tex-parens--debug
- (unless (equal other (car stack))
- (message "Mismatched delimiters: %s %s" delim (car
stack))))
- (pop stack))
- (forward-char (length delim)))))
- (setq delim (and stack (tex-parens--backward-delim bound))))
- (when stack
+ (if stack
+ (progn
+ (tp--check-match delim (tp--close-of-open delim) (car stack))
+ (pop stack)
+ (unless stack
+ (setq success t)))
+ (forward-char (length delim))
+ (setq success t)))
+ (setq delim (and (not success) (tp--backward-delim bound))))
+ (unless success
(goto-char start)
- (when tex-parens--debug
+ (when tp--debug
(message "Unmatched delimiters: %s" (car stack))))))
-(defun tex-parens-backward-up-list (&optional bound)
+(defun tp-backward-up-list (&optional bound)
"Move backward out of one balanced group.
Search up to BOUND."
(interactive)
- (unless bound (setq bound (tex-parens--backward-bound)))
+ (unless bound (setq bound (tp--backward-bound)))
(let ((start (point))
success
- (delim (tex-parens--backward-delim bound))
+ (delim (tp--backward-delim bound))
(stack ()))
(while delim
- (cond
- ((or
- (and (member delim '("$" "$$"))
- (save-excursion
- (backward-char (length delim))
- (tex-parens--math-face-p)))
- (and (not (member delim '("$" "$$")))
- (tex-parens--open-of-close delim)))
- (push delim stack))
- (t
- (let ((other (tex-parens--close-of-open delim)))
- (cl-assert other)
- (if stack
- (progn
- (when tex-parens--debug
- (unless (equal other (car stack))
- (message "Mismatched delimiters: %s %s" delim (car
stack))))
- (pop stack))
- (setq success t))
- ;; (push delim stack))
-
- ;; (if (equal other (car stack))
- ;; (pop stack)
- ;; (setq success t))
- )
- ;; (assoc delim tex-parens-pairs)
- ; Opening delimiter
- ;; (if (equal (cdr (tex-parens-delim-pair delim)) (car stack))
- ;; (pop stack)
- ;; (setq success t))
- )
- )
- (setq delim (and (not success) (tex-parens--backward-delim bound))))
+ (if (tp--backward-search-found-close delim)
+ (push delim stack)
+ (if stack
+ (progn
+ (tp--check-match delim (tp--close-of-open delim) (car stack))
+ (pop stack))
+ (setq success t)))
+ (setq delim (and (not success) (tp--backward-delim bound))))
(unless success
(goto-char start))))
-(defun tex-parens-up-list (&optional bound)
+(defun tp-up-list (&optional bound)
"Move forward out of one balanced group.
Search up to BOUND."
(interactive)
- (unless bound (setq bound (tex-parens--forward-bound)))
+ (unless bound (setq bound (tp--forward-bound)))
(let ((start (point))
success
- (delim (tex-parens--forward-delim bound))
+ (delim (tp--forward-delim bound))
(stack ()))
(while delim
- (cond
- ((or
- (and (member delim '("$" "$$"))
- (tex-parens--math-face-p))
- (and (not (member delim '("$" "$$")))
- (tex-parens--close-of-open delim)))
- (push delim stack))
- (t
- (let ((other (tex-parens--open-of-close delim)))
- (cl-assert other)
- (if stack
- (progn
- (when tex-parens--debug
- (unless (equal other (car stack))
- (message "Mismatched delimiters: %s %s" delim (car
stack))))
- (pop stack))
- (setq success t)))
- ;; (cdr (tex-parens-delim-pair delim))
- ; Closing delimiter
- ;; (if (equal (cdr (tex-parens-delim-pair delim)) (car stack))
- ;; (pop stack)
- ;; (setq success t))
- )
- )
- (setq delim (and (not success) (tex-parens--forward-delim bound))))
+ (if (tp--forward-search-found-open delim)
+ (push delim stack)
+ (if stack
+ (progn
+ (tp--check-match delim (tp--open-of-close delim) (car stack))
+ (pop stack))
+ (setq success t)))
+ (setq delim (and (not success) (tp--forward-delim bound))))
(unless success
(goto-char start))))
-(defun tex-parens-forward-sexp-1 ()
- "Move forward across one balanced expression (sexp)."
- (interactive)
+(defun tp--forward-sexp-1 ()
+ "Move forward across one balanced expression (sexp).
+Helper function for `tp-backward-sexp'."
(let ((delim-beg (save-excursion
- (tex-parens--forward-delim)
+ (tp--forward-delim)
(match-beginning 0)))
(vanilla (save-excursion
(goto-char (or (scan-sexps (point) 1) (buffer-end 1)))
(point))))
(if (and delim-beg
(> vanilla delim-beg))
- (tex-parens-forward-list)
+ (tp-forward-list)
(goto-char vanilla))))
-(defun tex-parens-backward-sexp ()
+(defun tp-backward-sexp ()
"Move backward across one balanced expression (sexp).
If `backward-sexp' does not take us beyond the ending point of
the previous delimiter, then do that. Otherwise, do
-`tex-parens-backward-list'."
+`tp-backward-list'."
(interactive)
(let ((delim-end (save-excursion
- (when-let ((delim (tex-parens--backward-delim)))
+ (when-let ((delim (tp--backward-delim)))
(forward-char (length delim))
(point))))
(vanilla (save-excursion
@@ -409,40 +501,36 @@ the previous delimiter, then do that. Otherwise, do
(point))))
(if (and delim-end
(< vanilla delim-end))
- (tex-parens-backward-list)
+ (tp-backward-list)
(goto-char vanilla))))
-(defun tex-parens-forward-sexp (&optional arg)
+(defun tp-forward-sexp (&optional arg)
"Move forward across one balanced expression (sexp).
If `forward-sexp' does not take us past the starting point of the
next delimiter, then do that. Otherwise, do
-`tex-parens-forward-list'.
+`tp-forward-list'.
With ARG, do it that many times. Negative arg -N means move
backward across N balanced expressions."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
- (tex-parens-forward-sexp-1)
+ (tp--forward-sexp-1)
(setq arg (1- arg)))
(while (< arg 0)
- (tex-parens-backward-sexp)
+ (tp-backward-sexp)
(setq arg (1+ arg))))
-(defun tex-parens-down-list (&optional bound)
+(defun tp-down-list (&optional bound)
"Move forward into one balanced group.
Search up to BOUND. Return t if successful, nil otherwise."
(interactive)
- (unless bound (setq bound (tex-parens--forward-bound)))
+ (unless bound (setq bound (tp--forward-bound)))
(let ((start (point))
- (delim (tex-parens--forward-delim bound))
+ (delim (tp--forward-delim bound))
success)
(when (and delim
- (or
- (and (equal delim "$")
- (tex-parens--math-face-p))
- (and (not (equal delim "$"))
- (tex-parens--close-of-open delim))))
+ (tp--forward-search-found-open delim))
(setq success t))
(unless success
(goto-char start))
@@ -450,31 +538,32 @@ Search up to BOUND. Return t if successful, nil
otherwise."
(preview-move-point))
success))
-(defun tex-parens-delete-pair (&optional bound)
+(defun tp-delete-pair (&optional bound)
"Delete a balanced pair of delimiters that follow point.
Push a mark at the end of the contents of the pair.
Search up to BOUND."
(interactive)
- (unless bound (setq bound (tex-parens--forward-bound)))
- (when (tex-parens-down-list bound)
+ (unless bound (setq bound (tp--forward-bound)))
+ (when (tp-down-list bound)
(save-excursion
- (tex-parens-up-list)
+ (tp-up-list)
(let ((q (point)))
- (tex-parens--backward-delim)
+ (tp--backward-delim)
(delete-region (point) q)
(push-mark)))
(let ((q (point)))
- (tex-parens--backward-delim)
+ (tp--backward-delim)
(delete-region (point) q))))
;;; AWKWARDNESS BEGINS HERE
-;; it shouldn't be necessary to define any of the following -- it
-;; should suffice to set forward-sexp-function to
-;; tex-parens-forward-sexp -- but for some reason, Emacs freezes when
-;; I do so. whatever. the ad hoc solution works fine
+;; it shouldn't be necessary to define any of the following (via
+;; copy/paste from lisp.el and simple.el) -- it should suffice to set
+;; forward-sexp-function to tp-forward-sexp -- but for some
+;; reason, Emacs freezes when I do so. I haven't been able to debug
+;; why. alas.
-(defun tex-parens-mark-sexp (&optional arg allow-extend)
+(defun tp-mark-sexp (&optional arg allow-extend)
"Set mark ARG sexps from point or move mark one sexp.
When called from Lisp with ALLOW-EXTEND omitted or nil, mark is
set ARG sexps from point.
@@ -502,7 +591,7 @@ This command assumes point is not in a string or comment."
(save-excursion
(goto-char (mark))
(condition-case error
- (tex-parens-forward-sexp arg)
+ (tp-forward-sexp arg)
(scan-error
(user-error (if (equal (cadr error)
"Containing expression ends prematurely")
@@ -513,7 +602,7 @@ This command assumes point is not in a string or comment."
(push-mark
(save-excursion
(condition-case error
- (tex-parens-forward-sexp (prefix-numeric-value arg))
+ (tp-forward-sexp (prefix-numeric-value arg))
(scan-error
(user-error (if (equal (cadr error)
"Containing expression ends prematurely")
@@ -522,7 +611,7 @@ This command assumes point is not in a string or comment."
(point))
nil t))))
-(defun tex-parens-kill-sexp (&optional arg interactive)
+(defun tp-kill-sexp (&optional arg interactive)
"Kill the sexp (balanced expression) following point.
With ARG, kill that many sexps after point.
Negative arg -N means kill N sexps before point.
@@ -537,10 +626,10 @@ report errors as appropriate for this kind of usage."
"No next sexp"
"No previous sexp"))))
(let ((opoint (point)))
- (tex-parens-forward-sexp (or arg 1))
+ (tp-forward-sexp (or arg 1))
(kill-region opoint (point)))))
-(defun tex-parens-backward-kill-sexp (&optional arg interactive)
+(defun tp-backward-kill-sexp (&optional arg interactive)
"Kill the sexp (balanced expression) preceding point.
With ARG, kill that many sexps before point.
Negative arg -N means kill N sexps after point.
@@ -548,9 +637,9 @@ This command assumes point is not in a string or comment.
If INTERACTIVE is non-nil, as it is interactively,
report errors as appropriate for this kind of usage."
(interactive "p\nd")
- (tex-parens-kill-sexp (- (or arg 1)) interactive))
+ (tp-kill-sexp (- (or arg 1)) interactive))
-(defun tex-parens-transpose-sexps-default-function (arg)
+(defun tp-transpose-sexps-default-function (arg)
"Default method to locate a pair of points for `transpose-sexps'.
ARG is as in the docstring for `transpose-sexps'."
;; Here we should try to simulate the behavior of
@@ -569,13 +658,13 @@ ARG is as in the docstring for `transpose-sexps'."
(progn (funcall (if (> arg 0)
#'skip-syntax-backward
#'skip-syntax-forward)
"w_")
- (cons (save-excursion (tex-parens-forward-sexp arg)
(point)) (point)))
+ (cons (save-excursion (tp-forward-sexp arg) (point))
(point)))
;; Otherwise, we're between sexps. Take a step back before jumping
;; to make sure we'll obey the same precedence no matter which
;; direction we're going.
(funcall (if (> arg 0) #'skip-syntax-backward #'skip-syntax-forward)
" .")
- (cons (save-excursion (tex-parens-forward-sexp arg) (point))
+ (cons (save-excursion (tp-forward-sexp arg) (point))
(progn (while (or (forward-comment (if (> arg 0) 1 -1))
(not (zerop (funcall (if (>
arg 0)
#'skip-syntax-forward
@@ -583,7 +672,7 @@ ARG is as in the docstring for `transpose-sexps'."
".")))))
(point)))))
-(defun tex-parens-raise-sexp (&optional n)
+(defun tp-raise-sexp (&optional n)
"Raise N sexps one level higher up the tree.
This function removes the sexp enclosing the form which follows
@@ -609,9 +698,9 @@ and point is before (zot), \\[raise-sexp] will give you
(buffer-substring (region-beginning) (region-end))
(buffer-substring
(point)
- (save-excursion (tex-parens-forward-sexp n) (point))))))
- (tex-parens-backward-up-list)
- (delete-region (point) (save-excursion (tex-parens-forward-sexp 1)
(point)))
+ (save-excursion (tp-forward-sexp n) (point))))))
+ (tp-backward-up-list)
+ (delete-region (point) (save-excursion (tp-forward-sexp 1) (point)))
(save-excursion (insert s))))
(provide 'tex-parens)