Elisp: Validate Matching Brackets ๐
Problem
Write a emacs lisp script to process ten thousand files and check for mismatched brackets.
The matching pairs includes these: () {} [] โโ โนโบ ยซยป ใใ ใใ ใใ ใใ ใใ ใใ. [see Unicode: Brackets ใใใใใใ]
The program should be able to check all files in a dir, and report any file that has mismatched bracket, and also indicate the line number or position where a mismatch occurs.
Solution
;; -*- coding: utf-8; lexical-binding: t; -*- ;; 2026-05-25 ;; Elisp: Validate Matching Brackets ๐ ;; http://xahlee.info/emacs/emacs/elisp_validate_matching_brackets.html (defvar xah-validate-brackets-alist nil "a alist of brackets. Each element is a cons pair, of the left and right bracket. Each is a string of single char.") (setq xah-validate-brackets-alist '( ("โ" . "โ") ;; ("โน" . "โบ") ;; ("ยซ" . "ยป") ("ใ" . "ใ") ("ใ" . "ใ") ("ใ" . "ใ") ("ใ" . "ใ") ("ใ" . "ใ") ("ใ" . "ใ") ("ใ" . "ใ") ("โฎ" . "โฏ") ("โฐ" . "โฑ") ;; ("{" . "}") ;; ("[" . "]") ;; ("(" . ")") )) (defun xah-validate-brackets-file (Filepath) "Validate brackets of file at Filepath. The type of brackets to check is stored in variable `xah-validate-brackets-alist'. When called interactively, it checks current buffer. Also, it saves first if modified. URL `http://xahlee.info/emacs/emacs/elisp_validate_matching_brackets.html' Created: 2024-08-10 Version: 2026-05-25" (interactive (progn (when (buffer-modified-p) (save-buffer)) (list buffer-file-name))) (let ((xoutbuf (get-buffer-create "*validate brackets out*" t)) xregex xstack xchar xpos) (when (not (file-exists-p Filepath)) (user-error "Error: file no exist: %s" Filepath)) (display-buffer xoutbuf) (with-current-buffer xoutbuf (goto-char (point-min)) (when (not (string-match "mode: xah-find-output" (buffer-substring-no-properties (pos-bol) (pos-eol)))) (insert "-*- mode: xah-find-output -*-\n")) (when (fboundp 'xah-find-output-mode) (xah-find-output-mode))) (setq xregex (mapconcat (lambda (x) (concat (regexp-quote (car x)) "\\|" (regexp-quote (cdr x)))) xah-validate-brackets-alist "\\|")) ;; (princ "\n" xoutbuf) (with-temp-buffer (insert-file-contents Filepath) (goto-char 1) (while (re-search-forward xregex nil t) (setq xpos (point)) (setq xchar (char-to-string (char-before))) (let (xrightBra-p xleftBra) (setq xrightBra-p (rassoc xchar xah-validate-brackets-alist)) (when xrightBra-p (setq xleftBra (car xrightBra-p))) (if xstack (if (string-equal (elt (car xstack) 0) xleftBra) (pop xstack) (push (vector xchar xpos) xstack)) (if xrightBra-p (princ (format "Nothing matches this bracket: โจ%sโฉ โขat position: %s โขat file: %s " xchar xpos Filepath) xoutbuf) (push (vector xchar xpos) xstack))))) (if xstack (princ (format "Nothing matches this bracket: โจ%sโฉ โขat position: %s โขat file: %s " (aref (car xstack) 0) (aref (car xstack) 1) Filepath) xoutbuf))))) (defun xah-validate-brackets-dir (Dir &optional FileExtension) "Validate brackets in all files in Dir, recursively. The type of brackets to check is stored in var `xah-validate-brackets-alist'. Check only files with FileExtension. If FileExtension is nil, do all files. Any file or dir name starting with dot is ignored. URL `http://xahlee.info/emacs/emacs/elisp_validate_matching_brackets.html' Created: 2024-08-11 Version: 2026-05-25" (interactive (list default-directory (if buffer-file-name (if (file-name-extension buffer-file-name) (file-name-extension buffer-file-name) "html" ) "html"))) (let (xpaths xextRegex) (setq xextRegex (if FileExtension (concat "\\." FileExtension "\\'") "")) (setq xpaths (directory-files-recursively Dir xextRegex nil (lambda (x) (not (string-match "/\\..*/" x))))) (mapc 'xah-validate-brackets-file xpaths)))
Video Tutorial