1

I am a copy editor and I make an intensive use of custom "predicates" when I perform replacements in LaTeX code.

I use, among others, this technique:

;; predicate
(defun omit-comments (beg end)
  "Return nil if some text BEG to END is in a comment string."
  (catch 'skip-commented-region
    (let ((pos beg))
      (save-excursion
        (save-match-data
          (goto-char pos)
          (while (< pos end)
            (when (nth 4 (syntax-ppss)) (throw 'skip-commented-region nil))
            (goto-char (setq pos (1+ pos)))))
        t))))
(defalias 'skip-comments 'omit-comments)

;; predicate
(defun hold-comments (beg end)
  "Return nil if some text BEG to END is outside a comment string."
  (catch 'skip-uncommented-region
    (let ((pos beg))
      (save-excursion
        (save-match-data
          (goto-char pos)
          (while (< pos end)
            (unless (nth 4 (syntax-ppss)) (throw 'skip-uncommented-region nil))
            (goto-char (setq pos (1+ pos)))))
        t))))
(defalias 'keep-comments 'hold-comments)

(defun with-temp-isearch-filter-predicate ()
  "Temporarily assigns a series of predicates to the variable `isearch-filter-predicate`
    to make only portions of the buffer that match specific criteria visible/invisible
    to search and replace functions."
  (interactive)
  (require 'typ-custom-macros)
  (save-excursion
    (let* ((isearch-filter-predicate isearch-filter-predicate)
           (DEFAULT "skip-comments")
           (PREDICATES_LIST '(
                              "keep-comments"
                              "skip-comments"
                              ))
           (PREDICATES (completing-read-multiple
                        "Specify, separating by commas, which predicates you want to activate: "
                        PREDICATES_LIST
                        nil
                        t
                        nil
                        nil
                        DEFAULT))
           
           ;; Non-nil means to allow minibuffer commands while in the minibuffer:
           (enable-recursive-minibuffers t))
      
      (mapcar (lambda (predicate)
                (add-function :before-while isearch-filter-predicate (intern-soft predicate)))
              PREDICATES)
      
      (read-string
       (format
        "The value assigned to the variable `isearch-filter-predicate' is currently `%S'.\nPress ENTER to restore the default value at the end of the operations"
        isearch-filter-predicate)))))

Since I have a lot of predicates, I'd like to replace the PREDICATES_LIST value, now inserted explicitly in the function, with a more efficient code.

I thought I can define a list, e.g., my-predicates and use (add-to-list 'my-predicates "predicate-name") but I'm wondering if there is a better solution.

Is there a way to create a "group of functions" or to add to a function name a property, so you can get a list of all the functions in the group or with a given property?

2
  • "I'd like to replace the PREDICATES_LIST value ... with a more efficient code" - more efficient in what sense? Faster to execute (program efficiency)? Easier to modify (programmer efficiency)? Something else?
    – NickD
    Commented Dec 5, 2023 at 3:34
  • 1
    I mean "Easier to modify (programmer efficiency)". I'd like to add a function (predicate) to the list/group after the predicate definition code not in the main function body,
    – Gabriele
    Commented Dec 5, 2023 at 7:21

1 Answer 1

1

A group of anything is usually going to be a list, and I can't imagine wanting anything different here.

A list of functions to be called is typically a "hook" in Emacs. A hook is still just a list (plus expected naming schemes), but there are a variety of run-hook* functions for invoking the functions. (For user options there's also a hook customize type for use in the defcustom form.)

Dealing in strings looks kinda gross. I've only skimmed the code, but it shouldn't be hard to avoid that. E.g.:

(mapcar #'intern (completing-read-multiple "?" '(foo bar baz)))
3
  • I searched a lot but I didn't understand if I have to build a simple list of functions or if there is a specific elisp syntax to do that.
    – Gabriele
    Commented Dec 5, 2023 at 7:26
  • 1
    There's no specific elisp syntax for a list of functions, because the existing syntax for lists is sufficient. You can put anything in a list, functions included.
    – phils
    Commented Dec 5, 2023 at 8:55
  • 1
    If you want multiple function lists each identified by some key then you'd likely use an alist or a plist. See C-h i g (elisp)Association Lists and (elisp)Property Lists respectively.
    – phils
    Commented Dec 5, 2023 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.