Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce custom-face-1/custom-face-2 facility #3646

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Introduce custom-face-1/custom-face-2 facility #3646

wants to merge 3 commits into from

Conversation

vemv
Copy link
Member

@vemv vemv commented Apr 19, 2024

Context

DSLs and libraries with special semantics aren't uncommon in the Clojure world.

Users of those may want some extra highlighting rules, with different faces, that apply to just those DSLs.

Those extra faces allow to:

  • distinguish "normal" Clojure from DSL code
    • note that both can be interleaved
  • make that DSL simply nicer to read in itself

CIDER by default gives a relatively small palette of faces to be possibly applied, so stuff either won't get any particular font-locking, or the applied font-locking will overlap with Clojure font-locking (e.g. N different things all use font-lock-variable-name-face), hindering the desired distinction.

Changes

Introduce two new faces and two customizable 'categorizers' that when set, decide whether a given symbol should use one of the custom faces.

Example

The user would simply use something like:

(setq cider-custom-symbol-categorizer-1 (lambda (sym meta)
                                          (member (nrepl-dict-get meta "ns")
                                                  '("com.rpl.ramaspecter"))))

(setq cider-custom-symbol-categorizer-2 (lambda (sym meta)
                                          (member sym
                                                  '("<<sources"
                                                    "<<if"
                                                    "<<subsource"
                                                    "<<cond"
                                                    "<<ramaop"
                                                    "<<ramafn"
                                                    "or>"
                                                    "and>"
                                                    "else>"
                                                    "case>"
                                                    "<<shadowif"))))

And then one's theme can be customized to use the produced faces:

(custom-theme-set-faces
 'my-theme
 `(cider-custom-face-1 ((t (:foreground "blue"))))
 `(cider-custom-face-2 ((t (:foreground "red")))))

Status

Generally ready and functional, except for the addition of a user manual + changelog entry.

I also plan to provide a little more metadata from cider-nrepl (in an efficient manner).

Tweaks welcome.

Cheers - V

@bbatsov
Copy link
Member

bbatsov commented Apr 20, 2024

I'll need some specific use-cases to be able to evaluate the usefulness of this proposal as DSLs come in many flavors and I don't see immediately how a couple of extra faces will make a big difference for them.

Might also be useful to have this as some generic mechanism - e.g. some macro that will define a matching face, instead of hardcoding some faces. Admittedly this will make theming a more manual process, but I doubt that will be a big deal for most people.

@vemv
Copy link
Member Author

vemv commented Apr 20, 2024

As for examples:

  • Rama has a dataflow DSL - it's code that is embedded into normal Clojure which however runs in a distributed fashion.
    • So, the highlighting makes it easier to see what is being run as normal code, and what is being distributed.
  • Electric has functions that run on the client, and that run in the server, interspersed
  • Specter has a navigator DSL which users might want to highlight distinctively
    • e.g. the all-caps part in (transform [MAP-VALS ALL MAP-VALS even?] inc data)
    • this is not unlike highlighting for SQL - distinguishing a query part from a code part makes things more comprehensible, to some.

Might also be useful to have this as some generic mechanism - e.g. some macro that will define a matching face, instead of hardcoding some faces. Admittedly this will make theming a more manual process, but I doubt that will be a big deal for most people.

I could use some pseudo-code to fully grasp the idea.

@bbatsov
Copy link
Member

bbatsov commented Apr 21, 2024

Something like:

(cider-define-font-locking-category 'category-name 
                                          (lambda (sym meta)
                                          (member (nrepl-dict-get meta "ns")
                                                  '("com.rpl.ramaspecter"))))

And this would create some face based on category-name. Or we can specify the face explicitly. Probably this should also take some face specification. And that's what I said that theming becomes a bit tricky - you'd need to have face overrides only after some faces have been created, but that's not that big of deal IMO.

@vemv
Copy link
Member Author

vemv commented Apr 21, 2024

Can give that a shot - would seem nice as I wasn't sure of how many 'slots' we should offer.

I take it that we'd go ahead with that?

@bbatsov
Copy link
Member

bbatsov commented Apr 21, 2024

Yeah, if it's flexible I'm OK with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants