[Top][All Lists]
[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