Function: org-babel-balanced-split

org-babel-balanced-split is a byte-compiled function defined in ob-core.el.gz.

Signature

(org-babel-balanced-split STRING ALTS)

Documentation

Split STRING on instances of ALTS.

ALTS is a character, or cons of two character options where each option may be either the numeric code of a single character or a list of character alternatives. For example, to split on
balanced instances of "[ ]:", set ALTS to ((32 9) . 58).

Source Code

;; Defined in /usr/src/emacs/lisp/org/ob-core.el.gz
(defun org-babel-balanced-split (string alts)
  "Split STRING on instances of ALTS.
ALTS is a character, or cons of two character options where each
option may be either the numeric code of a single character or
a list of character alternatives.  For example, to split on
balanced instances of \"[ \t]:\", set ALTS to ((32 9) . 58)."
  (with-temp-buffer
    (insert string)
    (goto-char (point-min))
    (let ((splitp (lambda (past next)
		    ;; Non-nil when there should be a split after NEXT
		    ;; character. PAST is the character before NEXT.
		    (pcase alts
		      (`(,(and first (pred consp)) . ,(and second (pred consp)))
		       (and (memq past first) (memq next second)))
		      (`(,first . ,(and second (pred consp)))
		       (and (eq past first) (memq next second)))
		      (`(,(and first (pred consp)) . ,second)
		       (and (memq past first) (eq next second)))
		      (`(,first . ,second)
		       (and (eq past first) (eq next second)))
		      ((pred (eq next)) t)
		      (_ nil))))
	  (partial nil)
	  (result nil))
      (while (not (eobp))
        (cond
	 ((funcall splitp (char-before) (char-after))
	  ;; There is a split after point.  If ALTS is two-folds,
	  ;; remove last parsed character as it belongs to ALTS.
	  (when (consp alts) (pop partial))
	  ;; Include elements parsed so far in RESULTS and flush
	  ;; partial parsing.
	  (when partial
	    (push (apply #'string (nreverse partial)) result)
	    (setq partial nil))
	  (forward-char))
	 ((memq (char-after) '(?\( ?\[))
	  ;; Include everything between balanced brackets.
	  (let* ((origin (point))
		 (after (char-after))
		 (openings (list after)))
	    (forward-char)
	    (while (and openings (re-search-forward "[]()]" nil t))
	      (pcase (char-before)
		((and match (or ?\[ ?\()) (push match openings))
		(?\] (when (eq ?\[ (car openings)) (pop openings)))
		(_ (when (eq ?\( (car openings)) (pop openings)))))
	    (if (null openings)
		(setq partial
		      (nconc (nreverse (string-to-list
					(buffer-substring origin (point))))
			     partial))
	      ;; Un-balanced bracket.  Backtrack.
	      (push after partial)
	      (goto-char (1+ origin)))))
	 ((and (eq ?\" (char-after)) (not (eq ?\\ (char-before))))
	  ;; Include everything from current double quote to next
	  ;; non-escaped double quote.
	  (let ((origin (point)))
	    (if (re-search-forward "[^\\]\"" nil t)
		(setq partial
		      (nconc (nreverse (string-to-list
					(buffer-substring origin (point))))
			     partial))
	      ;; No closing double quote.  Backtrack.
	      (push ?\" partial)
	      (forward-char))))
	 (t (push (char-after) partial)
	    (forward-char))))
      ;; Add pending parsing and return result.
      (when partial (push (apply #'string (nreverse partial)) result))
      (nreverse result))))