2

Because the allout.el is standard a library, rather than an optional ELPA package, to enable the it (allout minor mode) on Emacs starts for all modes can be as simple as creating a global version of the minor mode like so:

(defun my-turn-on-allout-mode-maybe ()
  "Enable `allout-mode', where applicable."
  ;; Unconditional here, but edit as desired if it turns out
  ;; that you don't actually want this for ALL modes.
  ;; (This function is called in every buffer, when the
  ;; global mode is enabled.)
  (allout-mode 1))

(define-globalized-minor-mode my-global-allout-mode allout-mode
  my-turn-on-allout-mode-maybe
  :group 'allout)

(my-global-allout-mode 1)

thanks to phils' answer from How to redefine the allout prefix keybinding.

Now I have two questions.

Question #1, suppose, just suppose, because I don't know emacs well to give another good example, that allout-mode is a minor mode from ELPA that I installed myself. How to enable it in this case? Would the above still be good?

My main confusing is about timing. From http://www.emacswiki.org/emacs/ELPA#toc6, it says,

Whenever Emacs starts up, it automatically calls the function ‘package-initialize’ to load installed packages. This is done after loading the init file... So packages are initialized AFTER the init.el is loaded. This means you should NOT put package specific initialization into your init.el except...

So if the installed packages are loaded after loading the init file, then how can I enable them in the init file, when the package is not loaded yet? Would the above still be good?

I meant, once the ELPA packages are installed locally, they would behave exactly like any other locally available library (either from system or from person libs), right? They normally would be required, which means loading a package if it has not already been loaded. The system library are normally autoloaded, which means loading a file only when a function is called. I don't think the ELPA packages cannot be autoloaded, correct? So my anwser would be, the above will still be good, is that correct?

Question #2, now that with above code I've turn the minor mode into a global mode, how to disable it for a specific mode, say markdown-mode?

I tired this

(use-package markdown-mode
  :mode ("\\.\\(txt\\|markdown\\|md\\)\\(\\'\\|\\.\\)" . gfm-mode)
  :init
  (progn
    (flyspell-mode 1)
    (allout-mode -1)
    ))

but the allout-mode is still on when I open a markdown file.

UPDATE, for the record, for all my questions, I gather all the answers to here.

  • The wiki page you linked to has the answer to your question, it's about 10cm down from where you stopped reading. – tarsius Jan 5 '15 at 21:13
  • Then also view the official documentation gnu.org/software/emacs/manual/html_node/emacs/… (linked to on the wiki page). It also explains why it is done this way. – tarsius Jan 5 '15 at 21:31
  • 1
    Also covered in this Emacs.SE thread and this S.O. thread. – Dan Jan 5 '15 at 22:00
  • As you can see tarsius, I'm still putting pieces together, and have used the wrong example to back up my own question because I've already overwhelmed by the info I need to grok. Accusing me of not reading enough might not be the best way to help. But thanks anyway. – xpt Jan 5 '15 at 22:53
  • I've changed your title to match the accepted answer. The old title was just a duplicate of the question linked by Dan. – Malabarba Jan 6 '15 at 2:42
3

"Package" refers explicitly to ELPA packages, which are installed via the package manager (e.g. M-x package-list-packages, M-x package-install, etc).

The allout.el library appears to be standard issue, rather than an optional ELPA package, and allout-mode itself is autoloaded on-demand, so you should be able to use that code anywhere in your init file. Packages are not involved here.

Edit:

Regarding additional Q1, please refer to the Q&A that Dan already pointed you to in the comments: https://stackoverflow.com/questions/11127109/emacs-24-package-system-initialization-problems. The accepted answer to that question will forcibly initialise the package system if you place it in your init file (prior to any code which uses a package). Then you can stop worrying about the timing of package initialisation.

The autoload declarations for ELPA packages aren't known to Emacs until package initialisation has taken place, so regardless of whether a package provides autoloaded functions or not, you can't call those functions before package initialisation. Autoloading simply means that you don't also need to require (or otherwise explicitly load) a library if there are known autoload declarations for the functions you are calling.

Your additional Q2 was, of course, why I wrote:

(defun my-turn-on-allout-mode-maybe ()
  "Enable `allout-mode', where applicable."
  ;; Unconditional here, but edit as desired if it turns out
  ;; that you don't actually want this for ALL modes.
  ;; (This function is called in every buffer, when the
  ;; global mode is enabled.)
  (allout-mode 1))

which you can change to something like:

(defun my-turn-on-allout-mode-maybe ()
  "Enable `allout-mode', where applicable."
  ;; (This function is called in every buffer, when the
  ;; global mode is enabled.)
  (unless (memq major-mode '(markdown-mode some-other-mode a-third-mode))
    (allout-mode 1)))
  • Thank you phils for your kind answer. As you can see, I'm still putting pieces together, and have used the wrong example to back up my question. Anyway. Thanks. – xpt Jan 5 '15 at 22:47
  • 1
    No problem -- there's a lot of information to take in. Be aware that ELPA packages are quite a recent development in Emacs (included as a default feature only since version 24.1), so while the number of available packages has been growing at an impressive rate, there's still a vast quantity of non-package elisp libraries available (or built-in, of course). So although the information you've read about packages is very important, it's also extremely common for the things you configure to not be packages. – phils Jan 5 '15 at 23:36
  • temporarily change to unanswered to draw attention... – xpt Jan 11 '15 at 3:49
  • Thank you @phils, as always. I'm not a elisp developer at all, so your explicit code sample really helps! – xpt Jan 11 '15 at 14:44
2

The use-package example you give has a number of issues. First of all, the :init section is run unconditionally at startup time, so what you're really doing is enabling flyspell mode and disabling allout mode in all buffers always with the code as given (and then assuming your (my-global-allout-mode 1) comes after that part, then it would be re-enabled and indeed it would seem like it's "not working".

The thing you need to learn about in order to configure anything on a per-mode basis is called hooks. A hook is a variable that contains a list of functions to run at a particular time. In particular, markdown-mode-hook is a hook that will run when entering markdown mode. That is the place that you're going to want to put code that should only run in markdown mode. Here's an example (untested, but it should work):

(use-package markdown-mode
  :mode ("\\.\\(txt\\|markdown\\|md\\)\\(\\'\\|\\.\\)" . gfm-mode)
  :config  ; runs after the mode is loaded
  (progn (add-hook 'markdown-mode-hook 'flyspell-mode)
         (add-hook 'markdown-mode-hook 'allout-mode)))

(this assumes that flyspell-mode and allout-mode are both buffer-local toggles, which you should probably confirm for yourself. If they turn out to be global toggles then you'll find this has really strange behavior, like flyspell mode will be disabled for all buffers until you open a markdown file, then it's enabled for all buffers).

  • Thank you @Robru, up-voting your answer. You do know that I want to disable allout mode in markdown-mode right? – xpt Jan 11 '15 at 14:46
  • Robru: Take note that Emacs 24.1 introduced a change such that "Passing a nil argument to a minor mode function call now ENABLES the minor mode unconditionally. This is so that you can write e.g. (add-hook 'text-mode-hook 'foo-mode)". So it's no longer possible to toggle modes that way in code (which I think is generally a good thing :) – phils Jan 11 '15 at 20:20
  • 1
    Ah, oops, didn't realize they weren't toggles anymore. @xpt, you'll need to write a lambda then that disables allout mode. Something like (add-hook 'markdown-mode-hook (lambda () (allout-mode -1))) (untested). – robru Jan 13 '15 at 22:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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