* bug#15577: 24.3; dir-local variables not applied when switching major-mode @ 2013-10-09 20:14 yary 2013-10-09 21:42 ` Glenn Morris [not found] ` <mailman.3789.1381430919.10748.bug-gnu-emacs@gnu.org> 0 siblings, 2 replies; 20+ messages in thread From: yary @ 2013-10-09 20:14 UTC (permalink / raw To: 15577 This bug report will be sent to the Bug-GNU-Emacs mailing list and the GNU bug tracker at debbugs.gnu.org. Please check that the From: line contains a valid email address. After a delay of up to one day, you should receive an acknowledgment at that address. Please write in English if possible, as the Emacs maintainers usually do not have translators for other languages. Please describe exactly what actions triggered the bug, and the precise symptoms of the bug. If you can, give a recipe starting from `emacs -Q': If I create a ".dir-locals.el" that applies to all major modes, such as: ((nil . ((tab-width . 3)))) It works when first opening any file under that directory- good. But, if I switch the buffer's major-mode, it loses the directory-local tab-width - and I've seen it lose other variables as well. An alternate case showing the same is to have a ".dir-locals.el" like: ((js-mode . ((tab-width . 3)))) and opening a non-JS file in the directory, such as an HTML file, and then switching to js-mode. Since I'm now editing the file in js-mode, I would want it to read the js-mode dir-local variables. Losing dir-locals seems like a bug to me, though perhaps there is a reason for it. I did notice from other dir-local-related bugs that they require some thought as to how to handle edge cases... In GNU Emacs 24.3.1 (i386-mingw-nt5.1.2600) of 2013-03-17 on MARVIN Windowing system distributor `Microsoft Corp.', version 5.1.2600 Configured using: `configure --with-gcc (4.7) --cflags -ID:/devel/emacs/libs/libXpm-3.5.8/include -ID:/devel/emacs/libs/libXpm-3.5.8/src -ID:/devel/emacs/libs/libpng-dev_1.4.3-1/include -ID:/devel/emacs/libs/zlib-dev_1.2.5-2/include -ID:/devel/emacs/libs/giflib-4.1.4-1/include -ID:/devel/emacs/libs/jpeg-6b-4/include -ID:/devel/emacs/libs/tiff-3.8.2-1/include -ID:/devel/emacs/libs/gnutls-3.0.9/include -ID:/devel/emacs/libs/libiconv-1.13.1-1-dev/include -ID:/devel/emacs/libs/libxml2-2.7.8/include/libxml2' Important settings: value of $LANG: ENU locale-coding-system: cp1252 default enable-multibyte-characters: t Major mode: Info Minor modes in effect: yas-global-mode: t yas-minor-mode: t global-auto-complete-mode: t diff-auto-refine-mode: t recentf-mode: t desktop-save-mode: t tooltip-mode: t mouse-wheel-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t buffer-read-only: t line-number-mode: t transient-mark-mode: t Features: (shadow sort mail-extr emacsbug message rfc822 mml mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums conf-mode sh-script smie executable info dos org-table org-wl org-w3m org-vm org-rmail org-mhe org-mew org-irc org-jsinfo org-infojs org-html org-exp ob-exp org-exp-blocks org-agenda org-info org-gnus org-docview org-bibtex bibtex org-bbdb face-remap gtags js json moz imenu thingatpt vc-git js2-mode-autoloads finder-inf undo-tree-autoloads package multi-web-mode mumamo-fun mumamo-chunks amrita desktop-autosave hide-lines yasnippet help-mode auto-complete-config auto-complete popup flymake-jslint flymake php-mode etags cc-langs cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align speedbar sb-image ezimage dframe psvn derived log-edit pcvs-util add-log diff-mode elp ediff-merg ediff-diff ediff-wind ediff-mult ediff-help ediff-init ediff-util dired emacsw32 w32-integ w32shell w32-grep rebind ourcomments-widgets ourcomments-util rx cus-edit cus-start cus-load uniquify recentf tree-widget mm-url url url-proxy url-privacy url-expand url-methods url-history url-cookie url-domsuf url-util url-parse auth-source eieio password-cache url-vars mailcap gnus gnus-ems nnheader gnus-util mail-utils mm-util mail-prsvr org ob-tangle ob-ref ob-lob ob-table org-footnote org-src ob-comint ob-keys org-pcomplete pcomplete org-list org-faces org-entities noutline outline org-version ob-emacs-lisp ob org-compat org-macs ob-eval org-loaddefs format-spec find-func cal-menu calendar cal-loaddefs ido grep compile comint ansi-color ring bookmark pp apropos mumamo byte-opt warnings bytecomp byte-compile cconv advice help-fns advice-preload sgml-mode ruby-mode rng-nxml rng-valid rng-loc rng-uri rng-parse nxml-parse rng-match rng-dt rng-util rng-pttrn nxml-ns nxml-mode nxml-outln nxml-rap nxml-util nxml-glyph nxml-enc xmltok mumamo-cmirr flyspell ispell desktop cc-engine cc-vars cc-defs new-key-seq-widget edmacro kmacro wid-edit hfyview easy-mmode easymenu htmlfontify cl-macs gv cl cl-lib noprint nxhtml-loader emacsw32-eol time-date tooltip ediff-hook vc-hooks lisp-float-type mwheel dos-w32 ls-lisp w32-common-fns disp-table w32-win w32-vars tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment lisp-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote make-network-process w32 multi-tty emacs) ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-09 20:14 bug#15577: 24.3; dir-local variables not applied when switching major-mode yary @ 2013-10-09 21:42 ` Glenn Morris 2013-10-10 18:34 ` yary [not found] ` <mailman.3789.1381430919.10748.bug-gnu-emacs@gnu.org> 1 sibling, 1 reply; 20+ messages in thread From: Glenn Morris @ 2013-10-09 21:42 UTC (permalink / raw To: yary; +Cc: 15577 yary wrote: > If I create a ".dir-locals.el" that applies to all major modes, such as: > ((nil . ((tab-width . 3)))) > It works when first opening any file under that directory- good. But, if > I switch the buffer's major-mode, it loses the directory-local > tab-width - File-local variables behave in the same way. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-09 21:42 ` Glenn Morris @ 2013-10-10 18:34 ` yary 2013-10-10 21:27 ` Glenn Morris 0 siblings, 1 reply; 20+ messages in thread From: yary @ 2013-10-10 18:34 UTC (permalink / raw To: Glenn Morris; +Cc: 15577 Before posting the mode-change-clobbering-locals behavior as a bug, I asked about it on stackoverflow, which generated a thorough explanation : http://stackoverflow.com/questions/19280851/how-to-keep-dir-local-variables-when-switching-major-modes -y On Wed, Oct 9, 2013 at 5:42 PM, Glenn Morris <rgm@gnu.org> wrote: > yary wrote: > >> If I create a ".dir-locals.el" that applies to all major modes, such as: >> ((nil . ((tab-width . 3)))) >> It works when first opening any file under that directory- good. But, if >> I switch the buffer's major-mode, it loses the directory-local >> tab-width - > > File-local variables behave in the same way. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-10 18:34 ` yary @ 2013-10-10 21:27 ` Glenn Morris 2013-10-10 21:52 ` Stefan Monnier 0 siblings, 1 reply; 20+ messages in thread From: Glenn Morris @ 2013-10-10 21:27 UTC (permalink / raw To: yary; +Cc: 15577 yary wrote: > Before posting the mode-change-clobbering-locals behavior as a bug, I > asked about it on stackoverflow, which generated a thorough > explanation : http://stackoverflow.com/questions/19280851/how-to-keep-dir-local-variables-when-switching-major-modes I think it slightly impolite to post the same question to two different places at the same time. Anyway, are you happy with the answers you have, or do you want Emacs to change? It is a long-standing behaviour that local variables (file or directory) are only applied (by normal-mode) when you visit a file, and get clobbered by major-mode changes. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-10 21:27 ` Glenn Morris @ 2013-10-10 21:52 ` Stefan Monnier 2013-10-10 23:12 ` yary 0 siblings, 1 reply; 20+ messages in thread From: Stefan Monnier @ 2013-10-10 21:52 UTC (permalink / raw To: Glenn Morris; +Cc: yary, 15577 > Anyway, are you happy with the answers you have, or do you want Emacs to > change? It is a long-standing behaviour that local variables (file or > directory) are only applied (by normal-mode) when you visit a file, and > get clobbered by major-mode changes. I do think it's at least undesirable behavior. Not sure how best to fix it, tho. We could try and setup file-local vars when we run after-change-major-mode-hook. Stefan ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-10 21:52 ` Stefan Monnier @ 2013-10-10 23:12 ` yary 2013-10-14 18:41 ` yary 0 siblings, 1 reply; 20+ messages in thread From: yary @ 2013-10-10 23:12 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 @Glenn "slightly impolite to post the same question to two different places" -Understood, but this is a bug report, different purpose from Stackoverflow question- and thus "are you happy with the answers you have, or do you want Emacs to change?"- both! The answers are a workaround for the current situation, but are slightly imperfect, and as Stefan just wrote the current scheme is "at least undesirable behavior." The problem with the "(add-hook 'after-change-major-mode-hook 'hack-local-variables)" workaround and its variants, is when a major-mode is set by a file-local variable- changing major mode will reload the local variables, which will revert the major-mode again! And the trouble with current Emacs out-of-the-box behavior is not gaining the relevant file-local and dir-local variables for a new major-mode when changing to that major-mode. I'd like to see a well-thought-out solution in some future release. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-10 23:12 ` yary @ 2013-10-14 18:41 ` yary 2013-10-16 14:26 ` yary 0 siblings, 1 reply; 20+ messages in thread From: yary @ 2013-10-14 18:41 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 Thinking about switching major modes more, my instinct is that the right solution involves being "smarter" both about which local variables to clear and reloading any {dir,file}-local variables for the new node. Basically, at the start, instead of calling "kill-all-local-variables", only clear the locals that were set as a consequence of the old mode. That is, if it was set directly by the old mode, or by dir-local matching the old mode, delete it. Don't delete a buffer-local variable if it was set explicitly by the user after opening during the editing session. Then after the new mode has set itself, recheck dir-locals and set any that match the new mode. Alas I don't use file-locals so am not sure how their use cases fit. Ignore any "mode:" specifiers and maybe "eval:" as well after the mode-change, I'd guess. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-14 18:41 ` yary @ 2013-10-16 14:26 ` yary 2013-10-18 15:43 ` yary 2013-10-18 16:29 ` Phil Sainty 0 siblings, 2 replies; 20+ messages in thread From: yary @ 2013-10-16 14:26 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 More thoughts, overturning my previous message of Oct 14th. I think I have the essence of the issues now. In my editing, I switch modes within a buffer (file) when working on: A. databases- SQL inside code, or non-SQL language inside SQL triggers B. web- HTML, CSS, JS is just the beginning... C. any language with heredocs (shell, python, perl)- sometimes have unrelated language blocks inside parent/wrapper code and I've had these undesirable local-variable issues caused by that mode switching: 1. dir-locals not being applied in the new mode 2. "manually" set local variables and minor-modes being lost. Issue #1 "dir locals" is a narrow use case. Dir locals are not intended to set a major mode; they are meant to set buffer-locals after the major mode is in place. Whether set by a .dir-locals,el file or dir-locals-set-* functions, the user is saying "buffers from files here in this mode should have those variables set" and is saying so clearly. So, to fix that issue, after switching major modes, it would be good to run "hack-dir-local-variables-non-file-buffer" to pick up any dir-locals for the new mode. Properly implementing that as an Emacs bug-fix is out of my skillset, though the tips from stackoverflow helped me put a workaround in my ~/.emacs Issue #2- "manually" set buffer-local's, and by extension file-local variables- is trickier. Trying to automate what happens there smells of unintended consequences. The answer here is an easier way for us to set the "permanent-local-hook" property for variables (eg "tab-width"), and minor-modes (eg "buffer-face-mode" with its new face). Then I & others who use file-locals can mark a particular item as "permanent" right in the file. Additionally, for other local variables that people might want to keep (eg set interactively), have an interactive command to mark a buffer-local variable or minor-mode as permanent. And also, allow describe-variable, describe-minor-mode to show/set the "permanent-local-hook" property. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-16 14:26 ` yary @ 2013-10-18 15:43 ` yary 2013-10-19 1:18 ` Stefan Monnier 2013-10-18 16:29 ` Phil Sainty 1 sibling, 1 reply; 20+ messages in thread From: yary @ 2013-10-18 15:43 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 My implementation thoughts for core-level fixes, after working on personal workarounds. For sub-issue #1 "dir-locals not being applied in the new mode," divide the responsibility for setting file-locals and dir-locals between `normal-mode find-file=t' and `define-derived-mode'. Just have `define-derived-mode' call `(hack-dir-local-variables)(hack-local-variables-apply)' unless it is being called as a result of `normal-mode t'. There's no change needed for the normal-mode function or anything it calls, except perhaps setting something that the define-derived-mode macro can check. For sub-issue #2 "an easier way for us to preserve minor-modes and buffer-local variables when switching modes"- I discovered this exchange showing it's been raised before https://lists.gnu.org/archive/html/emacs-devel/2007-12/msg00366.html which resulted in adding the property `permanent-local-hook' to compliment the `permanent-local' property, facilitating minor-mode preservation. That was in the context of helping mode authors preserve specific minor-modes. In itself, it isn't enough for a generic minor-mode preservation but it can help. A function to preserve any minor-mode needs to a. Get all of that mode's customizable buffer-locals. Ideally the minor-mode, or emacs core, would provide a function for that purpose. If not, might be able to reliably get a list by creating a scratch buffer, saving results of `buffer-local-variables', enabling the minor mode in question, then mark the differences from a subsequent call to `buffer-local-variables'. b. Mark those variables as permanent-local Then either b1. Continue to allow major-mode changes to disable all minor-modes, but re-enable the user-requested minor-modes after calling kill-all-local-variables. This doesn't require any use of `permanent-local-hook'; the minor mode is being disabled and re-enabled and any hooks can be normally uninstalled & re-installed & re-run b2. Apply `permanent-local-hook' to all the minor-mode's hook functions. The minor mode might provide those symbols via a function for that purpose, or perhaps they could be auto-discovered. Alas I don't yet know enough about Emacs' minor-mode handling to get further with these thoughts. Thanks for bearing with me. -y ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-18 15:43 ` yary @ 2013-10-19 1:18 ` Stefan Monnier 2013-10-19 19:08 ` yary 0 siblings, 1 reply; 20+ messages in thread From: Stefan Monnier @ 2013-10-19 1:18 UTC (permalink / raw To: yary; +Cc: 15577 > For sub-issue #1 "dir-locals not being applied in the new mode," > divide the responsibility for setting file-locals and dir-locals > between `normal-mode find-file=t' and `define-derived-mode'. Just have > `define-derived-mode' call > `(hack-dir-local-variables)(hack-local-variables-apply)' unless it is > being called as a result of `normal-mode t'. There's no change needed > for the normal-mode function or anything it calls, except perhaps > setting something that the define-derived-mode macro can check. Yes, as mentioned earlier, a possible fix is to move the file-local and dir-local setup code from normal-mode to after-change-major-mode-hook. > a. Get all of that mode's customizable buffer-locals. Not sure what that is. > Ideally the minor-mode, or emacs core, would provide a function for > that purpose. It's probably not possible (not reliably at least) with the way minor modes are defined currently. Tho depending on what you mean it might be a non-issue. > b. Mark those variables as permanent-local There's no such thing, currently (we instead have to use a hack with change-major-mode-hook, along the lines of what you did). For minor-modes, what we could do is to check which buffer-local minor-modes are enabled, and to "simply" re-enable them in after-change-major-mode-hook. But there are some issues: - we have to find out which buffer-local minor-modes are enabled, which presumes we have some kind of list of minor-modes. We can probably use minor-mode-list for that, tho. - some minor modes are mode-specific; e.g. it doesn't make much sense to preserve reftex-mode when switching from latex-mode to haskell-mode. Stefan ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-19 1:18 ` Stefan Monnier @ 2013-10-19 19:08 ` yary 2013-10-19 21:55 ` Stefan Monnier 0 siblings, 1 reply; 20+ messages in thread From: yary @ 2013-10-19 19:08 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 On Fri, Oct 18, 2013 at 9:18 PM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> For sub-issue #1 "dir-locals not being applied in the new mode," >> divide the responsibility for setting file-locals and dir-locals >> between `normal-mode find-file=t' and `define-derived-mode'. Just have >> `define-derived-mode' call >> `(hack-dir-local-variables)(hack-local-variables-apply)' unless it is >> being called as a result of `normal-mode t'. There's no change needed >> for the normal-mode function or anything it calls, except perhaps >> setting something that the define-derived-mode macro can check. > > Yes, as mentioned earlier, a possible fix is to move the file-local and > dir-local setup code from normal-mode to after-change-major-mode-hook. Moving dir-local setup code to after-change-major-mode-hook would be a simple fix for issue #1. File-local (as it is now) in after-change-major-mode-hook would cause some problems eg. if a file-local sets the mode! I'm opening a new bug for handling file-locals after major-mode-change, it's different enough to warrant its own discussion (and will also answer your questions about what I meant there), The initial report here was about dir-locals, which has a solution independent from the other buffer-local issues; let's just keep this bug#15577 about re-applying dir locals after a mode change. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-19 19:08 ` yary @ 2013-10-19 21:55 ` Stefan Monnier 2013-10-20 13:00 ` yary 0 siblings, 1 reply; 20+ messages in thread From: Stefan Monnier @ 2013-10-19 21:55 UTC (permalink / raw To: yary; +Cc: 15577 > Moving dir-local setup code to after-change-major-mode-hook would be a > simple fix for issue #1. File-local (as it is now) in > after-change-major-mode-hook would cause some problems eg. if a > file-local sets the mode! Obviously if we move the mode-setting part, we introduce a bug, so we wouldn't move it (it's already handled separately for the same kind of reasons). Stefan ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-19 21:55 ` Stefan Monnier @ 2013-10-20 13:00 ` yary 2013-10-20 13:38 ` Phil Sainty 0 siblings, 1 reply; 20+ messages in thread From: yary @ 2013-10-20 13:00 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 For anyone following this discussion, I moved the non-dir-local parts to: bug#15658: Easy way to make a file-local variable also permanent-local bug#15659: Simple method for preserving minor-mode >> Moving dir-local setup code to after-change-major-mode-hook would be a >> simple fix for issue #1. File-local (as it is now) in >> after-change-major-mode-hook would cause some problems eg. if a >> file-local sets the mode! > >Obviously if we move the mode-setting part, we introduce a bug, so we >wouldn't move it (it's already handled separately for the same kind of >reasons). Right. So it looks like a patch for moving dir-local setup to after-change-major-mode-hook is in order. Where I fall down in the implementation is figuring out what exactly changes so that I don't change behavior for find-file or kill-all-local-variables, and also don't set dir-locals twice when opening a file (without using defadvice which seems wrong in the core). Plus I'd have to get started as a contributor. Neither are insurmountable, though I think I don't have much more time to devote to these at the moment. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-20 13:00 ` yary @ 2013-10-20 13:38 ` Phil Sainty 2013-10-21 13:11 ` Stefan Monnier 0 siblings, 1 reply; 20+ messages in thread From: Phil Sainty @ 2013-10-20 13:38 UTC (permalink / raw To: yary, Stefan Monnier; +Cc: 15577 I've been experimenting with this today (along the lines of http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-10/msg00534.html ) and one of the things I noticed which I'd not previously considered was the major mode switches which happen every time you enter the minibuffer. I expect that we should make an exception for those mode changes, as (a) that is going to be a far more frequent occurrence -- and for people who enable local variable processing for tramp buffers, probably annoyingly expensive to boot -- but more importantly (b) there surely aren't any actual use-cases for dir/file locals in the minibuffer? Does that sound sensible? -Phil ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-20 13:38 ` Phil Sainty @ 2013-10-21 13:11 ` Stefan Monnier 2013-10-21 13:23 ` yary 0 siblings, 1 reply; 20+ messages in thread From: Stefan Monnier @ 2013-10-21 13:11 UTC (permalink / raw To: Phil Sainty; +Cc: yary, 15577 > I've been experimenting with this today (along the lines of > http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-10/msg00534.html ) > and one of the things I noticed which I'd not previously considered > was the major mode switches which happen every time you enter the > minibuffer. I don't see why that would be a problem: only the *Minibuf-N* buffer changes major mode (and not even that, really, because mini-buffers don't follow the rules w.r.t major modes). Stefan ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-21 13:11 ` Stefan Monnier @ 2013-10-21 13:23 ` yary 2013-10-21 14:23 ` Stefan Monnier 0 siblings, 1 reply; 20+ messages in thread From: yary @ 2013-10-21 13:23 UTC (permalink / raw To: Stefan Monnier; +Cc: 15577 On Mon, Oct 21, 2013 at 9:11 AM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> I've been experimenting with this today (along the lines of >> http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-10/msg00534.html ) >> and one of the things I noticed which I'd not previously considered >> was the major mode switches which happen every time you enter the >> minibuffer. > > I don't see why that would be a problem: only the *Minibuf-N* buffer > changes major mode (and not even that, really, because mini-buffers > don't follow the rules w.r.t major modes). I also noticed that going into the minibuffer would trigger mode-change hooks, and much hilarity ensued when I had a call to the debugger dropped in there... I don't have more to add other than I am following these posts with interest, and thanks for running it. Seems like you will be able to handle both file and dir-locals, and that splitting out file locals to bug #15658 was premature- I prefer the way you're going, since it keeps the permanence within the buffer; my proposal would have set the "permanent-local" property and alas properties are always global. ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-21 13:23 ` yary @ 2013-10-21 14:23 ` Stefan Monnier 2013-10-21 21:58 ` Phil Sainty 0 siblings, 1 reply; 20+ messages in thread From: Stefan Monnier @ 2013-10-21 14:23 UTC (permalink / raw To: yary; +Cc: 15577 > I prefer the way you're going, Just to clarify, in case there was some confusion: I'm not actually working on any of that. I'm just giving guidance for someone who wants to write a patch. Stefan "plenty of other things to do right now" ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-21 14:23 ` Stefan Monnier @ 2013-10-21 21:58 ` Phil Sainty 0 siblings, 0 replies; 20+ messages in thread From: Phil Sainty @ 2013-10-21 21:58 UTC (permalink / raw To: Stefan Monnier; +Cc: yary, 15577 >> I prefer the way you're going, > > Just to clarify, in case there was some confusion: I'm not actually > working on any of that. I'm just giving guidance for someone who > wants to write a patch. That comment may have been directed at me (and I do indeed intend to provide a patch). I need to rework some code to make the major mode variable detection more generally-available, as my existing solution to avoid applying a major mode local variable depends on hack-local-variables being called, but that doesn't happen in all cases. I think it's looking promising, though. -Phil ^ permalink raw reply [flat|nested] 20+ messages in thread
* bug#15577: 24.3; dir-local variables not applied when switching major-mode 2013-10-16 14:26 ` yary 2013-10-18 15:43 ` yary @ 2013-10-18 16:29 ` Phil Sainty 1 sibling, 0 replies; 20+ messages in thread From: Phil Sainty @ 2013-10-18 16:29 UTC (permalink / raw To: 15577 My gut feeling is that retaining (across a major mode change) the values of local variables which were set *interactively* probably isn't a practical thing to try to do? For starters we would have to flag variables as having been set interactively, otherwise there would be no way of telling which local values should be kept and which should be cleared. (e.g. if a major mode hook sets a local variable, we're not going to want to retain that when we change major modes.) But even knowing that a value was set interactively still isn't a *guarantee* that it should remain unchanged for the new major mode? What seems much simpler is to always hack-local-variables after a major mode change, and simply work out a solution to the associated problem with local 'mode' variables. If we do that, then all of the local variables which are *automatically* set for a given mode will be set correctly, which is all people actually need, most of the time. That seems to me like a "good enough" approach (and one which should be safer). At present `normal-mode' runs: (report-errors "File local-variables error: %s" (hack-local-variables)) My first thought was to just move that into `run-mode-hooks', but that relies upon the major mode function running its mode hook, which I presume isn't guaranteed (and maybe this is exactly why the code *does* run in `normal-mode'?) It's unclear to me whether this is a real concern, though -- can we assume that all major modes *will* call `kill-all-local-variables' and `run-mode-hooks'? Certainly all the non-derived major modes I've looked at in the Emacs lisp files take care of these steps manually. (Well... I suppose for any modes which don't do this housekeeping, there's actually nothing we can do to help in the situation when they are called interactively. So as long as we ensure that things work when `normal-mode' runs, and also when any *well-behaved* major mode is called interactively, we'll be doing everything that we can reasonably do.) So... how about this as a basic approach: * Define a new buffer-local variable to track whether local vars have been hacked (nil by default). This will obviously get reset in any given buffer when a mode calls `kill-all-local-variables'; and to take care of the case when `set-auto-mode' calls a 'badly-behaved' mode (one which does not kill local vars), we can also let-bind the variable to nil in normal-mode. * `normal-mode' then tests this variable before calling `hack-local-variables', only calling the function if the variable is nil. Most of the time, however, it will be non-nil, because... * `run-mode-hooks' calls `hack-local-variables' after it has run `after-change-major-mode-hook'. This is therefore the way that the vast majority of major modes will set the local vars, (but the code in `normal-mode' will still account for exceptions). See diffs below (from 24.3, and untested) for a possible implementation. This approach seems a little cleaner than the one used in the Stack Overflow workaround, as this way we are more consistent in *where* we call `hack-local-variables' for a given mode (the other approach would either call it after the mode change OR in normal-mode, depending on whether or not the mode was called interactively.) That leaves the problem of local 'mode' variables making it impossible to interactively call a different mode (because we immediately switch back to the mode specified by the local var). The code has me slightly confused here: `hack-one-local-variable' calls the mode function when there is a local mode variable, but my initial thought is that we only want to use a local mode var when running `set-auto-mode'? Yet set-auto-mode has already set the mode -- using the (hack-local-variables MODE-ONLY) look-up -- *before* we get to `hack-one-local-variable', so should the latter function actually ignore 'mode' vars instead? If we did that, then the problem would go away. I suspect I'm missing something here? Ah, okay; `autoload-find-file' is an example of code which could need a mode var to be processed directly by `hack-one-local-variable'. How about if we provide a new variable which determines whether or not local mode variables will be applied? Or maybe it should be an argument to `hack-local-variables'? By default we enable the behaviour, so there's no change for any code which hacks local variables directly; but in `normal-mode' and `run-mode-hooks' we explicitly disable it, so that mode variables are ignored. (n.b. The example code below does not implement this suggestion.) -Phil diff -u -L /usr/local/share/emacs/24.3/lisp/files.el.gz -L \#\<buffer\ files.el.gz\> /tmp/jka-com2287tTC /tmp/buffer-content-2287HoO --- /usr/local/share/emacs/24.3/lisp/files.el.gz +++ #<buffer files.el.gz> @@ -2172,13 +2172,17 @@ in that case, this function acts as if `enable-local-variables' were t." (interactive) (funcall (or (default-value 'major-mode) 'fundamental-mode)) - (let ((enable-local-variables (or (not find-file) enable-local-variables))) + (let ((enable-local-variables (or (not find-file) enable-local-variables)) + (local-variables-hacked nil)) ;; FIXME this is less efficient than it could be, since both ;; s-a-m and h-l-v may parse the same regions, looking for "mode:". (report-errors "File mode specification error: %s" (set-auto-mode)) - (report-errors "File local-variables error: %s" - (hack-local-variables))) + ;; Most major modes will hack local vars via `run-mode-hooks'; + ;; this catches the exceptions: + (unless local-variables-hacked + (report-errors "File local-variables error: %s" + (hack-local-variables)))) ;; Turn font lock off and on, to make sure it takes account of ;; whatever file local variables are relevant to it. (when (and font-lock-mode @@ -3140,6 +3144,11 @@ (assq-delete-all (car elt) file-local-variables-alist))) (push elt file-local-variables-alist))))) +(defvar local-variables-hacked nil + "Buffer-local variable which indicates whether `hack-local-variables' +has run for the current buffer.") +(make-variable-buffer-local 'local-variables-hacked) + (defun hack-local-variables (&optional mode-only) "Parse and put into effect this buffer's local variables spec. Uses `hack-local-variables-apply' to apply the variables. @@ -3277,7 +3286,8 @@ (if mode-only result ;; Otherwise, set the variables. (hack-local-variables-filter result nil) - (hack-local-variables-apply))))) + (hack-local-variables-apply) + (setq local-variables-hacked t))))) (defun hack-local-variables-apply () "Apply the elements of `file-local-variables-alist'. diff -u -L /usr/local/share/emacs/24.3/lisp/subr.el.gz -L \#\<buffer\ subr.el.gz\> /tmp/jka-com2287GnH /tmp/buffer-content-2287g7T --- /usr/local/share/emacs/24.3/lisp/subr.el.gz +++ #<buffer subr.el.gz> @@ -1588,7 +1588,9 @@ (setq hooks (nconc (nreverse delayed-mode-hooks) hooks)) (setq delayed-mode-hooks nil) (apply 'run-hooks (cons 'change-major-mode-after-body-hook hooks)) - (run-hooks 'after-change-major-mode-hook))) + (run-hooks 'after-change-major-mode-hook) + (report-errors "File Local-variables error: %s" + (hack-local-variables)))) (defmacro delay-mode-hooks (&rest body) "Execute BODY, but delay any `run-mode-hooks'. ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <mailman.3789.1381430919.10748.bug-gnu-emacs@gnu.org>]
* bug#15577: 24.3; dir-local variables not applied when switching major-mode [not found] ` <mailman.3789.1381430919.10748.bug-gnu-emacs@gnu.org> @ 2016-05-05 11:26 ` Alan Mackenzie 0 siblings, 0 replies; 20+ messages in thread From: Alan Mackenzie @ 2016-05-05 11:26 UTC (permalink / raw To: 15577-done; +Cc: yary Bug fixed in the master branch of GNU's savannah Emacs repository. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2016-05-05 11:26 UTC | newest] Thread overview: 20+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-10-09 20:14 bug#15577: 24.3; dir-local variables not applied when switching major-mode yary 2013-10-09 21:42 ` Glenn Morris 2013-10-10 18:34 ` yary 2013-10-10 21:27 ` Glenn Morris 2013-10-10 21:52 ` Stefan Monnier 2013-10-10 23:12 ` yary 2013-10-14 18:41 ` yary 2013-10-16 14:26 ` yary 2013-10-18 15:43 ` yary 2013-10-19 1:18 ` Stefan Monnier 2013-10-19 19:08 ` yary 2013-10-19 21:55 ` Stefan Monnier 2013-10-20 13:00 ` yary 2013-10-20 13:38 ` Phil Sainty 2013-10-21 13:11 ` Stefan Monnier 2013-10-21 13:23 ` yary 2013-10-21 14:23 ` Stefan Monnier 2013-10-21 21:58 ` Phil Sainty 2013-10-18 16:29 ` Phil Sainty [not found] ` <mailman.3789.1381430919.10748.bug-gnu-emacs@gnu.org> 2016-05-05 11:26 ` Alan Mackenzie
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.