clojure-emacs / clojure-ts-mode

The next generation Clojure major mode for Emacs, powered by TreeSitter
GNU General Public License v3.0
129 stars 11 forks source link

Add syntax table #14

Closed jasonjckn closed 1 year ago

jasonjckn commented 1 year ago

This adds a syntax table to clojure-ts-mode, Emacs syntax tables are used to determine where words, symbols, and other syntactic constructs begin and end. This information is used by many Emacs facilities, (not just font locking).

I ran into a use case for it, while using cider.

Cider relies on clojure-mode.el clojure-find-ns which relies on (thing-at-point 'symbol) to give you the full clojure symbol, in many of it's functionality. e.g. When Cider is sending sexp's to the nREPL it needs to determine which namespace that sexp should be executed under, and this boils down to a (thing-at-point 'symbol) call. Originally, I was getting 'namespace' not found, because at the top of my file (ns foo.bar), (thing-at-point 'symbol) was being called by cider at the beginning of the symbol , but thing-at-point was returning 'foo instead of 'foo.bar leading to my sexps being evaluated under the wrong namespace. Some of the code for this can be found at: https://github.com/clojure-emacs/clojure-mode/blob/master/clojure-mode.el#L2142

This PR simply adds a syntax table, i've confirmed thing-at-point behaves as expected now. The syntax table I copied verbatim from clojure-mode.el, so it'll be accurate.


Before submitting a PR mark the checkboxes for the items you've done (if you think a checkbox does not apply, then leave it unchecked):

Thanks!

dannyfreeman commented 1 year ago

How does anything use this syntax table? I get that this fix works and clojure-mode just defines it and nothing else. But what kind of magic is emacs doing to find it?

sogaiu commented 1 year ago

I think at least one thing that might be affected is how syntax-ppss / parse-partial-sexp behaves.

The parse state it returns apparently contains:

Value is a list of elements describing final state of parsing:
 0. depth in parens.
 1. character address of start of innermost containing list; nil if none.
 2. character address of start of last complete sexp terminated.
 3. non-nil if inside a string.
    (it is the character that will terminate the string,
     or t if the string should be terminated by a generic string delimiter.)
 4. nil if outside a comment, t if inside a non-nestable comment,
    else an integer (the current comment nesting).
 5. t if following a quote character.
 6. the minimum paren-depth encountered during this scan.
 7. style of comment, if any.
 8. character address of start of comment or string; nil if not in one.
 9. List of positions of currently open parens, outermost first.
10. When the last position scanned holds the first character of a
    (potential) two character construct, the syntax of that position,
    otherwise nil.  That construct can be a two character comment
    delimiter or an Escaped or Char-quoted character.
11..... Possible further internal information used by ‘parse-partial-sexp’.

Grepping for syntax-ppss / parse-partial-sexp under the lisp directory of the emacs source turns up a fair number of hits.

I think the function may be part of low level machinery that is used in more than a few places.

But perhaps there is someone else who can give a better answer :)

sogaiu commented 1 year ago

FWIW, I also made similar changes to janet-ts-mode.el and I verified that a number of *-ts-mode.el files in the emacs source tree have syntax-table-related bits.

Here is an example from emacs source on the emacs-29 branch.

dannyfreeman commented 1 year ago

Thanks for the insight @sogaiu, the typescript-ts-mode link led me down the right path. define-derived-mode can specify a :syntax-table. If not specified it uses this code to infer the syntax table var name https://github.com/emacs-mirror/emacs/blob/f2b2c752a5920c1152fd70d917e0fc5a3c9728c4/lisp/emacs-lisp/derived.el#L103C1-L105C56

So it will look for clojure-ts-mode-syntax-table based on the mode name clojure-ts-mode.

sogaiu commented 1 year ago

LOL, I totally misread your comment before. You made good use of an answer to a misunderstood question :)

Nice detective work!