Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emacs setq before loading

When customizing Emacs, do I set the corresponding variable before loading a package or after?

i.e.,

(setq some-variable some-value)
(require 'some-package)

or

(require 'some-package)
(setq some-variable some-value)

Seems to me that most of the time both work except when some packages explicitly require init after load. Am I right?

like image 892
gongzhitaao Avatar asked Apr 07 '14 14:04

gongzhitaao


2 Answers

If the variable is a user option, do it before loading the package. The package contains a defcustom that defines the option, but defcustom will not set the value if the variable already has a value (e.g., from your setq).

Similarly, if the variable is a globally defined variable that is not a user option, i.e., is defined by the package using defvar. defvar, like defcustom, will not override an existing value.

On the other hand, depending on the variable, sometimes you want to change its value after the package has been loaded. It all depends on what the package does and how that variable is used.

Regardless of what I've said above, IMO it is generally a bad idea to alter global variable values (whether options or not) using setq in your init file.

  • For an option, it is preferable to customize it using the Customize UI, or else to use one of the functions custom-set-variables or customize-set-variable in your init file (i.e., explicitly, yourself). This is because a defcustom defining an option can have "triggers" for value initialization and updating (and it can have other special handling). And a given defcustom can depend, for evaluating its default value expression, on other stuff that appears before it in the file.

    If you just use setq to initialize or update the option then you bypass any such special handling, which is probably not what you want, and which can lead to surprises.

  • Similarly, but less importantly in general, unless you are sure of what you are doing, it can be a bad idea to simply use setq on a non-option (i.e., defvar) variable.

My recommendation: Use Customize, but do not let it write to your init file. Instead, define variable custom-file (actually, it is an option, but you cannot really use it like one), so that Customize writes to that separate file and leaves your init file for you to modify manually. (You can still use customize-set-variable in your init file.)

If you do that, you need to load file custom-file from your init file. And you can decide at what point in your init file to do that, i.e., whether a given variable setting in your init file should come before or after loading custom-file (the settings that Customize manages).

like image 87
Drew Avatar answered Oct 01 '22 21:10

Drew


You are right that both cases are usually acceptable. But not always in special cases.

You must understand that for example if you set python-shell-interpreter after running *Python* process - it not change *Python* executable. You must kill *Python* buffer and run it again in order to changes have effect.

Also some variables binded on file loading depending on values of another variables. So changes to base variable doesn't propagated to derived values. Just read source code to check this.

So if you place code in .emacs both cases mostly equivalent unless mode docs say another (read about Emacs loading process in manual, at that stage Emacs doesn't process any user buffers).

But if you change variables after some buffer processing - it may not work. When Emacs process user buffers it can init/fill internal caches. It is hard to find this caches (you must read sources or docs) and understand how reset or trigger reload (set it to nil or call some mode-reinit function).

Some packages, like Gnus, allow clean unloading (gnus-group-exit), so you can load it again as if it not loaded before...

In any case I found reading Emacs sources very easy - if you have problem just look to variable/function declaration to understand how it set and what vlaues it used.

This example from my .emacs where I need tune mode before loading (so native Emacs doesn't use ; if I prefer work with Cygwin and : in INFOPATH env var):

;; Assume that cygwin-mount already activated.
(when (featurep 'cygwin-mount)
  (setenv "INFOPATH" "/usr/share/info/:~/usr/share/info/:")
  ;; Redefine path-separator to UNIX to update Info-directory-list.
  (let ( (path-separator ":") )
    (require 'info)
    (info-initialize)
    ))
like image 27
gavenkoa Avatar answered Oct 01 '22 21:10

gavenkoa