all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Adding and running a major mode hook
@ 2014-04-26 17:25 Jacob Gerlach
  2014-04-27  3:12 ` Eric Abrahamsen
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Jacob Gerlach @ 2014-04-26 17:25 UTC (permalink / raw)
  To: help-gnu-emacs

I think that a hook is the right way for me to allow users some customization in my major mode.

I have a list that is used to create font lock constructs, and I'd like to allow users to add to that list before my code processes it into font lock constructs.

What I have now is basically:

(setq content-list...)

(mapc 'create-constructs content-list)

What I've tried to do is

 (setq content-list ...)

 (defvar add-user-content-hook nil)
 (defun add-user-content (input)
   (add-hook 'add-user-content-hook
     (lambda () (add-to-list 'content-list input))))

 (run-hooks 'add-user-content-hook)

 (mapc 'create-constructs content-list)

With the intention that users put something like 

  (add-user-content '("my content"))

in their .emacs

This code doesn't generate any errors, but it doesn't work either.

Reading about hooks in the documentation makes me think that I have a conceptual misunderstanding about the manner and sequence in which code in mymode.el is executed. Specifically, what is the difference between putting (run-hooks... in (define-derived-mode ... vs putting (run-hooks... somewhere in the mode's code (as I have done above)?


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Adding and running a major mode hook
  2014-04-26 17:25 Adding and running a major mode hook Jacob Gerlach
@ 2014-04-27  3:12 ` Eric Abrahamsen
  2014-04-27  5:15 ` Eric Abrahamsen
       [not found] ` <mailman.107.1398568207.1147.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 6+ messages in thread
From: Eric Abrahamsen @ 2014-04-27  3:12 UTC (permalink / raw)
  To: help-gnu-emacs

Jacob Gerlach <jacobgerlach@gmail.com> writes:

