Xah Talk Show 2026-02-02 Ep755 emacs lisp write a find text command, but only if occur inside given tags
Video Summary (Generated by AI, Edited by Human.)
The video is an Emacs Lisp coding session by Xah Lee, where he demonstrates how to write a script that finds text within files based on specific conditions (0:30).
Here's a breakdown of the key points:
- Project Goal (1:40): The main goal is to create an Emacs Lisp script that can find a specific text string within files, but only if that string is located between two other defined text strings (e.g., within HTML tags). The example used is finding "console" within pre tags for JavaScript code.
- Challenges with Traditional Tools (3:54): Xah Lee explains that standard Unix grep commands cannot handle this kind of conditional search, necessitating a custom script.
- Traversing Directories (5:00): He begins by outlining the process of traversing directories to gather a list of files. This involves defining variables for the input directory and file name regular expressions (12:10) to filter for specific file types (e.g., HTML, JavaScript).
- File Processing (22:21): The next step is to open and read each file. He details how to create a temporary buffer in Emacs to load file content and then navigate within that buffer (24:00).
- Defining Search Parameters (25:57): Three key variables are defined: begin-tag-text (the text that must occur before the target text), end-tag-text (the text that must occur after), and find-text (the actual text to search for).
- Implementing the Search Logic (27:50): The core of the script involves nested search operations. First, it searches for the begin-tag-text, then for the find-text within that found section, and finally for the end-tag-text to confirm the context. If all conditions are met, the file path and position are reported (40:22).
- Testing and Debugging (42:00): Xah Lee demonstrates running the code, addressing issues like unquoted functions and errors related to ignored search errors (44:20). He successfully finds instances of "console log" within pre tags for JavaScript code (47:47).
- Future Refinements (54:50): He discusses potential improvements, such as displaying the actual text occurrences rather than just positions, and adding a feature to find instances where the find-text does not occur within the specified tags.
- Side Discussions (13:05): Throughout the video, Xah Lee engages with chat comments, including a significant digression on the "idiotic jargon" of "idempotency" in programming.
;; -*- coding: utf-8; lexical-binding: t; -*- ;; 2026-02-02 ;; script to find text in all files in a dir ;; with the condition the text only occur ;; between given texts, such as html begin and end tag. (defvar xah-inputDir nil "input dir to search.") (setq xah-inputDir "c:/Users/xah/web/xahlee_info/js/") (defvar xbegin-tag-text nil "text that must occur before.") (setq xbegin-tag-text "<pre class=\"js\">") (defvar xend-tag-text nil "text that must occur after.") (setq xend-tag-text "</pre>") (defvar xfind-text nil "text that we want to find.") (setq xfind-text "console") (defvar xnot-contain-text-p nil "boolean. if t, means only when not contain the text.") (setq xnot-contain-text-p t) (defvar xah-filename-regex nil "regex on filename.") (setq xah-filename-regex ".+\\.html$") (defvar xah-ignore-dir-regex nil "regex on filename or dir name to ignore.") (setq xah-ignore-dir-regex "/\\.") ;; s------------------------------ (defun xah-do-file (fPath xoutbuf) "Process the file at path FPATH" (with-temp-buffer (insert-file-contents fPath) (goto-char (point-min)) (when (search-forward xbegin-tag-text nil t) (let ((xbegin-text-pos (point))) (when (search-forward xend-tag-text nil t) (let ((xend-text-pos (point))) (goto-char xbegin-text-pos) (let ((xcontain-p (search-forward xfind-text xend-text-pos t))) (when (if xnot-contain-text-p (not xcontain-p) xcontain-p) (print (format "found! at file %s at position %s" fPath (point)) xoutbuf))))))))) ;; s------------------------------ (let ((xoutbuf (get-buffer-create "*xah-find-in-tag-output*"))) (mapc (lambda (x) (xah-do-file x xoutbuf)) (directory-files-recursively xah-inputDir xah-filename-regex nil (lambda (x) (not (string-match-p xah-ignore-dir-regex x))))) (pop-to-buffer xoutbuf))