defadvice error for isearch-search-fun-default

2019-08-16 03:08发布

问题:

This is a continue of my previous post (is it possible to preprocess the input string before isearch-forward in Emacs). I am trying to implement jpkotta's answer using the variable isearch-search-fun-function. Instead of writing my own function, I just advise the isearch-search-fun-default to include my own functions (isearch-str-forward and isearch-str-backward, just for the purpose of demo) so that everytime I type "abc", isearch will highlight and search the regexp a[ ]*b[ ]*c[ ]*.

The problem is, when I advised the function and then do isearch of "abc", it gave me the error of I-search: abc [(void-function nil)]. But if I put the code inside my defadvise into the original isearch-search-fun-default function, it works! So I get confused. The Elisp manual said ad-do-it is just a placeholder for the original function code, so these two approaches, advising the function or changing the original function, should generate the same code at last. Why the error when I advise it?

(defun isearch-mangle-str (str)
  "For input STR \"abc\", it will return \"a[ ]*b[ ]*c[ ]*\"."
  (let ((i 0) (out ""))
    (dotimes (i (length str))
      (setq out (concat out (substring str i (1+ i)) "[ ]" "*")))
    out))

(defun isearch-str-forward (str &optional bound noerror)
  "Search forward for STR."
  (let ((string (isearch-mangle-str str)))
    (re-search-forward string bound noerror)))

(defun isearch-str-backward (str &optional bound noerror)
  "Search backward for STR."
  (let ((string (isearch-mangle-str str)))
    (re-search-backward string bound noerror)))

(defvar my-search-p t)
(defadvice isearch-search-fun-default (around my-isearch-search-fun activate)
  (if my-search-p
      (if isearch-forward 'isearch-str-forward
        'isearch-str-backward)
    ad-do-it))

回答1:

I'm not entirely sure why you're getting those errors (my guess is that you probably need to use ad-return-value), but why use advice? Usually it should be a last resort, and in this case it is very easy to avoid advising.

Also, don't prefix your function names with "isearch". Since emacs only has one namespace (I'm not talking about lisp1 vs. lisp2), it's good practice to name your variables and functions uniquely. Personally, I use a prefix "jpk/", but I've used "my-" here.

(defun my-isearch-mangle-str (str)
  "For input STR \"abc\", it will return \"a[ ]*b[ ]*c[ ]*\"."
  (let ((i 0) (out ""))
    (dotimes (i (length str))
      (setq out (concat out (substring str i (1+ i)) "[ ]" "*")))
    out))

(defun my-isearch-str-forward (str &optional bound noerror)
  "Search forward for STR."
  (let ((string (my-isearch-mangle-str str)))
    (re-search-forward string bound noerror)))

(defun my-isearch-str-backward (str &optional bound noerror)
  "Search backward for STR."
  (let ((string (my-isearch-mangle-str str)))
    (re-search-backward string bound noerror)))

(defvar my-isearch-p t)

(defun my-isearch-search-fun ()
  (if my-isearch-p
      (if isearch-forward 'my-isearch-str-forward 'my-isearch-str-backward)
    (isearch-search-fun-default)))

(setq isearch-search-fun-function 'my-isearch-search-fun)

Also, I'm not sure exactly what you want, but it seems similar to my package flex-isearch.