3

I'd like to keep ess as automatic major mode for R files and everything else, except for Julia, for which I want to use julia-mode alone. However, I cannot find out how to "unbind" the file association of ess-julia-mode.

Without really knowing what I do, I tried putting

 (setq auto-mode-alist (assq-delete-all "\\.jl\\'" auto-mode-alist))

at some places, but it had no effect. My package loading is essentially the following (in this order):

(use-package ess
  :init (require 'ess-site)) ;; adds association automatically

(use-package julia-mode
  :mode "\\.jl\\'")          ;; set association manually - no effect

How can I make sure that .jl files use julia-mode, while keeping the other associations from ess?

(I use use-package for package loading; but any answer dealing with the same problem in general is equally welcome. It might also be independent of ess.)

3

The issue is mostly caused by autoloads.

In julia-mode.el you can see that (add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode)) is marked as to be autoloaded. If you were to look at ~/.emacs.d/elpa/julia-mode-${version}/julia-mode-autoloads.el (which is automatically generated from julia-mode.el when you initially install the package), you would indeed see that line.

Crucially, the -autoloads.el files in all the elpa/xx/ subdirectories are, themselves, loaded automatically and at the very beginning of start-up — their purpose is to defer loading of the "real" files until they're necessary, but in order for that to be possible, they have to be loaded at start-up). Indeed, if you were to comment out your entire init-file, but without deleting any of the installed packages, auto-mode-alist would still contain ("\\.jl\\'" . julia-mode).

† well, unless you set package-enable-at-startup to nil

In contrast, ess-autoloads.el only adds '("\\.R$" . R-mode) to the auto-mode-alist (see here — yes, in the case of ess, the autoloads file is present at the source, rather than being generated at installation, but that doesn't really matter). The .jl association is, as you noted, only added in ess-julia.el.

add-to-list adds the given element to the top of the list, but only if it's not already present (see the docstring of the function). Hence, the order of operations regarding the .jl association is:

  1. ("\\.jl\\'" . julia-mode) is added from julia-mode-autoloads.el

  2. When you (require 'ess-site), which in turn requires ess-julia.el, auto-mode-alist has ("\\.jl\\'" . ess-julia-mode) added to its beginning, effectively "overriding" ("\\.jl\\'" . julia-mode)

  3. :mode "\\.jl\\'" expands to (add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode)), but since ("\\.jl\\'" . julia-mode) is already an element of auto-mode-alist, it does nothing.

‡ when opening a file, parsing of auto-mode-alist is in order, and (sort-of) stops when you find a match, so later occurrences of the same pattern have no effect

Hack-ish solution

Change the use-package block dedicated to julia-mode:

(use-package julia-mode
  :init
  (push '("\\.jl\\'" . julia-mode) auto-mode-alist)
  (delete-dups auto-mode-alist))

push, unlike add-to-list does not try to be clever and just adds the element to the beginning of the list. delete-dups removes duplicates, leaving the first occurrence (it's not strictly necessary, but I've added it for neatness's sake). As a result, ("\\.jl\\'" . julia-mode) is now before ("\\.jl\\'" . ess-julia-mode).

Why does assq-delete-all not work?

assq-delete-all uses eq rather than equal for comparison (see the docstring), but eq does not work in the "expected" way for string — e.g. (eq "a" "a") evaluates to nil.

  • 1
    The hack does everything I want, thanks! After reading your explanation, I also tried use-packages :after command (:after julia-mode in the ess part), but that had the disadvantage of still overwriting the setting after ess has been loaded once... – phipsgabler Feb 3 '18 at 14:59

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.