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: Thu, 26 Jul 2007 08:06:46 -0700

Resending patch. What is the status of this?

> From: Drew Adams Sent: Monday, July 16, 2007 2:01 PM
>
> > > 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]