2

I have a file that I want to turn into a (local) package containing (inter alia) the code:

(defun tl-sort-regexp-fields (reverse record-regexp key-regexp beg end)
  "Extended sort function."
  (interactive "P\nsRegexp specifying records to sort: \nsRegexp specifying key within record: \nr")
  (if (string-match "\\`\\(?:-\\\\[1-9]\\|\\(?:-?\\\\[1-9]\\)\\{2,\\}\\)\\'" key-regexp)
      (let
          ((i (length key-regexp)))
        (while (> i 0)
          (let ((key-reverse (and (> i 2) (= (aref key-regexp (- i 3)) ?-)))
                (key (substring key-regexp (- i 2) i)))
            (sort-regexp-fields (if reverse (not key-reverse) key-reverse) record-regexp key beg end)
            (if key-reverse
                (setq i (- i 1)))
            (setq i (- i 2)))))
    (sort-regexp-fields reverse record-regexp key-regexp beg end)))

(dolist (i '(("Apples"  "^\\([-+ ]\\)\\([^\t]+\\)\t\\([0-9]+\\)\t.*$"                                            "\\2\\3-\\1")
             ("Bananas" "^\\([-+ ]\\)\\([0-9]+\\)\t.*$"                                                          "\\2-\\1")
             ("Oranges" "^\\([-+ ]\\)\\([0-9]+\\)\t.*$"                                                          "\\2-\\1")
             ("Pears"   "^\\([-+ ]\\)\\([^\t]+\\)\t\\([^\t]+\\)\t\\([^\t]+\\)\t\\([^\t]+\\)\t\\([^\t]+\\)\t.*$"  "\\2\\3\\4\\5\\6-\\1")
             ("Kiwis"   "^\\([-+ ]\\)\\([0-9]+\\)\t.*$"                                                          "\\2-\\1")))
  (fset (intern (concat "tl-sort-" (downcase (nth 0 i))))
        `(lambda (beg end)
           ,(concat "Sort region according to primary key of table " (nth 0 i) ".")
           (interactive "r")
           (tl-sort-regexp-fields nil ,(nth 1 i) ,(nth 2 i) beg end))))

This generates (one plus) five functions named tl-sort-apples, etc.

I can easily prepend ;;;###autoload to tl-sort-regexp-fields's defun to have it produce the proper autoload for tl-sort-regexp-fields, but how can I do the same for the "generated" functions while keeping the code DRY, i. e. not adding a ;;;###autoload (autoload 'tl-sort-apples […]) for every function?

If I prepend ;;;###autoload to dolist (on a separate line), the code is executed once when the autoloads are loaded and once when the file is loaded. If I prepend ;;;###autoload on the same line, i. e. writing:

;;;###autoload (dolist (i '(("Apples" "^\\([-+ ]\\)\\([^\t]+\\)\t\\([0-9]+\\)\t.*$" "\\2\\3-\\1") ("Bananas" "^\\([-+ ]\\)\\([0-9]+\\)\t.*$" "\\2-\\1") ("Oranges" "^\\([-+ ]\\)\\([0-9]+\\)\t.*$" "\\2-\\1") ("Pears" "^\\([-+ ]\\)\\([^\t]+\\)\t\\([^\t]+\\)\t\\([^\t]+\\)\t\\([^\t]+\\)\t\\([^\t]+\\)\t.*$" "\\2\\3\\4\\5\\6-\\1") ("Kiwis" "^\\([-+ ]\\)\\([0-9]+\\)\t.*$" "\\2-\\1"))) (fset (intern (concat "tl-sort-" (downcase (nth 0 i)))) `(lambda (beg end) ,(concat "Sort region according to primary key of table " (nth 0 i) ".") (interactive "r") (tl-sort-regexp-fields nil ,(nth 1 i) ,(nth 2 i) beg end))))

this would (only) define the functions when reading the autoloads (which in this case would probably be fine because the functions are short and few), but the code looks simply illegible and the solution not very universal.

What is the preferred pattern for declaring autoloads for "generated" functions?

1

To make it work like you suggest, you're going to need to turn tl-sort-regexp-fields into a macro. Then placing a ;;;###autoload in front of the macro call should do the trick (tho only if that macro is known to Emacs when the autoloads file is created).

BTW, I recommend you use defalias instead of fset when defining a function.

0

You can ;;;###autoload a form which defines the autoloads.

(dolist (x '(foo bar baz))
  (defalias (intern (concat "my-" (symbol-name x)))
    `(lambda () (interactive) (message "%S" ',x))
    (format "My %S command" x)))

;;;###autoload
(dolist (x '(foo bar baz))
  (autoload (intern (concat "my-" (symbol-name x))) "mylib" nil t))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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