emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: patch for thingatpt.el


From: Drew Adams
Subject: RE: patch for thingatpt.el
Date: Mon, 16 Jul 2007 14:01:21 -0700

> > Here is an updated change log and patch, which also
> > incorporates the `defun' bug fix I sent after the previous patch.
>
> > ! (defun symbol-at-point-with-bounds (&optional non-nil)
> > !   "Return (SYMBOL START . END) with START and END of SYMBOL.
> > ! Return nil if no such Emacs Lisp symbol is found.
> > ! SYMBOL is the `symbol-at-point' (which see).
> > ! If optional arg NON-NIL is non-nil, then the nearest symbol other
> > !   than `nil' is sought."
> > !   (with-syntax-table emacs-lisp-mode-syntax-table
> > !     (form-at-point-with-bounds
> > !      'symbol (if non-nil (lambda (sym) (and sym (symbolp sym)))
> > !                'symbolp))))
>
> This is wrong.  The name is clearly generic, whereas the
> docstring then goes on to say it's only specific to Emacs Lisp symbols.
> I think the name is right and the docstring (and code) are wrong.
>
> Check "recent" changes to symbol-at-point where I've fixed a
> similar problem (basically you shouldn't call `read').

I'm not sure which recent changes you mean. I see an entry for 2006-07-04
that mentions allowing symbol characters such as `(' and `''. Please
elaborate, if you meant some other change.

I think you're saying that you look at "symbol" here as referring to symbol
syntax, whatever the language, whereas I interpreted it as meaning a symbol
object in Emacs Lisp - that is, something that satisfies `symbolp'.

AFAIK, my interpretation was the traditional one for the meaning and
behavior of `symbol-at-point'. IIUC, `symbol-at-point' was intended to
retrieve Emacs-Lisp symbols, for use as default values in Emacs help
functions, for instance. You apparently changed the interpretation and
behavior last year; before that, `symbol-at-point' returned an Emacs-Lisp
symbol or nil if there was none at point. I wouldn't call such a change in
meaning a bug fix, but that's your call.

Emacs uses "symbol" in different ways, depending on the context. For
example, we have function `complete-symbol', which respects the current
symbol syntax, and we have function `lisp-complete-symbol', which uses Lisp
syntax and the names of objects that satisfy `symbolp'. Some of the function
names that contain "symbol" refer to symbols whose names respect Emacs-Lisp
syntax; others refer to symbols whose names respect the current symbol
syntax. I'm not sure if we have a convention, but `symbol' vs `lisp-symbol'
seems OK. (`complete-lisp-symbol' would be better than `lisp-complete
symbol', BTW.)

Below is a new patch. I've renamed the symbol and symbol-name functions that
I introduced, from `*symbol*' to `*lisp-symbol*'. I've restored your
definition of `symbol-at-point' (and added a doc string).

FWIW - I was wondering whether all of the current uses of `symbol-at-point'
in fact expect the current syntax table to define what constitutes a symbol,
or if, on the contrary, some of them might expect a symbol that respects
Emacs-Lisp syntax. When I grepped, I was surprised to see that
`symbol-at-point' is hardly used.

In my own code, I like to provide default values for user input, and I tend
to let users use completion for inputting, so I use a function that returns
a Lisp symbol (or its name) fairly often. In all such cases in my code, the
appropriate value is a name that respects Emacs-Lisp symbol syntax -
regardless of the current mode and syntax table. My guess is that if Emacs
were to do similarly, using more symbol-name default values, then most of
the need for a symbol or symbol name at or near point would be for an
Emacs-Lisp symbol. In any case, with the new names we should have sufficient
flexibility for whatever is needed.

---------8<------------------------

*** thingatpt-CVS-2007-07-14.el Sat Jul 14 08:40:06 2007
--- thingatpt-CVS-patched-2007-07-16b.el        Mon Jul 16 13:03:44 2007
***************
*** 49,79 ****

  (provide 'thingatpt)

! ;; Basic movement

! ;;;###autoload
! (defun forward-thing (thing &optional n)
!   "Move forward to the end of the Nth next THING."
!   (let ((forward-op (or (get thing 'forward-op)
!                       (intern-soft (format "forward-%s" thing)))))
!     (if (functionp forward-op)
!       (funcall forward-op (or n 1))
!       (error "Can't determine how to move over a %s" thing))))

! ;; General routines

  ;;;###autoload
  (defun bounds-of-thing-at-point (thing)
    "Determine the start and end buffer locations for the THING at point.
! THING is a symbol which specifies the kind of syntactic entity you want.
! Possibilities include `symbol', `list', `sexp', `defun', `filename',
`url',
! `email', `word', `sentence', `whitespace', `line', `page' and others.
!
! See the file `thingatpt.el' for documentation on how to define
! a symbol as a valid THING.

