From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Drew Adams Newsgroups: gmane.emacs.devel Subject: 1) (elisp) `Advising Named Functions', 2) search filtering example Date: Sun, 16 Oct 2016 22:25:09 -0700 (PDT) Message-ID: <5a44a850-e4fc-4c9f-a266-c74766810ba1@default> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: blaine.gmane.org 1476681966 13960 195.159.176.226 (17 Oct 2016 05:26:06 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 17 Oct 2016 05:26:06 +0000 (UTC) To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Oct 17 07:26:02 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bw0Qo-0001Qw-Le for ged-emacs-devel@m.gmane.org; Mon, 17 Oct 2016 07:25:50 +0200 Original-Received: from localhost ([::1]:59081 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bw0Qq-0004YC-Cp for ged-emacs-devel@m.gmane.org; Mon, 17 Oct 2016 01:25:52 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:50410) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bw0QJ-0004Xt-Ah for emacs-devel@gnu.org; Mon, 17 Oct 2016 01:25:20 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bw0QE-0005dG-CZ for emacs-devel@gnu.org; Mon, 17 Oct 2016 01:25:19 -0400 Original-Received: from userp1040.oracle.com ([156.151.31.81]:17381) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1bw0QE-0005cd-4p for emacs-devel@gnu.org; Mon, 17 Oct 2016 01:25:14 -0400 Original-Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u9H5PBR7025379 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 17 Oct 2016 05:25:12 GMT Original-Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id u9H5PBpY007340 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 17 Oct 2016 05:25:11 GMT Original-Received: from abhmp0001.oracle.com (abhmp0001.oracle.com [141.146.116.7]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id u9H5PALh018277 for ; Mon, 17 Oct 2016 05:25:11 GMT X-Priority: 3 X-Mailer: Oracle Beehive Extensions for Outlook 2.0.1.9.1 (1003210) [OL 12.0.6753.5000 (x86)] X-Source-IP: userv0022.oracle.com [156.151.31.74] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 156.151.31.81 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:208346 Archived-At: 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=E2=80=99s behavior in any other way. If it is possible to do the same thing via a hook, that is preferable. ... In particular, Emacs=E2=80=99s 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)