From: Dmitry Gutov <dmitry@gutov.dev>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: 68246@debbugs.gnu.org, "Eli Zaretskii" <eliz@gnu.org>,
casouri@gmail.com, "João Távora" <joaotavora@gmail.com>,
"Stefan Kangas" <stefankangas@gmail.com>
Subject: bug#68246: 30.0.50; Add non-TS mode as extra parent of TS modes
Date: Thu, 18 Jan 2024 07:05:55 +0200 [thread overview]
Message-ID: <8e6935bc-2a60-4a14-8e63-d6057a7e2af7@gutov.dev> (raw)
In-Reply-To: <jwvzfx329v2.fsf-monnier+emacs@gnu.org>
On 17/01/2024 19:08, Stefan Monnier wrote:
>> @@ -3150,6 +3150,9 @@ auto-mode-alist
>> Visiting a file whose name matches REGEXP specifies FUNCTION as the
>> mode function to use. FUNCTION will be called, unless it is nil.
>>
>> +FUNCTION can also be a keyword denoting a language, to be looked
>> +up in `major-mode-remap-alist'.
>
> Side note: the intention is OK but `major-mode-remap-alist' is
> a defcustom and should remain nil by default. It's there for the users
> to express which major modes they prefer. So if we want a mapping
> between some new language/type concept and major modes, it should be
> stored elsewhere (could be a plain alist that's handled as a kind of
> "implicit tail of `major-mode-remap-alist`").
Good point. The user can customize it and lose the non-default modes
configured for a language.
The way I introduced languages as keywords was an experiment, really.
Mostly to save on typing - because the first plan was to have a parallel
set of alists (since we can't right away deprecate the file -> mmode
mappings right away). The language-specific version of
major-mode-remap-alist looks necessary after all.
>> @@ -3206,10 +3209,10 @@ interpreter-mode-alist
>> ("emacs" . emacs-lisp-mode)))
>> "Alist mapping interpreter names to major modes.
>> This is used for files whose first lines match `auto-mode-interpreter-regexp'.
>> -Each element looks like (REGEXP . MODE).
>> +Each element looks like (REGEXP . MODE-OR-LANGUAGE).
>> If REGEXP matches the entire name (minus any directory part) of
>> the interpreter specified in the first line of a script, enable
>> -major mode MODE.
>> +MODE-OR-LANGUAGE.
>
> There's a similar need for "content type" rather than "language". If we
> want to mention "language" we should also take the opportunity to
> mention other related categorizations like "content type".
Are "content type" and "language" going to be different things? They
seem the same to me.
>> - (funcall (alist-get mode major-mode-remap-alist mode))
>> + ;; XXX: When there's no mapping for `:<language>', we could also
>> + ;; look for a function called `<language>-mode'.
>> + (funcall (alist-get mode major-mode-remap-alist (if (keywordp mode)
>> + #'fundamental-mode
>> + mode)))
>> + (when (keywordp mode) ;Perhaps do that unconditionally.
>> + (run-hooks (intern (format "%s-language-hook" (buffer-language)))))
>
> That seems wrong:
> - Why should this hook run when `auto-mode-alist` says `:js` but not
> when doing `M-x javascript-mode` (or other ways to enable this mode)?
> - Why run this hook *after* the mode's `:after-hook` and after
> things like `after-change-major-mode-hook`?
>
> I think it should remain the major mode's responsibility to decide which
> hooks it runs.
On one hand, this is an artefact of not implementing the
language-classification inside define-derived-mode.
OTOH, the major mode can only run the language hook, I think, if any
major mode can correspond only to one language. Though I suppose if
set-auto-mode-0 saves the currently "detected" language somewhere, the
major mode definitions could pick it up and call the corresponding hook.
Hmm, perhaps in that case the major modes won't need any special
attribute in their definitions (to specify their language): any major
mode would run <lang>-language-hook where <lang> is the language
detected for the buffer or assigned explicitly.
>> +(defun buffer-language ()
>> + "Return the language of the current buffer.
>> +A language is a lowercase keyword with the name of the language."
>> + ;; Alternatively, we could go through all the matchers in
>> + ;; auto-mode-alist, interpreter-mode-alist,
>> + ;; magic-fallback-mode-alist here, possibly using a cache keyed on
>> + ;; buffer-file-name. But that's probably an overkill: if the user
>> + ;; changes the settings, they can call `M-x revert-buffer' at the end.
>> + (if (keywordp (car set-auto-mode--last))
>> + (car set-auto-mode--last)
>> + ;; Backward compatibility.
>> + (intern (format ":%s" (replace-regexp-in-string "\\(?:-ts\\)?-mode\\'" ""
>> + (symbol-name major-mode))))))
>
> I'm not comfortable enshrining the "-ts-mode" convention here.
We can still go the "strict" approach, where when no language is
assigned, we don't try to guess it.
> Also I think if we want a `buffer-language` function, it should not rely
> on how the mode was installed (e.g. `set-auto-mode--last`) but only on
> the major mode itself, i.e. something like
>
> (defun buffer-language ()
> (or buffer-language
Where would the buffer-language variable be set, if not inside
set-auto-mode-*?
> (some heuristic based on major-mode and/or derived-modes)))
If we're sure we don't want several languages to be able to refer to the
same major mode...
> [ Of course, I already mentioned that I also suspect that there can/will
> be sometimes several languages (or none). ]
I'm not clear on this. You mentioned complex cases - like an xml inside
an archive? But depending on the usage, only one of the languages might
be "active" at a given time. Or a combination of languages would simply
be another language, basically.
A more specific scenario might clarify this better.
>> +(defun set-buffer-language (language)
>> + "Set the language of the current buffer.
>> +And switch the major mode appropriately."
>> + (interactive
>> + (list (let* ((ct (mapcan
>> + (lambda (pair) (and (keywordp (car pair))
>> + (list (symbol-name (car pair)))))
>> + major-mode-remap-alist))
>> + (lang (completing-read "Language: " ct)))
>> + (and lang (intern lang)))))
>> + (set-auto-mode-0 language))
>
> I see several issues with this function (name and implementation), but
> I wonder when we'd ever need such a thing.
It seemed like a missed opportunity not to provide a more high-level
command to switch to a specific language for the buffer. E.g. how we
sometimes use 'M-x foo-major-mode' when a file type's been misdetected,
or the buffer is non-file-visiting (perhaps very temporary).
A command which does this with exhaustive completion across the
configured languages seems handy. At least that's my impression from
briefly testing it out.
Also, get-current-mode-for-language can be implemented in terms of
set-buffer-language (see my earlier email to Joao).
>> ;;;###autoload
>> (dolist (name (list "node" "nodejs" "gjs" "rhino"))
>> - (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'js-mode)))
>> + (add-to-list 'interpreter-mode-alist (cons (purecopy name) :js)))
>
> BTW, my suggested patch basically proposes to use `<LANG>-mode` instead
> of `:LANG>` which saves us from those changes since that matches our
> historical conventions.
<LANG>-mode is lexically indistinguishable from <NONLANG>-mode. If we
used the names like <LANG>-lang, at least one could tell whether one of
the parents of a given <foo>-mode is a language.
> Another issue I see if we don't use something like
> `derived-mode-add-parents` is that all the various places where we use
> mode-indexing, such as `.dir-locals.el`, `ffap`, YASnippet, etc... will
> need to be extended with a way to use "languages" as well, and then we
> also need to define a sane precedence between settings that apply to
> a given mode and settings that apply to a given language (setting for
> `js-ts-mode` should presumably take precedence over settings for
> `:js` which should take precedence over settings for `prog-mode`).
That's a good point: if "languages" as a separate notion gets added, it
would make sense to use them in more places (not 100% necessary, but
good for consistency). With the associated complexity that you mention.
next prev parent reply other threads:[~2024-01-18 5:05 UTC|newest]
Thread overview: 146+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-04 22:11 bug#68246: 30.0.50; Add non-TS mode as extra parent of TS modes Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-04 23:02 ` João Távora
2024-01-04 23:05 ` Dmitry Gutov
2024-01-04 23:41 ` João Távora
2024-01-04 23:18 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-04 23:48 ` João Távora
2024-01-04 23:59 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-05 0:35 ` João Távora
2024-01-05 0:43 ` Yuan Fu
2024-01-05 7:51 ` Eli Zaretskii
2024-01-05 11:27 ` João Távora
2024-01-05 13:26 ` Eli Zaretskii
2024-01-05 15:16 ` João Távora
2024-01-05 15:34 ` Eli Zaretskii
2024-01-05 18:02 ` João Távora
2024-01-05 18:56 ` Eli Zaretskii
2024-01-05 23:20 ` João Távora
2024-01-05 23:51 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-06 0:16 ` João Távora
2024-01-06 4:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-06 14:36 ` João Távora
2024-01-06 15:50 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-06 22:22 ` João Távora
2024-01-07 6:55 ` Eli Zaretskii
2024-01-08 0:12 ` João Távora
2024-01-08 3:34 ` Eli Zaretskii
2024-01-08 10:50 ` João Távora
2024-01-08 13:13 ` Eli Zaretskii
2024-01-08 14:45 ` João Távora
2024-01-08 17:15 ` Eli Zaretskii
2024-01-14 2:19 ` Yuan Fu
2024-01-14 3:10 ` João Távora
2024-01-14 4:00 ` Yuan Fu
2024-01-14 7:02 ` Eli Zaretskii
2024-01-14 23:40 ` João Távora
2024-01-15 12:38 ` Eli Zaretskii
2024-01-15 14:45 ` João Távora
2024-01-15 15:00 ` Eli Zaretskii
2024-01-15 15:09 ` João Távora
2024-01-15 2:10 ` Dmitry Gutov
2024-01-15 12:46 ` Eli Zaretskii
2024-01-15 18:32 ` Dmitry Gutov
2024-01-15 18:52 ` Eli Zaretskii
2024-01-15 20:17 ` Dmitry Gutov
2024-01-15 20:27 ` Eli Zaretskii
2024-01-15 15:27 ` João Távora
2024-01-15 20:51 ` Dmitry Gutov
2024-01-15 23:11 ` João Távora
2024-01-16 2:09 ` Dmitry Gutov
2024-01-16 11:06 ` João Távora
2024-01-17 2:41 ` Dmitry Gutov
2024-01-17 10:20 ` João Távora
2024-01-18 0:47 ` Dmitry Gutov
2024-01-17 17:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-18 5:05 ` Dmitry Gutov [this message]
2024-01-18 14:17 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-18 19:55 ` Dmitry Gutov
2024-01-18 21:24 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-19 1:28 ` Dmitry Gutov
2024-01-19 12:43 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-19 12:53 ` João Távora
2024-01-19 13:19 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-19 14:01 ` João Távora
2024-01-19 18:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-19 22:47 ` João Távora
2024-01-20 7:03 ` Eli Zaretskii
2024-01-20 10:16 ` João Távora
2024-01-21 0:32 ` Yuan Fu
2024-01-21 9:54 ` Eli Zaretskii
2024-01-24 6:20 ` Yuan Fu
[not found] ` <jwvfrxt5e75.fsf-monnier+emacs@gnu.org>
[not found] ` <86v86ovp6j.fsf@gnu.org>
2024-03-09 15:39 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-20 5:43 ` Dmitry Gutov
2024-01-14 6:33 ` Eli Zaretskii
2024-01-14 23:18 ` João Távora
2024-01-15 12:35 ` Eli Zaretskii
2024-01-15 14:49 ` João Távora
2024-01-08 4:11 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-08 11:11 ` João Távora
2024-01-08 12:45 ` Eli Zaretskii
2024-01-08 18:57 ` Dmitry Gutov
2024-01-08 19:55 ` Eli Zaretskii
2024-01-08 20:06 ` Dmitry Gutov
2024-01-08 22:12 ` João Távora
2024-01-09 3:28 ` Eli Zaretskii
2024-01-08 19:18 ` Stefan Kangas
2024-01-08 19:57 ` Eli Zaretskii
2024-01-08 20:05 ` Dmitry Gutov
2024-01-09 3:27 ` Eli Zaretskii
2024-01-16 2:32 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-16 23:29 ` João Távora
2024-01-17 0:02 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-17 0:49 ` João Távora
2024-01-17 3:45 ` Dmitry Gutov
2024-01-19 5:12 ` Yuan Fu
2024-01-20 5:47 ` Dmitry Gutov
2024-01-20 7:46 ` Eli Zaretskii
2024-01-21 0:32 ` Dmitry Gutov
2024-01-08 19:04 ` Dmitry Gutov
2024-01-09 0:10 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-09 0:39 ` João Távora
2024-01-09 0:52 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-09 1:05 ` João Távora
2024-01-09 1:04 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-09 1:11 ` João Távora
2024-01-09 3:49 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-09 10:52 ` João Távora
2024-01-10 1:18 ` Dmitry Gutov
2024-01-10 16:11 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-11 3:41 ` Dmitry Gutov
2024-01-09 4:49 ` Stefan Kangas
2024-01-09 7:24 ` Kévin Le Gouguec
2024-01-09 1:09 ` Dmitry Gutov
2024-01-09 1:31 ` João Távora
2024-01-09 3:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-09 11:05 ` João Távora
2024-01-10 1:15 ` Dmitry Gutov
2024-01-10 1:59 ` João Távora
2024-01-10 16:04 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-10 17:02 ` Dmitry Gutov
2024-01-10 17:31 ` João Távora
2024-01-10 1:41 ` Dmitry Gutov
2024-01-10 6:24 ` Stefan Kangas
2024-01-10 15:51 ` João Távora
2024-01-11 3:49 ` Dmitry Gutov
2024-01-16 2:35 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-16 10:34 ` João Távora
2024-01-16 17:45 ` Dmitry Gutov
2024-01-16 22:00 ` João Távora
2024-01-17 2:05 ` Dmitry Gutov
2024-01-17 10:31 ` João Távora
2024-01-17 23:37 ` Dmitry Gutov
2024-01-06 8:12 ` Eli Zaretskii
2024-01-06 8:07 ` Eli Zaretskii
2024-01-06 13:52 ` João Távora
2024-01-05 19:03 ` Stefan Kangas
2024-01-05 23:37 ` João Távora
2024-01-06 8:09 ` Eli Zaretskii
2024-01-06 3:19 ` Yuan Fu
2024-01-06 3:36 ` Dmitry Gutov
2024-01-06 4:16 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-07 6:59 ` Yuan Fu
2024-01-06 14:54 ` João Távora
2024-01-08 18:16 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-05 7:40 ` Eli Zaretskii
2024-01-05 18:43 ` Stefan Kangas
2024-01-05 19:11 ` Stefan Kangas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8e6935bc-2a60-4a14-8e63-d6057a7e2af7@gutov.dev \
--to=dmitry@gutov.dev \
--cc=68246@debbugs.gnu.org \
--cc=casouri@gmail.com \
--cc=eliz@gnu.org \
--cc=joaotavora@gmail.com \
--cc=monnier@iro.umontreal.ca \
--cc=stefankangas@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).