! The value is a cons cell (START . END) giving the start and end positions
! of the textual entity that was found."
    (if (get thing 'bounds-of-thing-at-point)
        (funcall (get thing 'bounds-of-thing-at-point))
      (let ((orig (point)))
--- 49,86 ----

  (provide 'thingatpt)

! ;;; Options

! (defcustom near-point-x-distance 50
!   "Maximum number of characters from point to search, left and right.
! Used by functions that provide default text for minibuffer input.
! Some functions might ignore or override this setting temporarily."
!   :type 'integer :group 'minibuffer)
!
! (defcustom near-point-y-distance 5
!   "Maximum number of lines from point to search, up and down.
! To constrain search to the same line as point, set this to zero.
! Used by functions that provide default text for minibuffer input.
! Some functions might ignore or override this setting temporarily."
!   :type 'integer :group 'minibuffer)

!
! ;;; THINGS -----------------------------------------------

  ;;;###autoload
  (defun bounds-of-thing-at-point (thing)
    "Determine the start and end buffer locations for the THING at point.
! THING is an Emacs-Lisp symbol that specifies the kind of syntactic
! entity you want.  Possibilities include `symbol', `list', `sexp',
! `defun', `filename', `url', `email', `word', `sentence', `whitespace',
! `line', `page' and others.  See file `thingatpt.el' for how to define
! a symbol as a valid THING.  The value returned is a cons cell (START
! . END) giving the start and end positions of the textual entity that
! was found."
!   (bounds-of-thing-at-point-1 thing))

! (defun bounds-of-thing-at-point-1 (thing)
!   "Helper function for `bounds-of-thing-at-point'."
    (if (get thing 'bounds-of-thing-at-point)
        (funcall (get thing 'bounds-of-thing-at-point))
      (let ((orig (point)))
***************
*** 120,211 ****
        (error nil)))))

  ;;;###autoload
! (defun thing-at-point (thing)
!   "Return the THING at point.
! THING is a symbol which specifies the kind of syntactic entity you want.
! Possibilities include `symbol', `list', `sexp', `defun', `filename',
`url',
! `email', `word', `sentence', `whitespace', `line', `page' and others.

! See the file `thingatpt.el' for documentation on how to define
  a symbol as a valid THING."
    (if (get thing 'thing-at-point)
        (funcall (get thing 'thing-at-point))
      (let ((bounds (bounds-of-thing-at-point thing)))
!       (if bounds
!         (buffer-substring (car bounds) (cdr bounds))))))

  ;; Go to beginning/end

  (defun beginning-of-thing (thing)
    (let ((bounds (bounds-of-thing-at-point thing)))
      (or bounds (error "No %s here" thing))
      (goto-char (car bounds))))

  (defun end-of-thing (thing)
    (let ((bounds (bounds-of-thing-at-point thing)))
      (or bounds (error "No %s here" thing))
      (goto-char (cdr bounds))))

  ;;  Special cases

! ;;  Lines

  ;; bolp will be false when you click on the last line in the buffer
  ;; and it has no final newline.
!
! (put 'line 'beginning-op
!      (lambda () (if (bolp) (forward-line -1) (beginning-of-line))))

  ;;  Sexps
-
  (defun in-string-p ()
    (let ((orig (point)))
      (save-excursion
        (beginning-of-defun)
        (nth 3 (parse-partial-sexp (point) orig)))))

  (defun end-of-sexp ()
    (let ((char-syntax (char-syntax (char-after (point)))))
      (if (or (eq char-syntax ?\))
            (and (eq char-syntax ?\") (in-string-p)))
        (forward-char 1)
        (forward-sexp 1))))
-
  (put 'sexp 'end-op 'end-of-sexp)

  (defun beginning-of-sexp ()
    (let ((char-syntax (char-syntax (char-before (point)))))
      (if (or (eq char-syntax ?\()
            (and (eq char-syntax ?\") (in-string-p)))
        (forward-char -1)
        (forward-sexp -1))))
-
  (put 'sexp 'beginning-op 'beginning-of-sexp)

  ;;  Lists
-
  (put 'list 'end-op (lambda () (up-list 1)))
  (put 'list 'beginning-op 'backward-sexp)

  ;;  Filenames and URLs  www.com/foo%32bar
-
  (defvar thing-at-point-file-name-chars "-~/[:alnum:]_.${}#%,:"
    "Characters allowable in filenames.")
!
! (put 'filename 'end-op
!      (lambda ()
!        (re-search-forward (concat "\\=[" thing-at-point-file-name-chars
"]*")
                          nil t)))
! (put 'filename 'beginning-op
!      (lambda ()
!        (if (re-search-backward (concat "[^" thing-at-point-file-name-chars
"]")
                               nil t)
           (forward-char)
         (goto-char (point-min)))))

  (defvar thing-at-point-url-path-regexp
    "[^]\t\n \"'()<>[^`{}]*[^]\t\n \"'()<>[^`{}.,;]+"
!   "A regular expression probably matching the host and filename or e-mail
part of a URL.")

  (defvar thing-at-point-short-url-regexp
    (concat "[-A-Za-z0-9.]+" thing-at-point-url-path-regexp)
--- 127,327 ----
        (error nil)))))

  ;;;###autoload
! (defun thing-at-point-with-bounds (thing)
!   "Return (THING START . END) with START and END of THING.
! Return nil if no 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'."
!   (let ((bounds (bounds-of-thing-at-point thing)))
!     (and bounds (cons (buffer-substring (car bounds) (cdr bounds))
bounds))))

! ;;;###autoload
! (defun thing-at-point (thing)
!   "Return the THING at point, or nil if there is none.
! THING is an Emacs-Lisp symbol that specifies the kind of syntactic
! entity you want.  Possibilities include `symbol', `list', `sexp',
! `defun', `filename', `url', `email', `word', `sentence', `whitespace',
! `line', `page' and others.  See file `thingatpt.el' for how to define
  a symbol as a valid THING."
    (if (get thing 'thing-at-point)
        (funcall (get thing 'thing-at-point))
      (let ((bounds (bounds-of-thing-at-point thing)))
!       (and bounds (buffer-substring (car bounds) (cdr bounds))))))
!
! ;;;###autoload
! (defun thing-nearest-point-with-bounds (thing)
!   "Return (THING START . END) with START and END of THING.
! Return nil if no THING is found.
! THING is the `thing-nearest-point' (which see)."
!   (thing/form-nearest-point-with-bounds #'thing-at-point-with-bounds
thing))
!
! (defun thing/form-nearest-point-with-bounds (fn thing &optional pred)
!   "Thing or form nearest point, with bounds.
! FN is a function returning a thing or form at point, with bounds.
!   If PRED is non-nil, then FN is called with THING and PRED as
!   arguments.  Otherwise, it is called with THING as argument.
! THING is the `thing-nearest-point' (which see).
! PRED is an optional predicate that THING must satisfy to qualify."
!   (let ((f-or-t+bds (if pred (funcall fn thing pred) (funcall fn thing)))
!         (ind1 0) (ind2 0) (bobp (bobp)) (updown 1)
!         (eobp (eobp)) (bolp (bolp)) (eolp (eolp))
!         (max-x (abs near-point-x-distance))
!         (max-y (abs near-point-y-distance)))
!     ;; IND2: Loop over lines (alternately up and down).
!     (while (and (<= ind2 max-y) (not f-or-t+bds) (not (and bobp eobp)))
!       (setq updown (- updown))          ; Switch directions up/down
(1/-1).
!       (save-excursion
!         (condition-case ()
!             (previous-line (* updown ind2)) ; 0, 1, -1, 2, -2, ...
!           (beginning-of-buffer (setq bobp t))
!           (end-of-buffer (setq eobp t))
!           (error nil))
!         ;; Don't try to go beyond buffer limit.
!         (unless (or (and bobp (natnump updown)) (and eobp (< updown 0)))
!           (setq f-or-t+bds (if pred (funcall fn thing pred) (funcall fn
thing))
!                 bolp (bolp)    eolp (eolp)    ind1 0)
!           (save-excursion
!             ;; IND1: Loop over chars in same line (alternately left and
right),
!             ;; until either found thing/form or both line limits reached.
!             (while (and (not (and bolp eolp))
!                         (<= ind1 max-x)
!                         (not f-or-t+bds))
!               (unless bolp (save-excursion ; Left.
!                              (setq bolp       (forward-char-same-line (-
ind1))
!                                    f-or-t+bds
!                                    (if pred (funcall fn thing pred)
(funcall fn thing)))))
!               (unless (or f-or-t+bds eolp) ; Right.
!                 (save-excursion
!                   (setq eolp (forward-char-same-line ind1)
!                         f-or-t+bds (if pred (funcall fn thing pred)
(funcall fn thing)))))
!               (setq ind1 (1+ ind1)))
!             (setq bobp (bobp)     eobp (eobp)))))
!       ;; Increase search line distance every second time (once up, once
down).
!       (when (or (< updown 0) (zerop ind2)) (setq ind2 (1+ ind2)))) ;
0,1,1,2,2...
!     f-or-t+bds))
!
! (defun forward-char-same-line (&optional arg)
!   "Move forward a max of ARG chars on the same line, or backward if ARG <
0.
! Return the signed number of chars moved if /= ARG, else return nil."
!   (interactive "p")
!   (let* ((start (point))
!          (fwd-p (natnump arg))
!          (max (save-excursion
!                 (if fwd-p (end-of-line) (beginning-of-line))
!                 (- (point) start))))
!     (forward-char (if fwd-p (min max arg) (max max arg)))
!     (and (< (abs max) (abs arg)) max)))
!
! ;;;###autoload
! (defun bounds-of-thing-nearest-point (thing)
!   "Return (START . END) with START and END of  type THING.
! Return nil if no such THING is found.  See `thing-nearest-point'."
!   (let ((thing+bds (thing-nearest-point-with-bounds thing)))
!     (and thing+bds (cdr thing+bds))))
!
! ;;;###autoload
! (defun thing-nearest-point (thing)
!   "Return the THING nearest to the cursor, if any, else return nil.
! \"Nearest\" to point is determined as follows:
!   The nearest THING on the same line is returned, if there is any.
!       Between two THINGs equidistant from point on the same line, the
!       leftmost is considered nearer.
!   Otherwise, neighboring lines are tried in sequence:
!   previous, next, 2nd previous, 2nd next, 3rd previous, 3rd next, etc.
!       This means that between two THINGs equidistant from point in
!       lines above and below it, the THING in the line above point
!       (previous Nth) is considered nearer to it.
! Related function `thing-at-point' returns the THING under the cursor,
! or nil if none."
!   (let ((thing+bds (thing-nearest-point-with-bounds thing)))
!     (and thing+bds (car thing+bds))))
!
!
! ;;; FORWARD, BEGINNING, END OPERATIONS ------------------------------
!
! ;;;###autoload
! (defun forward-thing (thing &optional n)
!   "Move forward to the end of the Nth next THING."
!   (let ((forward-op (or (get thing 'forward-op)
!                       (intern-soft (format "forward-%s" thing)))))
!     (if (functionp forward-op)
!       (funcall forward-op (or n 1))
!       (error "Can't determine how to move over a %s" thing))))

  ;; Go to beginning/end

  (defun beginning-of-thing (thing)
+   "Go to the beginning of THING."
    (let ((bounds (bounds-of-thing-at-point thing)))
      (or bounds (error "No %s here" thing))
      (goto-char (car bounds))))

  (defun end-of-thing (thing)
+   "Go to the end of THING."
    (let ((bounds (bounds-of-thing-at-point thing)))
      (or bounds (error "No %s here" thing))
      (goto-char (cdr bounds))))

  ;;  Special cases

! ;;  Defuns
! (put 'defun 'beginning-op 'beginning-of-defun)
! (put 'defun 'end-op 'end-of-defun)
! (put 'defun 'forward-op 'end-of-defun)

+ ;;  Lines
  ;; bolp will be false when you click on the last line in the buffer
  ;; and it has no final newline.
! (put 'line 'beginning-op (lambda ()
!                            (if (bolp) (forward-line -1)
(beginning-of-line))))

  ;;  Sexps
  (defun in-string-p ()
+   "True if point is inside a string."
    (let ((orig (point)))
      (save-excursion
        (beginning-of-defun)
        (nth 3 (parse-partial-sexp (point) orig)))))

  (defun end-of-sexp ()
+   "Go to the end of the sexp at point."
    (let ((char-syntax (char-syntax (char-after (point)))))
      (if (or (eq char-syntax ?\))
            (and (eq char-syntax ?\") (in-string-p)))
        (forward-char 1)
        (forward-sexp 1))))
  (put 'sexp 'end-op 'end-of-sexp)

  (defun beginning-of-sexp ()
+   "Go to the beginning of the sexp at point."
    (let ((char-syntax (char-syntax (char-before (point)))))
      (if (or (eq char-syntax ?\()
            (and (eq char-syntax ?\") (in-string-p)))
        (forward-char -1)
        (forward-sexp -1))))
  (put 'sexp 'beginning-op 'beginning-of-sexp)

  ;;  Lists
  (put 'list 'end-op (lambda () (up-list 1)))
  (put 'list 'beginning-op 'backward-sexp)

  ;;  Filenames and URLs  www.com/foo%32bar
  (defvar thing-at-point-file-name-chars "-~/[:alnum:]_.${}#%,:"
    "Characters allowable in filenames.")
! (put 'filename 'end-op (lambda ()
!                          (re-search-forward
!                           (concat "\\=[" thing-at-point-file-name-chars
"]*")
                          nil t)))
! (put 'filename 'beginning-op (lambda ()
!                                (if (re-search-backward
!                                     (concat "[^"
thing-at-point-file-name-chars "]")
                                      nil t)
                                     (forward-char)
                                   (goto-char (point-min)))))

  (defvar thing-at-point-url-path-regexp
    "[^]\t\n \"'()<>[^`{}]*[^]\t\n \"'()<>[^`{}.,;]+"
!   "A regexp probably matching the host and filename or e-mail part of a
URL.")

  (defvar thing-at-point-short-url-regexp
    (concat "[-A-Za-z0-9.]+" thing-at-point-url-path-regexp)
***************
*** 238,245 ****
    "A regular expression matching a URL marked up per RFC1738.
  This may contain whitespace (including newlines) .")

- (put 'url 'bounds-of-thing-at-point
'thing-at-point-bounds-of-url-at-point)
  (defun thing-at-point-bounds-of-url-at-point ()
    (let ((strip (thing-at-point-looking-at
                         thing-at-point-markedup-url-regexp))) ;; (url "") short
      (if (or strip
--- 354,361 ----
    "A regular expression matching a URL marked up per RFC1738.
  This may contain whitespace (including newlines) .")

  (defun thing-at-point-bounds-of-url-at-point ()
+   "Return the bounds of the URL around or before point."
    (let ((strip (thing-at-point-looking-at
                         thing-at-point-markedup-url-regexp))) ;; (url "") short
      (if (or strip
***************
*** 254,269 ****
              (setq beginning (+ beginning 5))
              (setq end (- end 1)))
          (cons beginning end)))))

- (put 'url 'thing-at-point 'thing-at-point-url-at-point)
  (defun thing-at-point-url-at-point ()
    "Return the URL around or before point.
-
  Search backwards for the start of a URL ending at or after point.  If
  no URL found, return nil.  The access scheme will be prepended if
  absent: \"mailto:\"; if the string contains \"@\", \"ftp://\"; if it
  starts with \"ftp\" and not \"ftp:/\", or \"http://\"; by default."
-
    (let ((url "") short strip)
      (if (or (setq strip (thing-at-point-looking-at
                         thing-at-point-markedup-url-regexp))
--- 370,383 ----
              (setq beginning (+ beginning 5))
              (setq end (- end 1)))
          (cons beginning end)))))
+ (put 'url 'bounds-of-thing-at-point
'thing-at-point-bounds-of-url-at-point)

  (defun thing-at-point-url-at-point ()
    "Return the URL around or before point.
  Search backwards for the start of a URL ending at or after point.  If
  no URL found, return nil.  The access scheme will be prepended if
  absent: \"mailto:\"; if the string contains \"@\", \"ftp://\"; if it
  starts with \"ftp\" and not \"ftp:/\", or \"http://\"; by default."
    (let ((url "") short strip)
      (if (or (setq strip (thing-at-point-looking-at
                         thing-at-point-markedup-url-regexp))
***************
*** 291,296 ****
--- 405,411 ----
          (if (string-equal "" url)
              nil
            url)))))
+ (put 'url 'thing-at-point 'thing-at-point-url-at-point)

  ;; The normal thingatpt mechanism doesn't work for complex regexps.
  ;; This should work for almost any regexp wherever we are in the
***************
*** 326,332 ****
                    (setq match (point))))
        (goto-char match)
        (looking-at regexp)))))
-
  (put 'url 'end-op
       (lambda ()
         (let ((bounds (thing-at-point-bounds-of-url-at-point)))
--- 441,446 ----
***************
*** 351,357 ****
  ;; not sure they're actually needed, and URL seems to skip them too.
  ;; Note that (end-of-thing 'email) and (beginning-of-thing 'email)
  ;; work automagically, though.
-
  (put 'email 'bounds-of-thing-at-point
       (lambda ()
         (let ((thing (thing-at-point-looking-at
thing-at-point-email-regexp)))
--- 465,470 ----
***************
*** 359,365 ****
               (let ((beginning (match-beginning 0))
                     (end (match-end 0)))
                 (cons beginning end))))))
-
  (put 'email 'thing-at-point
       (lambda ()
         (let ((boundary-pair (bounds-of-thing-at-point 'email)))
--- 472,477 ----
***************
*** 368,375 ****
                (car boundary-pair) (cdr boundary-pair))))))

  ;;  Whitespace
-
  (defun forward-whitespace (arg)
    (interactive "p")
    (if (natnump arg)
        (re-search-forward "[ \t]+\\|\n" nil 'move arg)
--- 480,488 ----
                (car boundary-pair) (cdr boundary-pair))))))

  ;;  Whitespace
  (defun forward-whitespace (arg)
+   "Move forward over ARG groups of TAB or SPC characters or ARG lines.
+ Move backward if ARG is negative."
    (interactive "p")
    (if (natnump arg)
        (re-search-forward "[ \t]+\\|\n" nil 'move arg)
***************
*** 379,417 ****
              (skip-chars-backward " \t")))
        (setq arg (1+ arg)))))

! ;;  Buffer
!
  (put 'buffer 'end-op (lambda () (goto-char (point-max))))
  (put 'buffer 'beginning-op (lambda () (goto-char (point-min))))

  ;;  Symbols
-
  (defun forward-symbol (arg)
    (interactive "p")
    (if (natnump arg)
        (re-search-forward "\\(\\sw\\|\\s_\\)+" nil 'move arg)
      (while (< arg 0)
!       (if (re-search-backward "\\(\\sw\\|\\s_\\)+" nil 'move)
          (skip-syntax-backward "w_"))
        (setq arg (1+ arg)))))

  ;;  Syntax blocks
-
  (defun forward-same-syntax (&optional arg)
    (interactive "p")
    (while (< arg 0)
!     (skip-syntax-backward
!      (char-to-string (char-syntax (char-after (1- (point))))))
      (setq arg (1+ arg)))
    (while (> arg 0)
      (skip-syntax-forward (char-to-string (char-syntax (char-after
(point)))))
      (setq arg (1- arg))))

- ;;  Aliases
-
- (defun word-at-point () (thing-at-point 'word))
- (defun sentence-at-point () (thing-at-point 'sentence))
-
  (defun read-from-whole-string (str)
    "Read a Lisp expression from STR.
  Signal an error if the entire string was not used."
--- 492,527 ----
              (skip-chars-backward " \t")))
        (setq arg (1+ arg)))))

! ;;  Buffers
  (put 'buffer 'end-op (lambda () (goto-char (point-max))))
  (put 'buffer 'beginning-op (lambda () (goto-char (point-min))))

  ;;  Symbols
  (defun forward-symbol (arg)
+   "Move forward ARG symbols.  Move backward if ARG is negative.
+ \"Symbol\" here means any group of symbol characters.  The current
+ syntax table is used to determine which characters are symbol
+ characters."
    (interactive "p")
    (if (natnump arg)
        (re-search-forward "\\(\\sw\\|\\s_\\)+" nil 'move arg)
      (while (< arg 0)
!       (when (re-search-backward "\\(\\sw\\|\\s_\\)+" nil 'move)
          (skip-syntax-backward "w_"))
        (setq arg (1+ arg)))))

  ;;  Syntax blocks
  (defun forward-same-syntax (&optional arg)
+   "Move forward over ARG groups of characters with the same syntax.
+ Move backward if ARG is negative."
    (interactive "p")
    (while (< arg 0)
!     (skip-syntax-backward (char-to-string (char-syntax (char-after (1-
(point))))))
      (setq arg (1+ arg)))
    (while (> arg 0)
      (skip-syntax-forward (char-to-string (char-syntax (char-after
(point)))))
      (setq arg (1- arg))))

  (defun read-from-whole-string (str)
    "Read a Lisp expression from STR.
  Signal an error if the entire string was not used."
***************
*** 426,447 ****
        (error "Can't read whole string")
        (car read-data))))

  (defun form-at-point (&optional thing pred)
    (let ((sexp (condition-case nil
                  (read-from-whole-string (thing-at-point (or thing 'sexp)))
                (error nil))))
      (if (or (not pred) (funcall pred sexp)) sexp)))

  ;;;###autoload
! (defun sexp-at-point ()   (form-at-point 'sexp))
  ;;;###autoload
  (defun symbol-at-point ()
!   (let ((thing (thing-at-point 'symbol)))
!     (if thing (intern thing))))
  ;;;###autoload
! (defun number-at-point () (form-at-point 'sexp 'numberp))
  ;;;###autoload
! (defun list-at-point ()   (form-at-point 'list 'listp))

  ;; arch-tag: bb65a163-dae2-4055-aedc-fe11f497f698
  ;;; thingatpt.el ends here
--- 536,813 ----
        (error "Can't read whole string")
        (car read-data))))

+
+ ;;; FORMS ----------------------------------------------------------
+
+ ;;;###autoload
+ (defun form-at-point-with-bounds (&optional thing pred)
+   "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.
+ THING is the kind of form desired (default: `sexp').
+ PRED is a predicate that THING must satisfy to qualify."
+   (let* ((thing+bds (thing-at-point-with-bounds (or thing 'sexp)))
+          (sexp (and thing+bds
+                     (condition-case nil
+                         (read-from-whole-string (car thing+bds))
+                       (error nil)))))   ; E.g. tries to read `.'.
+     (and (or sexp (and thing+bds (string= "nil" (car thing+bds)))) ; Could
be `nil'.
+          (or (not pred) (funcall pred sexp))
+          (cons sexp (cdr thing+bds)))))
+
+ ;;;###autoload
+ (defun bounds-of-form-at-point (&optional thing pred)
+   "Return (START . END), with START and END of `form-at-point'.
+ THING is the kind of form desired (default: `sexp').
+ PRED is a predicate that THING must satisfy to qualify."
+   (let ((form+bds (form-at-point-with-bounds thing pred)))
+     (and form+bds (cdr form+bds))))
+
+ ;;;###autoload
  (defun form-at-point (&optional thing pred)
+   "Return the form nearest to the cursor, if any, else return nil.
+ The form is a Lisp entity, not necessarily a string.
+ THING is the kind of form desired (default: `sexp').
+ PRED is a predicate that THING must satisfy to qualify."
    (let ((sexp (condition-case nil
                  (read-from-whole-string (thing-at-point (or thing 'sexp)))
                (error nil))))
      (if (or (not pred) (funcall pred sexp)) sexp)))

  ;;;###autoload
! (defun form-nearest-point-with-bounds (&optional thing pred)
!   "Return (FORM START . END), START and END the char positions of FORM.
! FORM is the `form-nearest-point'.
! Return nil if no such form is found.
! THING is the kind of form desired (default: `sexp').
! PRED is a predicate that THING must satisfy to qualify."
!   (thing/form-nearest-point-with-bounds #'form-at-point-with-bounds thing
pred))
!
! ;;;###autoload
! (defun bounds-of-form-nearest-point (&optional thing pred)
!   "Return (START . END) with START and END of `form-nearest-point'.
! Return nil if no such form is found.
! THING is the kind of form desired (default: `sexp').
! PRED is a predicate that THING must satisfy to qualify."
!   (let ((form+bds (form-nearest-point-with-bounds thing pred)))
!     (and form+bds (cdr form+bds))))
!
! ;;;###autoload
! (defun form-nearest-point (&optional thing pred)
!   "Return the form nearest to the cursor, if any, else return nil.
! \"Nearest\" to point is determined as for `thing-nearest-point'.
! THING is the kind of form desired (default: `sexp').
! PRED is a predicate that THING must satisfy to qualify."
!   (let ((form+bds (form-nearest-point-with-bounds thing pred)))
!     (and form+bds (car form+bds))))
!
!
! ;;; SYMBOLS ----------------------------------------------------------
!
  ;;;###autoload
  (defun symbol-at-point ()
!   "Return the symbol under the cursor, or nil if none.
! \"Symbol\" here means any Emacs-Lisp symbol whose name has symbol
! characters.  The current syntax table is used to determine which
! characters are symbol characters."
!   (let ((thing (thing-at-point 'symbol))) (if thing (intern thing))))
!
! ;;;###autoload
! (defun lisp-symbol-at-point-with-bounds (&optional non-nil)
!   "Return (SYMBOL START . END) with START and END of SYMBOL.
! Return nil if no such Emacs-Lisp symbol is found.
! SYMBOL is the `lisp-symbol-at-point' (which see).
! If optional arg NON-NIL is non-nil, then the nearest symbol other
! than `nil' is sought."
!   (with-syntax-table emacs-lisp-mode-syntax-table
!     (form-at-point-with-bounds
!      'symbol (if non-nil (lambda (sym) (and sym (symbolp sym)))
'symbolp))))
!
! ;;;###autoload
! (defun bounds-of-lisp-symbol-at-point (&optional non-nil)
!   "Return (START . END) with START and END of `lisp-symbol-at-point'.
! If optional arg NON-NIL is non-nil, then the nearest Emacs-Lisp symbol
! other than `nil' is sought."
!   (let ((symb+bds (lisp-symbol-at-point-with-bounds non-nil)))
!     (and symb+bds (cdr symb+bds))))
!
! ;;;###autoload
! (defun lisp-symbol-at-point (&optional non-nil)
!   "Return the Emacs-Lisp symbol under the cursor, or nil if none.
! If optional arg NON-NIL is non-nil, then the nearest symbol other
!   than `nil' is sought.
! Some related functions:
!   `symbol-at-point' returns the Emacs-Lisp symbol at point whose name
!     is composed of symbol characters, where such characters are
!     determined by the current syntax table.
!   `lisp-symbol-nearest-point' returns the Emacs-Lisp symbol nearest
!     the cursor, or nil if none.
!   `lisp-symbol-name-nearest-point' returns the name of
!     `lisp-symbol-nearest-point' as a string, or \"\" if none.
!   `lisp-symbol-name-before-point' returns the string naming the symbol
!     at or before the cursor (even if it is on a previous line) or \"\"
!     if none.
!   `word-before-point' returns the word (a string) at or before cursor.
! Note that these last three functions return strings, not symbols."
!   (with-syntax-table emacs-lisp-mode-syntax-table
!     (form-at-point
!      'symbol (if non-nil (lambda (sym) (and sym (symbolp sym)))
'symbolp))))
!
! ;;;###autoload
! (defun lisp-symbol-nearest-point-with-bounds (&optional non-nil)
!   "Return (SYMBOL START . END) with START and END of SYMBOL.
! Return nil if no such Emacs-Lisp symbol is found.
! SYMBOL is the `lisp-symbol-nearest-point' (which see).
! If optional arg NON-NIL is non-nil, then the nearest Emacs-Lisp symbol
! other than `nil' is sought."
!   (with-syntax-table emacs-lisp-mode-syntax-table
!     (form-nearest-point-with-bounds
!      'symbol (if non-nil (lambda (sym) (and sym (symbolp sym)))
'symbolp))))
!
! ;;;###autoload
! (defun bounds-of-lisp-symbol-nearest-point (&optional non-nil)
!   "Return (START . END) with START and END of `lisp-symbol-nearest-point'.
! If optional arg NON-NIL is non-nil, then the nearest symbol other
! than `nil' is sought."
!   (let ((symb+bds (lisp-symbol-nearest-point-with-bounds non-nil)))
!     (and symb+bds (cdr symb+bds))))
!
! ;;;###autoload
! (defun lisp-symbol-nearest-point (&optional non-nil)
!   "Return the Emacs-Lisp symbol nearest the cursor, or nil if none.
! \"Nearest\" to point is determined as for `thing-nearest-point'.
! If optional arg NON-NIL is non-nil, then the nearest symbol other
!   than `nil' is sought.
! Some related functions:
!   `symbol-at-point' returns the Emacs-Lisp symbol at point whose name
!     is composed of symbol characters, where such characters are
!     determined by the current syntax table.
!   `lisp-symbol-at-point' returns the Emacs-Lisp symbol under the
!     cursor, or nil if none.
!   `lisp-symbol-name-nearest-point' returns the name of
!     `lisp-symbol-nearest-point' as a string, or \"\" if none.
!   `lisp-symbol-name-before-point' returns the string naming the symbol
!     at or before the cursor (even if it is on a previous line) or \"\"
!     if none.
!   `word-at-point' returns the word at point, or nil if none.
!   `word-nearest-point' returns the word nearest point, or \"\" if none.
!   `word-before-point' returns the word at or before the cursor as a
string.
! Note that these last three functions return strings, not symbols."
!   (let ((symb+bds (lisp-symbol-nearest-point-with-bounds non-nil)))
!     (and symb+bds (car symb+bds))))
!
  ;;;###autoload
! (defun non-nil-lisp-symbol-nearest-point ()
!   "Return the Emacs-Lisp symbol other than `nil' nearest the cursor.
! Return nil if none is found.
! \"Nearest\" to point is determined as for `thing-nearest-point'.
! Some related functions:
!   `symbol-at-point' returns the Emacs-Lisp symbol at point whose name
!     is composed of symbol characters, where such characters are
!     determined by the current syntax table.
!   `lisp-symbol-at-point' returns the Emacs-Lisp symbol under the
!     cursor, or nil if none.
!   `lisp-symbol-name-nearest-point' returns the name of
!     `lisp-symbol-nearest-point' as a string, or \"\" if none.
!   `lisp-symbol-name-before-point' returns the string naming the symbol
!     at or before the cursor (even if it is on a previous line) or \"\"
!     if none.
!   `word-at-point' returns the word at point, or nil if none.
!   `word-nearest-point' returns the word nearest point, or \"\" if none.
!   `word-before-point' returns the word at or before the cursor as a
string.
! Note that these last three functions return strings, not symbols."
!   (let ((symb+bds (symbol-nearest-point-with-bounds t)))
!     (and symb+bds (car symb+bds))))
!
!
! ;;; SYMBOL NAMES, WORDS, SENTENCES, SEXPS, NUMBERS, LISTS, etc. ----------
!
! ;;;###autoload
! (defun lisp-symbol-name-at-point ()
!   "String naming the Emacs-Lisp symbol at point, or \"\" if none."
!   ;; We do it this way to be able to pick symbol `nil' (name "nil").
!   (let ((symb+bds (lisp-symbol-at-point-with-bounds)))
!     (if symb+bds (symbol-name (car symb+bds)) "")))
!
! ;;;###autoload
! (defun non-nil-lisp-symbol-name-at-point ()
!   "String naming the Emacs-Lisp symbol nearest point, or \"\" if none.
! Returns the name of the nearest Emacs-Lisp symbol other than `nil'.
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   (let ((symb+bds (lisp-symbol-at-point-with-bounds t)))
!     (if symb+bds (symbol-name (car symb+bds)) "")))
!
! ;;;###autoload
! (defun lisp-symbol-name-nearest-point ()
!   "String naming the Emacs-Lisp symbol nearest point, or \"\" if none.
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   ;; We do it this way to be able to pick symbol `nil' (name "nil").
!   (let ((symb+bds (lisp-symbol-nearest-point-with-bounds)))
!     (if symb+bds (symbol-name (car symb+bds)) "")))
!
! ;;;###autoload
! (defun non-nil-lisp-symbol-name-nearest-point ()
!   "String naming the Emacs-Lisp symbol nearest point, or \"\" if none.
! Returns the name of the nearest Emacs-Lispsymbol other than `nil'.
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   (let ((symb+bds (lisp-symbol-nearest-point-with-bounds t)))
!     (if symb+bds (symbol-name (car symb+bds)) "")))
!
! ;;;###autoload
! (defun word-at-point ()
!   "Return the word (a string) nearest to point, if any, else \"\"."
!   (thing-at-point 'word))
!
! ;;;###autoload
! (defun word-nearest-point ()
!   "Return the word (a string) nearest to point, if any, else \"\".
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   (thing-nearest-point 'word))
!
! ;;;###autoload
! (defun sentence-at-point ()
!   "Return the sentence (a string) nearest to point, if any, else \"\"."
!   (thing-at-point 'sentence))
!
! ;;;###autoload
! (defun sentence-nearest-point ()
!   "Return the sentence (a string) nearest to point, if any, else \"\".
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   (thing-nearest-point 'sentence))
!
! ;;;###autoload
! (defun sexp-at-point ()
!   "Return the sexp (a string) nearest to point, if any, else \"\"."
!   (form-at-point 'sexp))
!
! ;;;###autoload
! (defun sexp-nearest-point ()
!   "Return the sexp (a string) nearest to point, if any, else \"\".
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   (form-nearest-point 'sexp))
!
! ;;;###autoload
! (defun number-at-point ()
!   "Return the number at point, if any, else nil."
!   (form-at-point 'sexp 'numberp))
!
! ;;;###autoload
! (defun number-nearest-point ()
!   "Return the number nearest to point, if any, else nil.
! \"Nearest\" to point is determined as for `thing-nearest-point'."
!   (form-nearest-point 'sexp 'numberp))
!
! ;;;###autoload
! (defun list-at-point ()
!   "Return the list nearest to point, if any, else nil."
!   (form-at-point 'list 'listp))
!
  ;;;###autoload
! (defun list-nearest-point ()
!   "Return the list nearest to point, if any, else nil.
! This does not distinguish between finding no list and finding
! the empty list.  \"Nearest\" to point is determined as for
! `thing-nearest-point'."
!   (form-nearest-point 'list 'listp))

  ;; arch-tag: bb65a163-dae2-4055-aedc-fe11f497f698
  ;;; thingatpt.el ends here






reply via email to

[Prev in Thread] Current Thread [Next in Thread]