* Calling another major mode in a major mode body @ 2022-11-21 22:07 Yuan Fu 2022-11-22 0:44 ` Phil Sainty 0 siblings, 1 reply; 13+ messages in thread From: Yuan Fu @ 2022-11-21 22:07 UTC (permalink / raw) To: emacs-devel Sometimes it would be nice for the tree-sitter mode to fallback to the non-tree-sitter mode, eg, when the buffer is to large. Sh-mode needs something similar, too, because tree-sitter only supports bash right now. If the shell is some other shell, the tree-sitter mode should fall back to the normal sh-mode. Fallback in the above two cases are necessary because users can’t easily avoid them: currently there is no easy way to make Emacs use different major modes based on file size, or shell type. (You could use magic-mode-alist for shell, but that’s not TRT, I think) So I wonder if it’s ok to fall back to another major mode by simply calling that mode. Yuan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-21 22:07 Calling another major mode in a major mode body Yuan Fu @ 2022-11-22 0:44 ` Phil Sainty 2022-11-23 2:03 ` Yuan Fu 0 siblings, 1 reply; 13+ messages in thread From: Phil Sainty @ 2022-11-22 0:44 UTC (permalink / raw) To: Yuan Fu; +Cc: emacs-devel On 2022-11-22 11:07, Yuan Fu wrote: > So I wonder if it’s ok to fall back to another major mode by simply > calling that mode. I think the following describes what that would do. Quoting myself from https://stackoverflow.com/a/19295380 (and as a tangent I'd be happy for some adaptation of that to live somewhere in the elisp manual, as I think it was a decent explanation of the processes), when we call `child-mode', the full sequence is: (run-hooks 'change-major-mode-hook) ;; actually the first thing done by (kill-all-local-variables) ;; <-- this function ,@grandparent-body ,@parent-body ,@child-body (run-hooks 'change-major-mode-after-body-hook) (run-hooks 'grandparent-mode-hook) (run-hooks 'parent-mode-hook) (run-hooks 'child-mode-hook) (run-hooks 'after-change-major-mode-hook) ;; plus the following final step, since: ;; commit 2eb6817ba971184cc109f8530f4b3b38f65650ea ;; Add :after-hook facility to define-derived-mode. (run-hooks delayed-after-hook-functions) `delay-mode-hooks' is still in effect until child-body has returned, so I believe calling (fallback-mode) within child-body would result in this sequence: (run-hooks 'change-major-mode-hook) ;; actually the first thing done by (kill-all-local-variables) ;; <-- this function ,@grandparent-body ,@parent-body ,@child-body + (run-hooks 'change-major-mode-hook) ;; actually the first thing done by + (kill-all-local-variables) ;; <-- this function + ,@fallback-parent-mode-body + ,@fallback-mode-body ;; The child-mode binding for `delay-mode-hooks' is now out of scope, ;; so `run-mode-hooks' finally acts... (run-hooks 'change-major-mode-after-body-hook) (run-hooks 'grandparent-mode-hook) (run-hooks 'parent-mode-hook) (run-hooks 'child-mode-hook) + (run-hooks 'fallback-parent-mode-hook) + (run-hooks 'fallback-mode-hook) (run-hooks 'after-change-major-mode-hook) (run-hooks delayed-after-hook-functions) It looks like things pushed onto `delayed-after-hook-functions' would happen in this sequence, though: - grandparent-mode - parent-mode - fallback-parent-mode - fallback-mode - child-mode Although `delayed-after-hook-functions' does not seem to be permanent-local, so in fact it might be this? - fallback-parent-mode - fallback-mode - child-mode There's also this, which doesn't seem entirely appropriate, but... ** New functions 'major-mode-suspend' and 'major-mode-restore' Used when switching temporarily to another major mode, e.g. for hexl-mode, or to switch between c-mode and image-mode in XPM. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-22 0:44 ` Phil Sainty @ 2022-11-23 2:03 ` Yuan Fu 2022-11-23 2:15 ` Yuan Fu 2022-11-23 2:46 ` Stefan Monnier 0 siblings, 2 replies; 13+ messages in thread From: Yuan Fu @ 2022-11-23 2:03 UTC (permalink / raw) To: Phil Sainty; +Cc: emacs-devel > On Nov 21, 2022, at 4:44 PM, Phil Sainty <psainty@orcon.net.nz> wrote: > > On 2022-11-22 11:07, Yuan Fu wrote: >> So I wonder if it’s ok to fall back to another major mode by simply >> calling that mode. > > I think the following describes what that would do. > > > Quoting myself from https://stackoverflow.com/a/19295380 (and as a > tangent I'd be happy for some adaptation of that to live somewhere > in the elisp manual, as I think it was a decent explanation of the > processes), when we call `child-mode', the full sequence is: > > (run-hooks 'change-major-mode-hook) ;; actually the first thing done by > (kill-all-local-variables) ;; <-- this function > ,@grandparent-body > ,@parent-body > ,@child-body > (run-hooks 'change-major-mode-after-body-hook) > (run-hooks 'grandparent-mode-hook) > (run-hooks 'parent-mode-hook) > (run-hooks 'child-mode-hook) > (run-hooks 'after-change-major-mode-hook) > ;; plus the following final step, since: > ;; commit 2eb6817ba971184cc109f8530f4b3b38f65650ea > ;; Add :after-hook facility to define-derived-mode. > (run-hooks delayed-after-hook-functions) > > > `delay-mode-hooks' is still in effect until child-body has returned, > so I believe calling (fallback-mode) within child-body would result > in this sequence: > > > (run-hooks 'change-major-mode-hook) ;; actually the first thing done by > (kill-all-local-variables) ;; <-- this function > ,@grandparent-body > ,@parent-body > ,@child-body > + (run-hooks 'change-major-mode-hook) ;; actually the first thing done by > + (kill-all-local-variables) ;; <-- this function > + ,@fallback-parent-mode-body > + ,@fallback-mode-body > ;; The child-mode binding for `delay-mode-hooks' is now out of scope, > ;; so `run-mode-hooks' finally acts... > (run-hooks 'change-major-mode-after-body-hook) > (run-hooks 'grandparent-mode-hook) > (run-hooks 'parent-mode-hook) > (run-hooks 'child-mode-hook) > + (run-hooks 'fallback-parent-mode-hook) > + (run-hooks 'fallback-mode-hook) > (run-hooks 'after-change-major-mode-hook) > (run-hooks delayed-after-hook-functions) > > > It looks like things pushed onto `delayed-after-hook-functions' > would happen in this sequence, though: > > - grandparent-mode > - parent-mode > - fallback-parent-mode > - fallback-mode > - child-mode > > Although `delayed-after-hook-functions' does not seem to be > permanent-local, so in fact it might be this? > > - fallback-parent-mode > - fallback-mode > - child-mode Thanks for that detailed explanation :-) It seems the current mode’s after-hook is ran the very last. So it might be a good place to call the fallback major mode. The call to run-hooks in a major mode invocation command is outside the scope delay-mode-hooks, so simply calling the fallback major mode should be fine? IMO, the sequence would be - parent-mode - child-mode - parent-hook - child-hook - parent-after-hook - child-after-hook: calls fallback-mode - fallback-parent ... Yuan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-23 2:03 ` Yuan Fu @ 2022-11-23 2:15 ` Yuan Fu 2022-11-23 2:46 ` Stefan Monnier 1 sibling, 0 replies; 13+ messages in thread From: Yuan Fu @ 2022-11-23 2:15 UTC (permalink / raw) To: Phil Sainty; +Cc: emacs-devel, Stefan Monnier > On Nov 22, 2022, at 6:03 PM, Yuan Fu <casouri@gmail.com> wrote: > > > >> On Nov 21, 2022, at 4:44 PM, Phil Sainty <psainty@orcon.net.nz> wrote: >> >> On 2022-11-22 11:07, Yuan Fu wrote: >>> So I wonder if it’s ok to fall back to another major mode by simply >>> calling that mode. >> >> I think the following describes what that would do. >> >> >> Quoting myself from https://stackoverflow.com/a/19295380 (and as a >> tangent I'd be happy for some adaptation of that to live somewhere >> in the elisp manual, as I think it was a decent explanation of the >> processes), when we call `child-mode', the full sequence is: >> >> (run-hooks 'change-major-mode-hook) ;; actually the first thing done by >> (kill-all-local-variables) ;; <-- this function >> ,@grandparent-body >> ,@parent-body >> ,@child-body >> (run-hooks 'change-major-mode-after-body-hook) >> (run-hooks 'grandparent-mode-hook) >> (run-hooks 'parent-mode-hook) >> (run-hooks 'child-mode-hook) >> (run-hooks 'after-change-major-mode-hook) >> ;; plus the following final step, since: >> ;; commit 2eb6817ba971184cc109f8530f4b3b38f65650ea >> ;; Add :after-hook facility to define-derived-mode. >> (run-hooks delayed-after-hook-functions) >> >> >> `delay-mode-hooks' is still in effect until child-body has returned, >> so I believe calling (fallback-mode) within child-body would result >> in this sequence: >> >> >> (run-hooks 'change-major-mode-hook) ;; actually the first thing done by >> (kill-all-local-variables) ;; <-- this function >> ,@grandparent-body >> ,@parent-body >> ,@child-body >> + (run-hooks 'change-major-mode-hook) ;; actually the first thing done by >> + (kill-all-local-variables) ;; <-- this function >> + ,@fallback-parent-mode-body >> + ,@fallback-mode-body >> ;; The child-mode binding for `delay-mode-hooks' is now out of scope, >> ;; so `run-mode-hooks' finally acts... >> (run-hooks 'change-major-mode-after-body-hook) >> (run-hooks 'grandparent-mode-hook) >> (run-hooks 'parent-mode-hook) >> (run-hooks 'child-mode-hook) >> + (run-hooks 'fallback-parent-mode-hook) >> + (run-hooks 'fallback-mode-hook) >> (run-hooks 'after-change-major-mode-hook) >> (run-hooks delayed-after-hook-functions) >> >> >> It looks like things pushed onto `delayed-after-hook-functions' >> would happen in this sequence, though: >> >> - grandparent-mode >> - parent-mode >> - fallback-parent-mode >> - fallback-mode >> - child-mode >> >> Although `delayed-after-hook-functions' does not seem to be >> permanent-local, so in fact it might be this? >> >> - fallback-parent-mode >> - fallback-mode >> - child-mode > > Thanks for that detailed explanation :-) > > It seems the current mode’s after-hook is ran the very last. So it might be a good place to call the fallback major mode. The call to run-hooks in a major mode invocation command is outside the scope delay-mode-hooks, so simply calling the fallback major mode should be fine? > > IMO, the sequence would be > - parent-mode > - child-mode > - parent-hook > - child-hook > - parent-after-hook > - child-after-hook: calls fallback-mode > - fallback-parent … Perhaps it’s more clear with a demonstration: We define three modes, A for parent, B for child, F for fallback. Both B and F inherits A. When we call B-mode, it automatically falls back to F-mode in its after-hook (define-derived-mode A-mode nil "A" "A mode." :after-hook (message "A after-hook") (message "A body")) (define-derived-mode B-mode A-mode "B" "B mode." :after-hook (progn (message "B after-hook") (F-mode)) (message "B body")) (define-derived-mode F-mode A-mode "F" "F mode." :after-hook (message "F after-hook") (message "F body")) (setq A-mode-hook (list (lambda () (message "A hook")))) (setq B-mode-hook (list (lambda () (message "B hook")))) (setq F-mode-hook (list (lambda () (message "F hook")))) M-x B-mode RET produces: A body B body A hook A after-hook B after-hook (here F-mode is called) A body F body A hook A after-hook F after-hook All in all, I don’t see any immediate harm of falling back to another mode like this. A’s body and hook run twice, but so does it when the user manually changes B-mode to F-mode. If we want to be extra safe, perhaps we can do (run-with-idle-timer 0 nil #'F-mode) in B-mode’s after-hook. Yuan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-23 2:03 ` Yuan Fu 2022-11-23 2:15 ` Yuan Fu @ 2022-11-23 2:46 ` Stefan Monnier 2022-11-23 18:36 ` Yuan Fu 1 sibling, 1 reply; 13+ messages in thread From: Stefan Monnier @ 2022-11-23 2:46 UTC (permalink / raw) To: Yuan Fu; +Cc: Phil Sainty, emacs-devel > Thanks for that detailed explanation :-) > > It seems the current mode’s after-hook is ran the very last. So it might be > a good place to call the fallback major mode. The call to run-hooks in > a major mode invocation command is outside the scope delay-mode-hooks, so > simply calling the fallback major mode should be fine? I think even cleaner is if the dispatch can happen before we even call `kill-all-local-variables`. That's what `tex-mode` does (tho it gets there in a roundabout way because I didn't want to change `define-derived-mode`). Stefan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-23 2:46 ` Stefan Monnier @ 2022-11-23 18:36 ` Yuan Fu 2022-11-23 19:21 ` Stefan Monnier 0 siblings, 1 reply; 13+ messages in thread From: Yuan Fu @ 2022-11-23 18:36 UTC (permalink / raw) To: Stefan Monnier; +Cc: Phil Sainty, emacs-devel > On Nov 22, 2022, at 6:46 PM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: > >> Thanks for that detailed explanation :-) >> >> It seems the current mode’s after-hook is ran the very last. So it might be >> a good place to call the fallback major mode. The call to run-hooks in >> a major mode invocation command is outside the scope delay-mode-hooks, so >> simply calling the fallback major mode should be fine? > > I think even cleaner is if the dispatch can happen before we even call > `kill-all-local-variables`. > > That's what `tex-mode` does (tho it gets there in a roundabout way > because I didn't want to change `define-derived-mode`). > > > Stefan > Yes, it’s much cleaner. If we don’t care too much about using advice in our source. I’ll do that instead. Yuan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-23 18:36 ` Yuan Fu @ 2022-11-23 19:21 ` Stefan Monnier 2022-12-04 7:54 ` Yuan Fu 0 siblings, 1 reply; 13+ messages in thread From: Stefan Monnier @ 2022-11-23 19:21 UTC (permalink / raw) To: Yuan Fu; +Cc: Phil Sainty, emacs-devel > Yes, it’s much cleaner. If we don’t care too much about using advice in our > source. I’ll do that instead. We really should change `define-derived-mode` to support this directly, tho. Stefan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-11-23 19:21 ` Stefan Monnier @ 2022-12-04 7:54 ` Yuan Fu 2022-12-05 22:37 ` Richard Stallman 0 siblings, 1 reply; 13+ messages in thread From: Yuan Fu @ 2022-12-04 7:54 UTC (permalink / raw) To: Stefan Monnier; +Cc: Phil Sainty, emacs-devel > On Nov 23, 2022, at 11:21 AM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: > >> Yes, it’s much cleaner. If we don’t care too much about using advice in our >> source. I’ll do that instead. > > We really should change `define-derived-mode` to support this > directly, tho. > > > Stefan > Yeah, in Emacs 30, probably :-) I used the advice technique/hack similar to tex-mode for bash-ts-mode. Yuan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-12-04 7:54 ` Yuan Fu @ 2022-12-05 22:37 ` Richard Stallman 2022-12-05 22:50 ` Stefan Monnier 0 siblings, 1 reply; 13+ messages in thread From: Richard Stallman @ 2022-12-05 22:37 UTC (permalink / raw) To: Yuan Fu; +Cc: monnier, psainty, emacs-devel [[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > Yeah, in Emacs 30, probably :-) I used the advice technique/hack similar to tex-mode for bash-ts-mode. Plsee fix that. To make one part of Emacs put advice on another part is asking for future development trouble. The worst thing is that the trouble is likely to happen to some other developer. When your code puts advice on a function BAR, that means other code that calls BAR will get behavior different from what the source code of BAR says. Someone else will debug a program that calls BAR and tear per hair out trying to figure out why it does not do what ALL the source code says it should do. Please don't install code that advises other code. If you've already done that, please fix it now. Don't add it to the backlog of pitfalls waiting to be fixed. -- Dr Richard Stallman (https://stallman.org) Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-12-05 22:37 ` Richard Stallman @ 2022-12-05 22:50 ` Stefan Monnier 2022-12-08 23:07 ` Richard Stallman 0 siblings, 1 reply; 13+ messages in thread From: Stefan Monnier @ 2022-12-05 22:50 UTC (permalink / raw) To: Richard Stallman; +Cc: Yuan Fu, psainty, emacs-devel > > Yeah, in Emacs 30, probably :-) I used the advice technique/hack similar > > to tex-mode for bash-ts-mode. > Plsee fix that. To make one part of Emacs put advice on another part > is asking for future development trouble. Note that the above two uses of advice don't advise *other* code but advise their own code instead :-) Stef ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-12-05 22:50 ` Stefan Monnier @ 2022-12-08 23:07 ` Richard Stallman 2022-12-09 12:56 ` Stefan Monnier 0 siblings, 1 reply; 13+ messages in thread From: Richard Stallman @ 2022-12-08 23:07 UTC (permalink / raw) To: Stefan Monnier; +Cc: casouri, psainty, emacs-devel [[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > Note that the above two uses of advice don't advise *other* code but > advise their own code instead :-) That is less of a problem, I agree. But still, why not use a flag or a hook? -- Dr Richard Stallman (https://stallman.org) Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-12-08 23:07 ` Richard Stallman @ 2022-12-09 12:56 ` Stefan Monnier 2022-12-10 22:05 ` Richard Stallman 0 siblings, 1 reply; 13+ messages in thread From: Stefan Monnier @ 2022-12-09 12:56 UTC (permalink / raw) To: Richard Stallman; +Cc: casouri, psainty, emacs-devel > > Note that the above two uses of advice don't advise *other* code but > > advise their own code instead :-) > That is less of a problem, I agree. But still, why not use a flag > or a hook? Look at the code and you'll see :-) Stefan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Calling another major mode in a major mode body 2022-12-09 12:56 ` Stefan Monnier @ 2022-12-10 22:05 ` Richard Stallman 0 siblings, 0 replies; 13+ messages in thread From: Richard Stallman @ 2022-12-10 22:05 UTC (permalink / raw) To: Stefan Monnier; +Cc: casouri, psainty, emacs-devel [[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > > > Note that the above two uses of advice don't advise *other* code but > > > advise their own code instead :-) > > That is less of a problem, I agree. But still, why not use a flag > > or a hook? > Look at the code and you'll see :-) 1. Is it in master? If I pull in the latest master, will this be included? 2. Can you tell me which file it is in? -- Dr Richard Stallman (https://stallman.org) Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org) ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2022-12-10 22:05 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-11-21 22:07 Calling another major mode in a major mode body Yuan Fu 2022-11-22 0:44 ` Phil Sainty 2022-11-23 2:03 ` Yuan Fu 2022-11-23 2:15 ` Yuan Fu 2022-11-23 2:46 ` Stefan Monnier 2022-11-23 18:36 ` Yuan Fu 2022-11-23 19:21 ` Stefan Monnier 2022-12-04 7:54 ` Yuan Fu 2022-12-05 22:37 ` Richard Stallman 2022-12-05 22:50 ` Stefan Monnier 2022-12-08 23:07 ` Richard Stallman 2022-12-09 12:56 ` Stefan Monnier 2022-12-10 22:05 ` Richard Stallman
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).