Function: electric-pair--balance-info

electric-pair--balance-info is a byte-compiled function defined in elec-pair.el.gz.

Signature

(electric-pair--balance-info DIRECTION STRING-OR-COMMENT)

Documentation

Examine lists forward or backward according to DIRECTION's sign.

STRING-OR-COMMENT is info suitable for running parse-partial-sexp.

Return a cons of two descriptions (MATCHED-P . PAIR) for the innermost and outermost lists that enclose point. The outermost list enclosing point is either the first top-level or first mismatched list found by listing up.

If the outermost list is matched, don't rely on its PAIR. If point is not enclosed by any lists, return ((t) . (t)).

Source Code

;; Defined in /usr/src/emacs/lisp/elec-pair.el.gz
;; Balancing means controlling pairing and skipping of parentheses
;; so that, if possible, the buffer ends up at least as balanced as
;; before, if not more.  The algorithm is slightly complex because
;; some situations like "()))" need pairing to occur at the end but
;; not at the beginning.  Balancing should also happen independently
;; for different types of parentheses, so that having your {}'s
;; unbalanced doesn't keep `electric-pair-mode' from balancing your
;; ()'s and your []'s.
(defun electric-pair--balance-info (direction string-or-comment)
  "Examine lists forward or backward according to DIRECTION's sign.

STRING-OR-COMMENT is info suitable for running `parse-partial-sexp'.

Return a cons of two descriptions (MATCHED-P . PAIR) for the
innermost and outermost lists that enclose point.  The outermost
list enclosing point is either the first top-level or first
mismatched list found by listing up.

If the outermost list is matched, don't rely on its PAIR.
If point is not enclosed by any lists, return ((t) . (t))."
  (let* (innermost
         outermost
         (table (if string-or-comment
                    electric-pair-text-syntax-table
                  (syntax-table)))
         (at-top-level-or-equivalent-fn
          ;; called when `scan-sexps' ran perfectly, when it found
          ;; a parenthesis pointing in the direction of travel.
          ;; Also when travel started inside a comment and exited it.
          #'(lambda ()
              (setq outermost (list t))
              (unless innermost
                (setq innermost (list t)))))
         (ended-prematurely-fn
          ;; called when `scan-sexps' crashed against a parenthesis
          ;; pointing opposite the direction of travel.  After
          ;; traversing that character, the idea is to travel one sexp
          ;; in the opposite direction looking for a matching
          ;; delimiter.
          #'(lambda ()
              (let* ((pos (point))
                     (matched
                      (save-excursion
                        (cond ((< direction 0)
                               (condition-case nil
                                   (eq (char-after pos)
                                       (electric-pair--with-uncached-syntax
                                           (table)
                                         (matching-paren
                                          (char-before
                                           (scan-sexps (point) 1)))))
                                 (scan-error nil)))
                              (t
                               ;; In this case, no need to use
                               ;; `scan-sexps', we can use some
                               ;; `electric-pair--syntax-ppss' in this
                               ;; case (which uses the quicker
                               ;; `syntax-ppss' in some cases)
                               (let* ((ppss (electric-pair--syntax-ppss
                                             (1- (point))))
                                      (start (car (last (nth 9 ppss))))
                                      (opener (char-after start)))
                                 (and start
                                      (eq (char-before pos)
                                          (or (with-syntax-table table
                                                (matching-paren opener))
                                              opener))))))))
                     (actual-pair (if (> direction 0)
                                      (char-before (point))
                                    (char-after (point)))))
                (unless innermost
                  (setq innermost (cons matched actual-pair)))
                (unless matched
                  (setq outermost (cons matched actual-pair)))))))
    (save-excursion
      (while (not outermost)
        (condition-case err
            (electric-pair--with-uncached-syntax (table)
              (scan-sexps (point) (if (> direction 0)
                                      (point-max)
                                    (- (point-max))))
              (funcall at-top-level-or-equivalent-fn))
          (scan-error
           (cond ((or
                   ;; some error happened and it is not of the "ended
                   ;; prematurely" kind...
                   (not (string-match "ends prematurely" (nth 1 err)))
                   ;; ... or we were in a comment and just came out of
                   ;; it.
                   (and string-or-comment
                        (not (nth 8 (syntax-ppss)))))
                  (funcall at-top-level-or-equivalent-fn))
                 (t
                  ;; exit the sexp
                  (goto-char (nth 3 err))
                  (funcall ended-prematurely-fn)))))))
    (cons innermost outermost)))