emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Average-user-facing interface for tree-sitter


From: Jostein Kjønigsen
Subject: Re: Average-user-facing interface for tree-sitter
Date: Thu, 13 Oct 2022 16:32:37 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.2.2


Yuan Fu <casouri@gmail.com> writes:

From the suggestions I collected from the old thread, here is my proposal:

We define a custom option treesit-settings (we can discuss the name
later), which controls whether to enable/disable tree-sitter for each
major mode, and the default preference, like this:

(defcustom treesit-settings '((t nil nil))
  "Tree-sitter toggles for major modes.
Hm...  well, there's also modes that are "pure treesit", and there are
(or will be) alternate modes with and without tree-sitter.

I think users basically fall into two camps: The ones that want to have
tree-sitter in all modes, and ones that want to enable it in specific
modes (and ones that don't want it at all).  (Note Computer
Science-mandated off-by-one error.)

This suggests to me that we should just use the normal minor mode
machinery that we have for these things.

That is, people that want treesit in python-mode will say:

(add-hook 'python-mode 'treesit-mode)

And people that want it everywhere will say:

(global-treesit-mode)

This mode will, in addition to switching `treesit-mode' on everywhere,
also set up `major-mode-remap-alist', so that `typescript-mode' is
mapped to `ts-mode', and `c-mode' is mapped to `treesit-c-mode' (which
I'm sure somebody is going to write in a couple of days), etc.


Hey there.

I'd like to come up with a somewhat contrarian point of view, if nothing else to provide a point of reference.

Right now we have a single (that is: one, 1) implementation for c-mode and c++-mode. They are based on cc-mode.

There's no c-mode where you enable usage of cc-mode through a minor-mode, nor is there a global-cc-mode toggle. And there's a really simple reason for that. That's because c-mode is implemented using cc-mode as a foundation, and there's no other implementations.

Now if we are starting to implement some new major-modes using treesitter as a foundation (for instance ts-mode or c#-mode), such a toggle for tree-sitter-mode will be equally pointless. There is no ts-mode without treesitter. And what should we do if people activate ts-mode without these bespoke minor-modes being active at the same time? I think it's a bit fuzzy and doesn't really sound very .. well defined.

Existing users of typescript-mode can be guided to the new implementation through a variety of ways, but to me the flow of activating typescript-mode major-mode, then treesit-minor-mode, and then magically switching to ts-mode makes absolutely no sense. And the performance of that is probably terrible too.

For those users I think a simple deprecation warning which informs about the new built-in ts-mode should be more than sufficient, for the users to clean out the old (buggy) typescript.el from their conigs.

The one place where it gets slightly complicated is for major-modes where one decides to have two or more canonical implementations, that is to add a new treesitter backend alongside the existing elisp-one.

For an established built in-mode, like c-mode, switching over night is probable not feasable nor desirable. So in practice you will have a few modes where you might have multiple backends, ideally only in a transitional phase, but in worst case scenario permanently.

So how can we deal with that problem, where we have it, and not everywhere else?

I've had a similar "problem" for LSP backend for some programming languages. The solution I landed on there was to have a defcustom per language/major-mode where there were different LSP-backends which I may want to use.

Examples below:

- (defcustom csharp-lsp-backend) ;; 'lsp-mode 'omnisharp

- (defcustom typescript-lsp-backend) ;; 'lsp-mode 'tide

Then I in my major-mode hooks checked for which of the possible backends are chosen and dynamically dispatch based on that.

For major-modes ending up with multiple backends, I think this is an approach which scales better (supports more than 1 backend, but only 1 at a time!), and will perform better (because it means avoiding triggering code for more than one single backend when activated).

It will also better support the flow if we eventually end up with a single backend again which then becomes the default. In that case, we don't need to maintain empty/obsolete minor-modes just to avoid breaking people's major-mode hooks. Then they will just have a defcustom setting which will be ignored.

Personally I think that would work much better, and support the transitional period we may be entering, without causing lasting "cruft" in the code-base we rather would not have.

Just my 2 cents.

--
Jostein




reply via email to

[Prev in Thread] Current Thread [Next in Thread]