From: Michael Heerdegen <michael_heerdegen@web.de>
To: Chunyang Xu <mail@xuchunyang.me>
Cc: help-gnu-emacs@gnu.org
Subject: Re: [el-search] How to search string excluding docstring?
Date: Mon, 25 Dec 2017 15:56:14 +0100 [thread overview]
Message-ID: <87608u501d.fsf@web.de> (raw)
In-Reply-To: <m2h8sfje5v.fsf@xuchunyang.me> (Chunyang Xu's message of "Mon, 25 Dec 2017 18:27:24 +0800")
Chunyang Xu <mail@xuchunyang.me> writes:
> Hi Michael Heerdegen and other Emacs users,
>
> For example, with the following contents in a buffer
>
> (defun foo ()
> "foo docstring"
> (message "foo string"))
>
> (string "foo") matches both "foo docstring" and "foo string", I want a
> way to exclude the docstring, by "docstring", I just mean the string
> being checking should not be the fourth element in
>
> (defun _ _ docstring . _)
>
> I am thinking a pattern like
>
> (and (pred stringp) (guard (not (docstring-p))) (string "foo"))
>
> but I have no idea how to define 'docstring-p'.
The general task is context-sensitive matching. You have no chance with
the current version of el-search, because all patterns there are not
context aware, as you have noticed.
I want to add that, but because there are some pitfalls, I've not yet
uploaded something like this.
Here is what I currently have:
#+begin_src emacs-lisp
(defun el-search--try-find-parent-beg ()
;; try to find beg of parent exp heuristically
(unless (looking-at "^(")
(let ((opoint (point)))
(or (and (search-backward-regexp "[;\(\)\"]" (max (- (point) 300) (point-min)))
(looking-at "\(")
(and (or (eobp)) (not (= (char-before) ?\\)))
(not (looking-back ";" (line-beginning-position))))
(progn (goto-char opoint)
nil)))))
(el-search-defpattern parent (pattern &optional n)
"Matches when PATTERN matches the (Nth) parent of the current expression.
N defaults to 1. Slow."
(let ((parent-end (make-symbol "parent-end"))
(counter (make-symbol "ctr")))
`(and
(let ,counter (or ,n 1))
(let (,'\` ((,'\, ,pattern)))
(save-excursion
(condition-case nil
(progn
(while (>= (cl-decf ,counter) 0)
(or
(el-search--try-find-parent-beg)
(cond
((eq (char-before) ?`) (backward-char 1))
((eq (char-before) ?,) (backward-char 1))
((and (eq (char-before (1- (point))) ?,)
(eq (char-before) ?@))
(backward-char 2))
((eq (char-before) ?') (backward-char 1))
((and (eq (char-before (1- (point))) ?#)
(eq (char-before) ?'))
(backward-char 2))
(t (when-let* ((,parent-end (scan-lists (point) 1 1)))
(goto-char ,parent-end)
(backward-list))))))
(list (read (current-buffer))))
(scan-error nil)))))))
#+end_src
That should enable you to solve your task. Note it's experimental, and
I only had a quick look again now - want to go hiking!
One thing you can definitely _not_ do with this is to use it recursively
- i.e. (parent (parent PATTERN)) won't work (that's why I added the
optional N argument) - `parent' is only valid when applied to the
current expression.
Please tell me if it works for you.
BTW, another not yet uploaded pattern for matching strings you may find
useful is
#+begin_src emacs-lisp
(el-search-defpattern string-lines (pattern)
"Match any string whose line number is matched by PATTERN.
Examples: (string-lines 1) matches one-line strings.
\(string-lines (pred (>= 5))\) matches strings consisting of not
more than 5 lines."
(let ((string (make-symbol "string")))
`(and (string)
,string
(let ,pattern
(with-temp-buffer
(insert ,string)
(count-lines (point-min) (point-max)))))))
#+end_src
I don't know if it's useful enough to upload it.
Regards,
Michael.
next prev parent reply other threads:[~2017-12-25 14:56 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-25 10:27 [el-search] How to search string excluding docstring? Chunyang Xu
2017-12-25 10:40 ` Jean-Christophe Helary
2017-12-25 12:00 ` Skip Montanaro
2017-12-25 18:04 ` Michael Heerdegen
2017-12-25 14:56 ` Michael Heerdegen [this message]
2017-12-25 16:58 ` Chunyang Xu
2017-12-25 17:51 ` Michael Heerdegen
[not found] ` <mailman.6340.1514213787.27995.help-gnu-emacs@gnu.org>
2017-12-25 15:50 ` Emanuel Berg
2017-12-25 16:59 ` Michael Heerdegen
[not found] ` <mailman.6351.1514221174.27995.help-gnu-emacs@gnu.org>
2017-12-25 18:04 ` Emanuel Berg
[not found] <mailman.6328.1514197667.27995.help-gnu-emacs@gnu.org>
2017-12-25 12:00 ` Emanuel Berg
2017-12-25 13:57 ` Chunyang Xu
2017-12-25 14:34 ` Michael Heerdegen
[not found] ` <mailman.6334.1514210258.27995.help-gnu-emacs@gnu.org>
2017-12-25 14:08 ` Emanuel Berg
2017-12-25 17:55 ` tomas
[not found] ` <mailman.6358.1514224565.27995.help-gnu-emacs@gnu.org>
2017-12-25 18:11 ` Emanuel Berg
2017-12-25 19:14 ` tomas
[not found] ` <mailman.6366.1514229270.27995.help-gnu-emacs@gnu.org>
2017-12-25 19:36 ` Emanuel Berg
2017-12-25 21:20 ` tomas
[not found] ` <mailman.6371.1514236843.27995.help-gnu-emacs@gnu.org>
2017-12-25 21:56 ` Emanuel Berg
2017-12-26 2:44 ` Emanuel Berg
2017-12-26 13:34 ` Emanuel Berg
2017-12-26 13:48 ` Jean-Christophe Helary
[not found] ` <mailman.6381.1514296097.27995.help-gnu-emacs@gnu.org>
2017-12-26 15:19 ` Emanuel Berg
2017-12-27 5:38 ` Chunyang Xu
2017-12-27 13:58 ` Michael Heerdegen
[not found] ` <mailman.6406.1514353148.27995.help-gnu-emacs@gnu.org>
2017-12-27 6:58 ` Emanuel Berg
2017-12-25 19:39 ` Emanuel Berg
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87608u501d.fsf@web.de \
--to=michael_heerdegen@web.de \
--cc=help-gnu-emacs@gnu.org \
--cc=mail@xuchunyang.me \
/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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).