From: Drew Adams <drew.adams@oracle.com>
To: emacs-devel <emacs-devel@gnu.org>
Subject: 1) (elisp) `Advising Named Functions', 2) search filtering example
Date: Sun, 16 Oct 2016 22:25:09 -0700 (PDT) [thread overview]
Message-ID: <5a44a850-e4fc-4c9f-a266-c74766810ba1@default> (raw)
1. Node `Advising Named Functions' of the Elisp manual says this:
For these reasons, advice should be reserved for the cases
where you cannot modify a function’s behavior in any other way.
If it is possible to do the same thing via a hook, that is
preferable. ...
In particular, Emacs’s own source files should not put advice
on functions in Emacs. (There are currently a few exceptions
to this convention, but we aim to correct them.)
Is that still true? Is this the policy, even with the new
advice system?
If so, then it seems that it is being ignored, as new advice
has been added to `isearch-filter-predicate' in `dired-aux.el'
and `wdired.el'.
And the `isearch.el' code has been modified to accommodate such
advising, instead of, for example, just using a hook variable.
----
2. As a related aside, I recently added, to my library
`isearch+.el', an ability to add search-filter predicates on
the fly.
a. At first, I took the hook approach:
`isearch-filter-predicate' is essentially a hook, so I made
it one explicitly. I modified (my version of) the code that
uses it, so that the value could be either a function or a
list of functions. I used `run-hook-with-args-until-failure'
for the (now true) hook variable `isearch-filter-predicate'.
This approach was simple to implement. However, it would
also mean modifying any and all code that uses or will use
`isearch-filter-predicate' differently. In particular,
code in `replace.el', as well as the code in `dired-aux.el'
and `wdired.el' mentioned above.
b. Figuring that the current wave of advising instead of
hooking is here to stay, I then took the different approach
of using `add-function', `remove-function', etc. instead of
a hook.
The implementation is not as simple or straightforward as
for a hook, but it is clean enough. I'm sticking with it,
as I expect that this is the way the wind is blowing now.
(Note that one difference from a hook is that a hook does
not privilege the first hook function in any way (or the
last, depending on how you look at it). Removing advice
is not equivalent to `remove-hook'. It never "empties the
hook" completely - the function that was advised is still
there after removal of all advice.)
Anyway, using either approach you can do any of these
things while searching, to modify the zones you search:
* `M-? &' (`isearchp-add-filter-predicate') adds a filter
predicate, AND-ing it as an additional `:after-while' filter.
* `M-? |' (`isearchp-or-filter-predicate') adds a filter
predicate, OR-ing it as an additional `:before-until' filter.
* `M-? ~' (`isearchp-complement-filter') complements the current
filter. It either adds an `:around' filter that complements
or it removes an existing top-level complementing filter.
* `M-? -' (`isearchp-remove-filter-predicate') removes the last
added filter predicate (aka advice).
* `M-? !' (`isearchp-set-filter-predicate') sets the overall
filter predicate (advised `isearch-filter-predicate') to a
single predicate.
* `M-? 0' (`isearchp-reset-filter-predicate') resets
`isearch-filter-predicate' to its original (unadvised) value.
* `M-? s' (`isearchp-save-filter-predicate') saves the current
filter-predicate suite (advised `isearch-filter-predicate')
for subsequent searches. Unless you save it, the next
Isearch starts out from scratch, using the last (unadvised)
value of `isearch-filter-predicate'.
* `M-? n' (`isearchp-defun-filter-predicate') names the current
suite of filter predicates, creating a named predicate that
does the same thing. (You can use that name with `M-? -' to
remove that predicate.) With a prefix arg it can also set or
save (i.e., do what `M-? !' or `M-? s' does).
* `M-? M-h' (`isearchp-show-filters') echoes the current suite
of filter predicates (advice and original, unadvised
predicate).
* `M-? @', `M-? <', and `M-? >' (`isearchp-near',
`isearchp-near-before', and `isearchp-near-after') constrain
searching to be within a given distance of (near) another
search pattern.
When you use one of the commands that adds a filter predicate as
advice to `isearch-filter-predicate' you can be prompted for two
things: (1) a name for the predicate and (2) text to add to the
Isearch prompt as a reminder of filtering. Two user options
control this prompting:
* `isearchp-prompt-for-filter-name' says whether to prompt you
always, never, or only when the predicate that you provide is
not a symbol (it is a lambda form). The last of these is the
default behavior. If you are prompted and provide a name, you
can use that name with `M-? -' to remove that predicate.
* `isearchp-prompt-for-isearch-prompt-prefix' says whether to
prompt you for a prefix to add to the Isearch prompt. You are
prompted by default, but if you don't care to see such a
prompt prefix and you don't want to be bothered by it, you can
customize this to skip prompting.
In addition, whatever the value of these options, when you add a
filter predicate you can override the option values by using a
prefix argument. A non-positive prefix arg overrides the option
for name prompting, and a non-negative prefix arg overrides the
option for prompt-prefix prompting. (So zero, e.g., `M-0',
overrides both.)
(The code is here, if anyone wants to play with it:
https://www.emacswiki.org/emacs/download/isearch%2b.el)
next reply other threads:[~2016-10-17 5:25 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-17 5:25 Drew Adams [this message]
2016-10-17 12:20 ` 1) (elisp) `Advising Named Functions', 2) search filtering example Noam Postavsky
2016-10-17 14:02 ` Drew Adams
2016-10-17 14:37 ` Noam Postavsky
2016-10-17 14:52 ` Stefan Monnier
2016-10-17 15:40 ` Drew Adams
2016-10-17 15:51 ` Stefan Monnier
2016-10-17 17:05 ` Drew Adams
2016-10-17 17:47 ` Stefan Monnier
2016-10-17 15:40 ` Drew Adams
2016-10-17 16:16 ` Noam Postavsky
2016-10-17 17:05 ` Drew Adams
2016-10-17 17:53 ` Stefan Monnier
2016-10-17 18:41 ` Drew Adams
2016-10-17 19:25 ` Stefan Monnier
2016-10-18 19:47 ` Richard Stallman
2016-10-19 6:15 ` Eli Zaretskii
2016-10-19 20:00 ` Richard Stallman
2016-10-19 20:18 ` Stefan Monnier
2016-10-20 7:17 ` Eli Zaretskii
2016-10-20 7:06 ` Eli Zaretskii
2016-10-20 18:06 ` Richard Stallman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5a44a850-e4fc-4c9f-a266-c74766810ba1@default \
--to=drew.adams@oracle.com \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.