0

I wrote a little derived mode for the kage shader language, it's derived from go-mode (syntax is the same). I also like to use gofmt, but it's just not loading the hook.

Here's the mode:

(define-derived-mode kage-mode go-mode "Kage shader script"
  "Kage mode is a major mode for editing Ebitengine Kage shader files"
  ;; disable lsp just in case, kage  is not supported properly by lsp,
  ;; even if kage code looks like go, it isn't
  (lsp-mode nil))

(defun kage-gofmt-before-save ()
  (interactive)
  (when (eq major-mode 'kage-mode) (gofmt)))

(autoload 'kage-mode "kage-mode")
(autoload 'kage-gofmt-before-save "execute gofmt on write")

(provide 'kage-mode)

And this is the config:

(use-package kage-mode
  :ensure nil ;; installed in site-lisp
  :defer nil
  :mode "\\.kg\\'"
  :commands kage-gofmt-before-save
  :init
  (add-hook 'before-save-hook
            #'kage-gofmt-before-save
            nil t))

I tried many variations (like putting the add-hook into the :config section, using a lambda() instead of a direct hook, etc). Nothing works so far, that is, when I open a kage file, before-save-hook is empty.

When I execute kage-gofmt-before-save it works.

How can I add that hook to before-save-hook?

5
  • Did you check the value of the hook? Does it include your function?
    – NickD
    Mar 15 at 1:53
  • "Nothing works so far" - how do you check whether it worked?
    – NickD
    Mar 15 at 3:22
  • Well, when I open a kage file, then the hook variable before-safe-hook is empty. And if I change some code in the file and safe it, nothing will be corrected (what would happen if the hook worked, since it executes gofmt -s on the buffer).
    – Tom
    Mar 15 at 7:56
  • Should be save, not safe: are you spelling it correctly?
    – NickD
    Mar 15 at 13:09
  • 1
    I only spelled it wrong here in the question, in my config I use before-save-hook. But I corrected the question.
    – Tom
    Mar 18 at 8:19

2 Answers 2

0

I don't know anything about use-package, but I imagine it evaluates the :init form exactly once, and yet you're passing LOCAL to add-hook in that init form. I imagine that's a mistake and the cause of your problem.

5
  • Indeed, when I remove the local flag, it works. However, it's not local then anymore.
    – Tom
    Mar 18 at 18:40
  • Well yes -- it's no good having a local hook function in whichever single arbitrary buffer happened to be current at the time your code was initially loaded. If the intention is for it to be local in buffers using kage-mode then do it in your kage-mode body.
    – phils
    Mar 18 at 20:27
  • And if the idea is not to force that on people, then use kage-mode-hook.
    – phils
    Mar 18 at 20:28
  • I finally solved it. The primary problem was the go-mode-hooks. These have been loaded because kage-mode derives from it. I removed these hooks, used kage-mode-hook as suggested (thanks!) and now it works as I want.
    – Tom
    Mar 19 at 6:58
  • Right, that all makes sense. stackoverflow.com/a/19295380/324105 might be useful reading regarding the sequence of events for derived modes, in case you're still missing any pieces of that puzzle.
    – phils
    Mar 22 at 5:07
0

This needs to be configured via kage-mode-hook. This is the fixed mode:

(define-derived-mode kage-mode go-mode "Kage shader script"
  "Kage mode is a major mode for editing Ebitengine Kage shader files")

(defun kage-gofmt-before-save ()
  (interactive)
  (when (eq major-mode 'kage-mode) (gofmt)))

(autoload 'kage-mode "kage-mode")
(autoload 'kage-gofmt-before-save "execute gofmt on write")

(provide 'kage-mode)

And this is the use-package code I use:

(use-package kage-mode
  :ensure nil ;; installed in site-lisp
  :defer nil
  :mode "\\.kg\\'"
  :commands kage-gofmt-before-save

  :init
  (defun tvd-kage-install-hooks()
    (remove-hook 'before-save-hook #'lsp-format-buffer t)
    (remove-hook 'before-save-hook #'lsp-organize-imports t)
    (add-hook 'before-save-hook #'kage-gofmt-before-save t t))

  :config
  (add-hook 'kage-mode-hook #'tvd-kage-install-hooks)
  (setq lsp-warn-no-matched-clients nil))

Here I remove the lsp-mode symbols from the before-save-hook (which have been added via go-mode-hook and add my own. I also disable the lsp-mode warning about non matching client.

2
  • (run-hooks 'kage-mode-hook) is not necessary. By default, the mode function generated by (define-derived-mode kage-mode ...) will run kage-mode-hook.
    – phils
    Mar 19 at 9:02
  • Thanks, it works indeed w/o it.
    – Tom
    Mar 19 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.