> I think that a hook is the right way for me to allow users some customization in my major mode.
>
> I have a list that is used to create font lock constructs, and I'd like to allow users to add to that list before my code processes it into font lock constructs.
>
> What I have now is basically:
>
> (setq content-list...)
>
> (mapc 'create-constructs content-list)
>
> What I've tried to do is
>
>  (setq content-list ...)
>
>  (defvar add-user-content-hook nil)
>  (defun add-user-content (input)
>    (add-hook 'add-user-content-hook
>      (lambda () (add-to-list 'content-list input))))
>
>  (run-hooks 'add-user-content-hook)
>
>  (mapc 'create-constructs content-list)
>
> With the intention that users put something like 
>
>   (add-user-content '("my content"))
>
> in their .emacs
>
> This code doesn't generate any errors, but it doesn't work either.
>
> Reading about hooks in the documentation makes me think that I have a conceptual misunderstanding about the manner and sequence in which code in mymode.el is executed. Specifically, what is the difference between putting (run-hooks... in (define-derived-mode ... vs putting (run-hooks... somewhere in the mode's code (as I have done above)?

If you've got the run-hooks inside the mode declaration, then the hooks
won't run until the user activates the mode in some particular buffer.
They will then run *every* time your mode is activated.

If you've got it at the top level of the file, the hooks will run once,
*while* the file is being loaded for the first time: ie quite likely
during emacs startup, possibly before the user's relevant customization
is loaded, probably before any relevant file are opened.

They won't run again later, when the user calls `add-user-content',
because all `add-user-content' does is add to the hook, it doesn't run
the hook again. You'd have to reload the file for that.

From what I can see from your examples above, it might be enough just to
have:

(defvar content-list '(default values))

(define-derived-mode 'your-mode
  ....
  (mapc 'create-constructs content-list)

(defun add-user-content (input)
  (add-to-list 'content-list input))

Without any hooks at all.

When the file is loaded, these functions are defined, but no constructs
are created. After the file is loaded, the user's customizations are
loaded, including possible calls to `add-user-content', which put new
values into `content-list'. Then, *every time* the user activates this
mode, constructs are created out of whatever's in `content-list'.

Now your new problem is, do you want new constructs created every time
the mode is activated? Will that create duplicate/extraneous constructs?
I don't actually know much about font constructs, so maybe this is how
it's supposed to work to begin with.

Anyway, if you do go the hook route, remember that it won't make much
sense to call `run-hooks' at the top level of the file. That's pretty
much always done in the mode declaration, or in other functions. Hooks
are meant to store functions to be run later, when something else
happens. If you put it at the top level of the file, it will only happen
on load, in which case you might as well just call whatever the function
is directly.

Hope that didn't make it worse,
Eric




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Adding and running a major mode hook
  2014-04-26 17:25 Adding and running a major mode hook Jacob Gerlach
  2014-04-27  3:12 ` Eric Abrahamsen
@ 2014-04-27  5:15 ` Eric Abrahamsen
       [not found] ` <mailman.107.1398568207.1147.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 6+ messages in thread
From: Eric Abrahamsen @ 2014-04-27  5:15 UTC (permalink / raw)
  To: help-gnu-emacs

Jacob Gerlach <jacobgerlach@gmail.com> writes:

> I think that a hook is the right way for me to allow users some customization in my major mode.
>
> I have a list that is used to create font lock constructs, and I'd like to allow users to add to that list before my code processes it into font lock constructs.
>
> What I have now is basically:
>
> (setq content-list...)
>
> (mapc 'create-constructs content-list)
>
> What I've tried to do is
>
>  (setq content-list ...)
>
>  (defvar add-user-content-hook nil)
>  (defun add-user-content (input)
>    (add-hook 'add-user-content-hook
>      (lambda () (add-to-list 'content-list input))))
>
>  (run-hooks 'add-user-content-hook)
>
>  (mapc 'create-constructs content-list)
>
> With the intention that users put something like 
>
>   (add-user-content '("my content"))
>
> in their .emacs
>
> This code doesn't generate any errors, but it doesn't work either.
>
> Reading about hooks in the documentation makes me think that I have a conceptual misunderstanding about the manner and sequence in which code in mymode.el is executed. Specifically, what is the difference between putting (run-hooks... in (define-derived-mode ... vs putting (run-hooks... somewhere in the mode's code (as I have done above)?

If you've got the run-hooks inside the mode declaration, then the hooks
won't run until the user activates the mode in some particular buffer.
They will then run *every* time your mode is activated.

If you've got it at the top level of the file, the hooks will run once,
*while* the file is being loaded for the first time: ie quite likely
during emacs startup, possibly before the user's relevant customization
is loaded.

They won't run again later, when the user calls `add-user-content',
because all `add-user-content' does is add to the hook, it doesn't run
the hook again.

From what I can see from your examples above, it might be enough just to
have:

(defvar content-list '(default values))

(define-derived-mode 'your-mode
  ....
  (mapc 'create-constructs content-list)

(defun add-user-content (input)
  (add-to-list 'content-list input))

Without any hooks at all.

When the file is loaded, these functions are defined, but no constructs
are created. After the file is loaded, the user's customizations are
loaded, including possible calls to `add-user-content', which put new
values into `content-list'. Then, *every time* the user activates this
mode, constructs are created out of whatever's in `content-list'.

Now your new problem is, do you want new constructs created every time
the mode is activated? Will that create duplicate/extraneous constructs?
Perhaps you could use a buffer-local variable to store the constructs,
so that each buffer has its own list.

Anyway, if you do go the hook route, remember that it won't make much
sense to call `run-hooks' at the top level of the file. That's pretty
much always done in the mode declaration. Hooks are meant to store
functions to be run later, when something else happens. If you put it at
the top level of the file, it will only happen on load, in which case
you might as well just call whatever the function is directly.

Hope that didn't make it worse,
Eric




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Adding and running a major mode hook
       [not found] ` <mailman.107.1398568207.1147.help-gnu-emacs@gnu.org>
@ 2014-04-27 11:56   ` Jacob Gerlach
  2014-04-27 12:10     ` Jacob Gerlach
  2014-04-29  0:45     ` Eric Abrahamsen
  0 siblings, 2 replies; 6+ messages in thread
From: Jacob Gerlach @ 2014-04-27 11:56 UTC (permalink / raw)
  To: help-gnu-emacs

> If you've got the run-hooks inside the mode declaration, then the hooks
> 
> won't run until the user activates the mode in some particular buffer.
> 
> They will then run *every* time your mode is activated.
> 
> 
> 
> If you've got it at the top level of the file, the hooks will run once,
> 
> *while* the file is being loaded for the first time: ie quite likely
> 
> during emacs startup, possibly before the user's relevant customization
> 
> is loaded, probably before any relevant file are opened.

Ahhh, this is the key piece of information that I was missing. I was confused by the fact that the mode declaration wasn't bothered by the fact that it came before the function definitions further on in the file.

> >From what I can see from your examples above, it might be enough just to
> 
> have:
> [...]
> Then, *every time* the user activates this
> 
> mode, constructs are created out of whatever's in `content-list'.
 
The creation uses add-to-list, which checks for duplicates, so that won't be a problem necessarily, but it does seem like unnecessary overhead that I can get rid of. I will play with some conditionals to see what I can do about this.

> Hope that didn't make it worse,
On the contrary, much clearer now!

To add a wrinkle to this, can someone explain how autoload changes this sequence? I tried to implement autoload by putting something like this in my file:

(autoload 'my-mode "my-name" "My Editing Mode" t)

I copied it from somewhere, but now that I read the documentation more carefully, I think I have two problems with this:

First, "my-name" should actually be the filename: "mymode.el". Does this argument care about paths?
Second, I put this line after the mode definition, but the help says:

If FUNCTION is already defined other than as an autoload,
this does nothing and returns nil.

So I think it's doing nothing (and perhaps that's why it doesn't matter that I didn't include the file name as I should have). It also seems it would be much easier to make the mode autoloaded using a magic comment, which is how I'm fixing it.

With regards to the order of code execution, how does autoloading the mode definition change what Eric already described? Users will still have(require 'my-mode) in their .emacs, which I think executes everything except the mode definition.

Is it then redundant to put autoload on a function definition?


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Adding and running a major mode hook
  2014-04-27 11:56   ` Jacob Gerlach
@ 2014-04-27 12:10     ` Jacob Gerlach
  2014-04-29  0:45     ` Eric Abrahamsen
  1 sibling, 0 replies; 6+ messages in thread
From: Jacob Gerlach @ 2014-04-27 12:10 UTC (permalink / raw)
  To: help-gnu-emacs

> Is it then redundant to put autoload on a function definition?
I meant redundant on a mode definition!


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Adding and running a major mode hook
  2014-04-27 11:56   ` Jacob Gerlach
  2014-04-27 12:10     ` Jacob Gerlach
@ 2014-04-29  0:45     ` Eric Abrahamsen
  1 sibling, 0 replies; 6+ messages in thread
From: Eric Abrahamsen @ 2014-04-29  0:45 UTC (permalink / raw)
  To: help-gnu-emacs

Jacob Gerlach <jacobgerlach@gmail.com> writes:

>> If you've got the run-hooks inside the mode declaration, then the hooks
>> 
>> won't run until the user activates the mode in some particular buffer.
>> 
>> They will then run *every* time your mode is activated.
>> 
>> 
>> 
>> If you've got it at the top level of the file, the hooks will run once,
>> 
>> *while* the file is being loaded for the first time: ie quite likely
>> 
>> during emacs startup, possibly before the user's relevant customization
>> 
>> is loaded, probably before any relevant file are opened.
>
> Ahhh, this is the key piece of information that I was missing. I was
> confused by the fact that the mode declaration wasn't bothered by the
> fact that it came before the function definitions further on in the
> file.
>
>> >From what I can see from your examples above, it might be enough just to
>> 
>> have:
>> [...]
>> Then, *every time* the user activates this
>> 
>> mode, constructs are created out of whatever's in `content-list'.
>  
> The creation uses add-to-list, which checks for duplicates, so that
> won't be a problem necessarily, but it does seem like unnecessary
> overhead that I can get rid of. I will play with some conditionals to
> see what I can do about this.
>
>> Hope that didn't make it worse,
> On the contrary, much clearer now!
>
> To add a wrinkle to this, can someone explain how autoload changes this sequence? I tried to implement autoload by putting something like this in my file:
>
> (autoload 'my-mode "my-name" "My Editing Mode" t)
>
> I copied it from somewhere, but now that I read the documentation more carefully, I think I have two problems with this:
>
> First, "my-name" should actually be the filename: "mymode.el". Does
> this argument care about paths?

`autoload' uses `load', which searches for files in your 'load-path. If
the file you want to load isn't in your load-path, you can give an
absolute path, but that's probably a bad idea. You don't need the ".el"
suffix -- load will try with ".el", ".elc" and no suffix. (see
'load-suffixes)

> second, I put this line after the mode definition, but the help says:
>
> If FUNCTION is already defined other than as an autoload,
> this does nothing and returns nil.
>
> So I think it's doing nothing (and perhaps that's why it doesn't
> matter that I didn't include the file name as I should have). It also
> seems it would be much easier to make the mode autoloaded using a
> magic comment, which is how I'm fixing it.
>
> With regards to the order of code execution, how does autoloading the
> mode definition change what Eric already described? Users will still
> have(require 'my-mode) in their .emacs, which I think executes
> everything except the mode definition.
>
> Is it then redundant to put autoload on a function definition?

It's redundant to have an autoload for a function that is defined in the
same file, yes. autoloads should be put elsewhere, either in the user's
configuration or in other libraries that might theoretically depend on
your library.

Users will either use require, or autoload, but not both. Require means
"load it now" (ie the whole file is executed, probably at emacs
startup), and autoload means "load it the first time I try to use it",
which probably happens as a relevant file is being opened. Practically
speaking that's the only difference.

HTH,
Eric




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-04-29  0:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-26 17:25 Adding and running a major mode hook Jacob Gerlach
2014-04-27  3:12 ` Eric Abrahamsen
2014-04-27  5:15 ` Eric Abrahamsen
     [not found] ` <mailman.107.1398568207.1147.help-gnu-emacs@gnu.org>
2014-04-27 11:56   ` Jacob Gerlach
2014-04-27 12:10     ` Jacob Gerlach
2014-04-29  0:45     ` Eric Abrahamsen

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.