Skip to content

Instantly share code, notes, and snippets.

@jefftrull
Created July 19, 2024 01:06
Show Gist options
  • Save jefftrull/10cae87ce38bdf6655b30af5891b0fa6 to your computer and use it in GitHub Desktop.
Save jefftrull/10cae87ce38bdf6655b30af5891b0fa6 to your computer and use it in GitHub Desktop.
** Jeff Trull: thing-at-point
*** Generalizes "things" - parseable elements in a buffer
- words, lines, sentences
- symbols and sexps
- emails and urls
- uuids
Imagine anything that might come after ~forward-~
**** Example
#+begin_src elisp
(with-temp-buffer
(save-excursion (insert "foo"))
(forward-word)
(point))
#+end_src
#+begin_src elisp
(with-temp-buffer
(save-excursion (insert "foo"))
(forward-thing 'word)
(point))
#+end_src
There's also motion commands ~beginning-of-thing~ and ~end-of-thing~ that work similarly.
*** Getting the thing
#+begin_src elisp
(with-temp-buffer
(save-excursion (insert "foo"))
(thing-at-point 'word)) ;; there is also "thing-at-mouse"!
#+end_src
*** Getting the boundaries of the thing
#+begin_src elisp
(with-temp-buffer
(save-excursion (insert "foo_"))
(bounds-of-thing-at-point 'word))
#+end_src
#+begin_src elisp
(with-temp-buffer
(save-excursion (insert "foo_"))
(bounds-of-thing-at-point 'symbol))
#+end_src
*** Writing your own thing-at-point provider
Let's make a thing called ~coord~, a comma-separated pair of coordinates in parentheses
**** Parser
#+begin_src elisp
(defun jet/parse-coord ()
(with-peg-rules
((number (and (opt (char ?-)) (+ [digit])))
(coord (and (char ?\() number (char ?,) number (char ?\)))))
(peg-run (peg (region coord) eob))))
#+end_src
**** thing-at-point Provider
#+begin_src elisp
(defun jet/bounds-of-coord-at-point ()
(save-excursion
(let ((pt (point))
(lim (point-max)))
;; search forward for parens
(skip-chars-forward "^()")
(if (and (eq (char-after) ?\() (eq (point) pt))
;; we began at a left paren. attempt to parse a coord
(jet/parse-coord) ;; returns bounds
(if (eq (point) lim)
;; we found no right parens
nil
(if (eq (char-after) ?\()
;; we found a left paren after our start point
nil
;; go to the start of this parenthesized expression
(backward-up-list)
(jet/parse-coord) ;; and return bounds (or nil)
))))))
#+end_src
**** Installation
#+begin_src elisp
(put 'coord 'bounds-of-thing-at-point 'jet/bounds-of-coord-at-point)
#+end_src
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment