Subject: bug#74447: 30.0.92; asm-comment-char cannot be set via dir-local variables

From: Eli Zaretskii <[email-masked]>
Date: Sat, 30 Nov 2024 12:04:01 +0200

Ping!  Johann, could you please try Stefan's patch below and see if it
solves the problem?

> From: Stefan Monnier <[email-masked]>
> Cc: Johann Klähn <[email-masked]>,
>   [email-masked]
> Date: Wed, 20 Nov 2024 14:36:42 -0500
> 
> >> In `.dir-locals.el' setting `((asm-mode . ((asm-comment-char . 35))))'
> >> does not have the desired effect.  The comment char is still `;' instead
> >> of `#'.  The reason is that when the syntax table is adjusted according
> >> to the comment char in the body of `asm-mode', the dir-local variables
> >> haven't been loaded yet: `run-mode-hooks' (which would call
> >> `hack-local-variables') is only invoked _after_ the `define-derived-mode'
> >> body, i.e., too late.
> >> 
> >> I'm using the following workaround:
> >> 
> >>     (defun asm-mode-set-comment-char-from-dir-local-variables ()
> >>       "Load `asm-comment-char' from dir-local variables.
> >>     This is a HACK, since in `asm-mode', `run-mode-hooks' (which would call
> >>     `hack-local-variables') is only invoked after the `define-derived-mode' body,
> >>     i.e., too late."
> >>       (let ((enable-local-variables :safe))
> >>         (hack-dir-local-variables)
> >>         (when-let* ((char (alist-get 'asm-comment-char dir-local-variables-alist)))
> >>           (setq-local asm-comment-char char))))
> >>     (add-hook 'asm-mode-set-comment-hook #'asm-mode-set-comment-char-from-dir-local-variables)
> >> 
> >> But maybe there is a more principled approach?
> >
> > Stefan, any suggestions?
> 
> IIRC there are 2 "standard" solutions:
> 
> - in `asm-mode` use
> 
>       (add-hook 'hack-local-variables-hook #'asm--set-comment-syntax nil t)
> 
>   where `asm--set-comment-syntax` would be a new function that sets the
>   syntax-table according to `asm-comment-char`.
> 
> - in `asm-mode` move the syntax-table setting code to an `:after-hook`
>   section, as in the patch below.
> 
> 
>         Stefan
> 
> diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el
> index d47c525c5f9..76defbf6ac8 100644
> --- a/lisp/progmodes/asm-mode.el
> +++ b/lisp/progmodes/asm-mode.el
> @@ -125,25 +125,29 @@ asm-mode
>  
>  Special commands:
>  \\{asm-mode-map}"
> +  :after-hook
> +  (progn
> +    (run-hooks 'asm-mode-set-comment-hook)
> +    ;; Make our own local child of `asm-mode-map'
> +    ;; so we can define our own comment character.
> +    (use-local-map (nconc (make-sparse-keymap) asm-mode-map))
> +    (local-set-key (vector asm-comment-char) #'asm-comment)
> +    (set-syntax-table (make-syntax-table asm-mode-syntax-table))
> +    (modify-syntax-entry	asm-comment-char "< b")
> +
> +    (setq-local comment-start (string asm-comment-char)))
> +
>    (setq local-abbrev-table asm-mode-abbrev-table)
>    (setq-local font-lock-defaults '(asm-font-lock-keywords))
>    (setq-local indent-line-function #'asm-indent-line)
>    ;; Stay closer to the old TAB behavior (was tab-to-tab-stop).
>    (setq-local tab-always-indent nil)
>  
> -  (run-hooks 'asm-mode-set-comment-hook)
> -  ;; Make our own local child of `asm-mode-map'
> -  ;; so we can define our own comment character.
> -  (use-local-map (nconc (make-sparse-keymap) asm-mode-map))
> -  (local-set-key (vector asm-comment-char) #'asm-comment)
> -  (set-syntax-table (make-syntax-table asm-mode-syntax-table))
> -  (modify-syntax-entry	asm-comment-char "< b")
> -
> -  (setq-local comment-start (string asm-comment-char))
>    (setq-local comment-add 1)
>    (setq-local comment-start-skip "\\(?:\\s<+\\|/[/*]+\\)[ \t]*")
>    (setq-local comment-end-skip "[ \t]*\\(\\s>\\|\\*+/\\)")
> -  (setq-local comment-end ""))
> +  (setq-local comment-end "")
> +  ))
>  
>  (defun asm-indent-line ()
>    "Auto-indent the current line."