[Top][All Lists]

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

Re: Unifying "foo-mode"s and "foo-ts-mode"s

From: Theodor Thornhill
Subject: Re: Unifying "foo-mode"s and "foo-ts-mode"s
Date: Fri, 30 Dec 2022 16:24:56 +0100

On 30 December 2022 16:02:37 CET, Philip Kaludercic <philipk@posteo.net> wrote:
>Theodor Thornhill <theo@thornhill.no> writes:
>> Philip Kaludercic <philipk@posteo.net> writes:
>>> Theodor Thornhill <theo@thornhill.no> writes:
>>>> Philip Kaludercic <philipk@posteo.net> writes:
>>>>> Eli Zaretskii <eliz@gnu.org> writes:
>>>>>> You can try.  I would like to start a full feature freeze in a day or
>>>>>> two, so I'm not sure you will have enough time.  And it isn't like we
>>>>>> didn't try various approaches during the past two months, so frankly I
>>>>>> don't think that a better way even exists.  But if you come up with
>>>>>> some very bright idea, who knows?
>>>>> I have attached a sketch of my proposal with support for Python.
>>>>> Instead of a separate python-ts-mode, we regulate tree-sitter support
>>>>> using a user option `treesit-enabled-modes'.  It can either be a list
>>>> [...]
>>>> IIUC this will make all other config run before the treesit-related
>>>> code?  
>>> If that is the problem, that we can solve that by re-adjusting the order
>>> in which the expanded code occurs. 
>>>>        In that case I think this cannot work, because we _don't_ want to
>>>> set all the before/after-change functions many modes set, for example.
>>> What exactly is the issue here?  Can't we overwrite it again if
>>> necessary?
>> For example the CC modes set up lots of functions in the mode init, many
>> of which override things like '*-function' variables, that if either not
>> overriden explicitly by a treesit alternative or removed before mode
>> init will impact performance.  There are some modes that will be worse
>> in this regard than others, but one of my earlier suggestions was to
>> just:
>> (define-derived-mode foo ........
>>   (cond
>>     (use-treesit-p
>>      (init-all-the-treesit-stuff))
>>     (use-hypothetical-future-thing
>>      (init-all-the-hypothetical-future-stuff))
>>     (t
>>      (init-all-the-other-stuff))))
>This also looks good.
>> In this case we don't let any code bleed in between the modes, which IMO
>> is necessary.  At least we should be very careful with _when_ it is ok
>> for such settings to bleed in.  Things like comment-start/end etc can
>> bleed in just fine, but stuff like
>> ```
>>   (c-init-language-vars js-mode)
>>   (setq-local indent-line-function #'js-indent-line)
>>   (setq-local beginning-of-defun-function #'js-beginning-of-defun)
>>   (setq-local end-of-defun-function #'js-end-of-defun)
>>   (setq-local open-paren-in-column-0-is-defun-start nil)
>>   (setq-local font-lock-defaults
>>               (list js--font-lock-keywords nil nil nil nil
>>                     '(font-lock-syntactic-face-function
>>                       . js-font-lock-syntactic-face-function)))
>>   (setq-local syntax-propertize-function #'js-syntax-propertize)
>>   (add-hook 'syntax-propertize-extend-region-functions
>>             #'syntax-propertize-multiline 'append 'local)
>>   (add-hook 'syntax-propertize-extend-region-functions
>>             #'js--syntax-propertize-extend-region 'append 'local)
>>   (setq-local prettify-symbols-alist js--prettify-symbols-alist)
>>   (setq-local parse-sexp-ignore-comments t)
>>   (setq-local which-func-imenu-joiner-function #'js--which-func-joiner)
>> ```
>> Should absolutely not.
>> Does that make sense?  I don't think this is impossible, but my biggest
>> argument was that we need to keep things distinct, or at least be very
>> explicit on when we share code.
>Yes, I do understand this point, yet my impression has been that this
>was not always necessary.  The relative complexity of cc-mode might
>necessitate a separate mode, but I don't see why that should be the rule
>instead of an exception?

IIRC it was mostly because we wanted to start creating things instead of 
bikeshedding over these details. 

My thought process was to create separate modes now, and make a facility to map 
a language to a mode implementation. For example, imo it doesn't make sense for 
"the first" implementation to own a language's namespace. c-mode should be able 
to leverage cc-mode _or_ c-ts-mode, rather than the other way around.

At least during these months that seemed smart, because we have many 
contributions now due to the simple nature of creating a foo-ts-mode. 

Surgically injecting tree sitter into existing modes is prone to error, and 
requires quite deep knowledge of each existing mode's inner working.

So I'd just hold off and maybe create a nice facility for Emacs 30.

Something like

(setq major-mode-backend
  '((c . cc-mode)
    (c++ . treesit)))

Then M-x c-mode would trigger cc, and c++-mode would trigger c++-ts-mode.

And we keep the old implementations as the default until we know tree-sitter, 
has no disadvantages and swap the default. No need to deprecate anything or 
require config changes, imo.


reply via email to

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