8

After packages have been updated, the location of the loaded elisp files will change to be in the folder of the new version of the package.

Yasnippet attempts to lazily load snippets for the file it was installed it, when I open a file in a major mode yasnippet hasn't seen before.

This means that loading things with previously unseen major modes once emacs has been updated fails, because yasnippet breaks the whole thing by complaining about "no such file or directory".

Is there a good general way to solve this, such as not letting updates break things? (I get a similar but less tedious problem when ag is updated). Alternatively, would advising something in yasnippet to just swallow the errors so it merely warns instead of erroring when it couldn't load packages be a better plan?

Clarification:

  • I start emacs, and yasnippet is loaded.
  • I load no files whose major mode is (for example) makefiles.
  • I update to a new version of yasnippet, using the package manager
  • I load a makefile, and yasnippet attempts to load the snippets for makefiles but it fails, because the folder it was using for snippets no longer exists. Not only that, but practically every other command fails, because the pre-hook to them that yasnippet installed fails.
  • Workaround: Open the message buffer, find which folder cannot be opened and run mkdir ~/.blargh/folder-yasnippet-wants.

Clearly, one could could write some advice for some bit of yasnippet, but I'm hoping for a more global solution (and it'd take a while of playing with elisp to get the advice to work I'm sure).

Squidly
  • 1,499
  • 14
  • 17
  • Please explain your problem more clearly: which path is found missing? After updating YASnippet or after updating something else? What configuration do you have in your Emacs init file? – Lorenzo Gatti Nov 11 '14 at 17:11
  • I realize you just want `package.el` to work flawlessly and you are probably looking for a solution in relation thereto. I personally become unglued when things break, so I reduce the probability of breakage by placing libraries in a completely different location -- in some cases, I even change all the names by adding a prefix in the library -- e.g., `lawlist-...` That way, nothing breaks except a modified function by the Emacs team -- e.g., a new argument to an existing function, etc. I copied `yasnippet.el` somewhere else, removed it from the package manager, and never worry about it. – lawlist Nov 11 '14 at 18:15
  • File an issue. This is something that can be fixed within Yasnippet, AFAICT. – Dmitry Nov 12 '14 at 13:51
  • @Dmitry Waaaay ahead of you. See [#495](https://github.com/capitaomorte/yasnippet/issues/495). – Sean Allred Nov 13 '14 at 18:05
  • @SeanAllred Huh, indeed. So, the problem is fixed in master already? – Dmitry Nov 13 '14 at 19:42
  • @Dmitry It would seem so. I have yet to try out the fix, though -- I unfortunately managed to get in the habit of disabling `yas-global-mode` when I update packages. – Sean Allred Nov 13 '14 at 19:58

1 Answers1

1

What I do is a little complex: I advise the function package-activate such that every time a package is activated, Emacs will look for a file called [package]-conf.el and execute it using load instead of require, so it can be executed multiple times.

(defun kzn-package-dir (package)
  "Return the full path of the directory where the package is installed."
  (interactive)
  (let ((desc (cadr (assq package package-alist))))
    (if desc
        (package-desc-dir desc))))

(defadvice package-activate (after kzn-package-activate-load-conf activate)
  "Load kzn/<package.el> file after the package is activated."
  (let* ((package-name (symbol-name package))
         (dir (kzn-package-dir package))
         (pkg-conf (kzn-path :lisp (concat (file-name-as-directory "pkg-confs") package-name "-conf.el"))))
    (if ad-return-value
        (progn
          (message (concat package-name ": activated (dir: " dir ")"))
          (if (file-exists-p pkg-conf)
              (progn
                (message (concat "loading package configuration file: '" pkg-conf "'"))
                (load pkg-conf))))
      (message (concat package-name ": couldn't be activated with dir: " dir )))))

And in my pkg-configs/yasnippet-conf.el, I set the yas-snippet-dirs variable to point where the yasnippet package is:

(setq yas-snippet-dirs
      `(,(kzn-path :emacsd "snippets")
        ,(concat (file-name-as-directory (kzn-package-dir 'yasnippet)) "snippets")
        ,(kzn-path :vendor "yasnippets-rails/rails-snippets")
        ,(kzn-path :vendor "yasnippets-shoulda")))

kzn-path is a function I use to find my custom directories by symbol; you can replace it for directories.

All of this is copied directly from my configuration files. I think it's every thing you need, or it should at least point you in the right direction.

itsjeyd
  • 14,586
  • 3
  • 58
  • 87