From: "Drew Adams" <drew.adams@oracle.com>
To: "'Chong Yidong'" <cyd@stupidchicken.com>
Cc: 8628@debbugs.gnu.org
Subject: bug#8628: 24.0.50; `thing-at-point-bounds-of-list-at-point' - no good
Date: Fri, 8 Jul 2011 17:10:54 -0700 [thread overview]
Message-ID: <546E2B1593B54F21A7C3EC3E4F842330@us.oracle.com> (raw)
In-Reply-To: <8F3C066C93F84F0CB6E730F074F75697@us.oracle.com>
FWIW, you can find new definitions of the list-at-point functions, which work
correctly, in my library thingatpt+.el:
http://www.emacswiki.org/emacs/download/thingatpt%2b.el
The definitions are general.
They handle correctly all cases; i.e., where point is:
a. within a list,
b. just after/before or at a list end/beginning, and
c. outside any list.
They return the non-nil list in (a) and (b), and nil in (c).
For the current question, which concerns (bounds-of-thing-at-point 'list), this
is the code I use, in case you want to test:
(put 'list 'bounds-of-thing-at-point 'bounds-of-list-at-point)
(defun bounds-of-list-at-point (&optional up unquotedp)
"Return (START . END), boundaries of the `list-at-point'.
Return nil if no non-empty list is found.
UP (default: 0) is the number of list levels to go up to start with.
Non-nil UNQUOTEDP means remove the car if it is `quote' or
`backquote-backquote-symbol'."
(let ((thing+bds (list-at-point-with-bounds up unquotedp)))
(and thing+bds (cdr thing+bds))))
(defun list-at-point-with-bounds (&optional up unquotedp)
"Return (LIST START . END), boundaries of the `list-at-point'.
Return nil if no non-empty list is found.
UP (default: 0) is the number of list levels to go up to start with.
Non-nil UNQUOTEDP means remove the car if it is `quote' or
`backquote-backquote-symbol'."
(list-at/nearest-point-with-bounds
'sexp-at-point-with-bounds up unquotedp))
(defun list-at/nearest-point-with-bounds (at/near &optional up unquotedp)
"Helper for `list-at-point-with-bounds' and similar functions.
AT/NEAR is a function called to grab the initial list and its bounds.
UP (default: 0) is the number of list levels to go up to start with.
Non-nil UNQUOTEDP means remove the car if it is `quote' or
`backquote-backquote-symbol'.
Return (LIST START . END) with START and END of the LIST.
Return nil if no non-empty list is found."
(save-excursion
(unless (eq at/near 'sexp-at-point-with-bounds)
(cond ((looking-at "\\s-*\\s(") (skip-syntax-forward "-"))
((looking-at "\\s)\\s-*") (skip-syntax-backward "-"))))
(let ((sexp+bnds (funcall at/near)))
(condition-case nil ; Handle an `up-list' error.
(progn
(when up
(up-list (- up))
(setq sexp+bnds (sexp-at-point-with-bounds)))
(while (not (consp (car sexp+bnds)))
(up-list -1)
(setq sexp+bnds (sexp-at-point-with-bounds)))
(when (and unquotedp (consp (car sexp+bnds))
(memq (caar sexp+bnds)
(list backquote-backquote-symbol 'quote)))
(cond ((eq 'quote (caar sexp+bnds))
(setq sexp+bnds
(cons (cadr (car sexp+bnds))
(cons (+ 5 (cadr sexp+bnds))
(cddr sexp+bnds)))))
((eq backquote-backquote-symbol (caar sexp+bnds))
(setq sexp+bnds (cons (cadr (car sexp+bnds))
(cons (+ 1 (cadr sexp+bnds))
(cddr sexp+bnds)))))))
(while (not (consp (car sexp+bnds)))
(up-list -1)
(setq sexp+bnds (sexp-at-point-with-bounds))))
(error (setq sexp+bnds nil)))
sexp+bnds)))
(defun sexp-at-point-with-bounds (&optional pred syntax-table)
"Return (SEXP START . END), boundaries of the `sexp-at-point'.
Return nil if no sexp is found.
Optional args are the same as for `form-at-point-with-bounds'."
(form-at-point-with-bounds 'sexp pred syntax-table))
(defun form-at-point-with-bounds (&optional thing pred syntax-table)
"Return (FORM START . END), START and END the char positions of FORM.
FORM is the `form-at-point'. Return nil if no form is found.
Optional arguments:
THING is the kind of form desired (default: `sexp').
PRED is a predicate that THING must satisfy to qualify.
SYNTAX-TABLE is a syntax table to use."
(condition-case nil ; E.g. error if tries to read `.'.
(let* ((thing+bds (thing-at-point-with-bounds
(or thing 'sexp) syntax-table))
(bounds (cdr thing+bds))
(sexp (and bounds (read-from-whole-string
(car thing+bds)))))
(and bounds (or (not pred) (funcall pred sexp))
(cons sexp bounds)))
(error nil)))
(defun thing-at-point-with-bounds (thing &optional syntax-table)
"Return (THING START . END) with START and END of THING.
Return nil if no such THING is found.
THING is the `thing-at-point' (which see).
START and END are the car and cdr of the `bounds-of-thing-at-point'.
SYNTAX-TABLE is a syntax table to use."
(let ((bounds (bounds-of-thing-at-point thing syntax-table)))
(and bounds
(cons (buffer-substring (car bounds) (cdr bounds)) bounds))))
(defun bounds-of-thing-at-point (thing &optional syntax-table)
"Determine the start and end buffer locations for the THING at point.
Return a consp `(START . END)' giving the START and END positions,
where START /= END. Return nil if no such THING is found.
THING is an entity for which there is a either a corresponding
`forward-'THING operation, or corresponding `beginning-of-'THING and
`end-of-'THING operations. THING examples include `word', `sentence',
`defun'.
SYNTAX-TABLE is a syntax table to use.
See the commentary of library `thingatpt.el' for how to define a
symbol as a valid THING."
(if syntax-table
(let ((buffer-syntax (syntax-table)))
(unwind-protect
(progn (set-syntax-table syntax-table)
(bounds-of-thing-at-point-1 thing))
(set-syntax-table buffer-syntax)))
(bounds-of-thing-at-point-1 thing)))
;; This is the original `bounds-of-thing-at-point',
;; but with bug #8667 fixed.
(defun bounds-of-thing-at-point-1 (thing)
"Helper for `bounds-of-thing-at-point'.
Do all except handle the optional SYNTAX-TABLE arg."
(if (get thing 'bounds-of-thing-at-point)
(funcall (get thing 'bounds-of-thing-at-point))
(let ((orig (point)))
(condition-case nil
(save-excursion
;; Try moving forward, then back.
(funcall (or (get thing 'end-op) ; Move to end.
(lambda () (forward-thing thing 1))))
(funcall (or (get thing 'beginning-op) ; Move to beg.
(lambda () (forward-thing thing -1))))
(let ((beg (point)))
(if (<= beg orig)
;; If that brings us all the way back to ORIG,
;; it worked. But END may not be the real end.
;; So find the real end that corresponds to BEG.
;; FIXME:
;; in which cases can `real-end' differ from `end'?
(let ((real-end (progn
(funcall
(or (get thing 'end-op)
(lambda ()
(forward-thing thing 1))))
(point))))
(and (<= orig real-end) (< beg real-end)
(cons beg real-end)))
(goto-char orig)
;; Try a second time, moving first backward then forward,
;; so that we can find a thing that ends at ORIG.
(funcall (or (get thing 'beginning-op) ; Move to beg.
(lambda () (forward-thing thing -1))))
(funcall (or (get thing 'end-op) ; Move to end.
(lambda () (forward-thing thing 1))))
(let ((end (point))
(real-beg (progn
(funcall
(or (get thing 'beginning-op)
(lambda ()
(forward-thing thing -1))))
(point))))
(and (<= real-beg orig) (<= orig end) (< real-beg end)
(cons real-beg end))))))
(error nil)))))
prev parent reply other threads:[~2011-07-09 0:10 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-06 0:29 bug#8628: 24.0.50; `thing-at-point-bounds-of-list-at-point' - no good Drew Adams
2011-05-06 0:41 ` Drew Adams
2011-05-13 19:34 ` Stefan Monnier
2011-05-13 20:06 ` Drew Adams
2011-05-13 22:49 ` Juanma Barranquero
2011-05-13 23:11 ` Drew Adams
2011-07-07 18:43 ` Chong Yidong
2011-07-07 21:27 ` Drew Adams
2011-07-07 22:28 ` Chong Yidong
2011-07-07 23:39 ` Drew Adams
2011-07-09 0:10 ` Drew Adams [this message]
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=546E2B1593B54F21A7C3EC3E4F842330@us.oracle.com \
--to=drew.adams@oracle.com \
--cc=8628@debbugs.gnu.org \
--cc=cyd@stupidchicken.com \
/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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
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).