spacemacs icon indicating copy to clipboard operation
spacemacs copied to clipboard

support XDG Base Directory Specification

Open thkoch2001 opened this issue 10 years ago • 19 comments

The XDG Base Directory Specification proposes where to store configuration, data and cache files. Basically spacemacs config should go to $HOME/.config/spacemacs, cache files to $HOME/.cache/spacemacs and data (like backup files) into $HOME/.local/share/spacemacs.

This scheme has a few advantages:

  • It avoids pollution of $HOME with dotdirs
  • It makes it simpler to thread different kinds of files different: don't backup cache files, make sure all config files are version controlled and auto-committed on change, keep cache files in a ramdisk, ...
  • A user knows immediately which files are configuration files and which ones shouldn't be touched.

It would be nice of course, if spacemacs could add $HOME/.config/spacemacs as a fallback place to look for its configuration.

Maybe you don't want to do this. In this case please make it possible at least to configure spacemacs in the way described above. It would be enough, if I could provide environment variables to override the default directories defined in core-load-paths.el:

spacemacs constant current value why make it configurable
spacemacs-info-directory spacemacs-core-directory "info/" Hopefully there will be distribution packages of spacemacs soon. Then the docs will not be in the users homedir anymore.
spacemacs-release-notes-directory spacemacs-info-directory "release-notes/" see info-directory, also docs, banners?
spacemacs-cache-directory user-emacs-directory ".cache/" for xdg compliance, see above
spacemacs-auto-save-directory spacemacs-cache-directory "auto-save/" that's not cache data but important data to backup and my not reside on a ramdisk

thkoch2001 avatar Oct 29 '15 11:10 thkoch2001

I am highly supporting this. More over, $XDG_CONFIG_HOME/spacemacs can be used as default directory for private layers.

Update

Also note that Spacemacs supports SPACEMACSDIR environment variable. So you can set it to $XDG_CONFIG_HOME/spacemacs.

d12frosted avatar Oct 30 '15 06:10 d12frosted

I just found out about the XDG spec, and this is a huge issue. I know my home directory is completely cluttered by tons of config files, and if more apps followed this spec everything would be better.

andrew-kennedy avatar Feb 14 '16 02:02 andrew-kennedy

So, I've been having some fun with this.

user-emacs-directory (~/.emacs.d)

You can change user-emacs-directory in a leim-list.el file dropped into the default load path (e.g., /usr/share/emacs/site-lisp/leim-list.el). This is a horrible hack but this variable needs to be set really early to avoid creating the default user-emacs-directory. site-lisp.el is the correct place to put this but it's to late by the time it gets loaded.

Code (/usr/share/emacs/site-lisp/leim-list.el):

(require 'xdg) ; requires emacs 26

;; If ~/.emacs.d exists, prefer it for compatibility.
(unless (file-exists-p user-emacs-directory)
  (setq user-emacs-directory (concat (file-name-as-directory (xdg-data-home)) "emacs/")))

;; Always put the socket in the right place.
;; TODO: Figure out how to get `emacsclient' to check this directory.
(setq server-socket-dir (concat (file-name-as-directory (xdg-runtime-dir)) "emacs/"))

spacemacs

I've configured default.el to load spacemacs if no other init file is loaded.

Code (/usr/share/emacs/site-lisp/default.el):

(when (= (aref user-init-file 0) ?~) ; this isn't expanded when it doesn't exist.
  (require 'xdg)

  ;; TODO: Handle `init-file-user'? That's the hack that makes emacs load the
  ;; "real" user's profile when run as root. Really, we might just want to bail if it's set.

  (let ((user-init-file-xdg (concat (file-name-as-directory (xdg-config-home)) "emacs/init.el")))

    ; deep magic
    (setq user-init-file t)

    (cond

     ;; Try emacs xdg
     ((progn
        (load user-init-file-xdg t t t)
        (not (eq user-init-file t)))
      t)

     ;; Try spacemacs
     ((progn
        ;; TODO: Spacemacs should handle this internally.
        (unless (getenv "SPACEMACSDIR")
          (setenv "SPACEMACSDIR" (concat (file-name-as-directory (xdg-config-home)) "spacemacs")))

        ;; Try `$XDG_DATA_HOME/spacemacs' first, then system directories.
        (let ((dirs (xdg-data-dirs)) ; Using a system directory will cause problems with `spacemacs/private'.
              (dir (xdg-data-home)))
          (while (and dir (eq user-init-file t))
            (let ((spacemacs-start-directory (concat (file-name-as-directory dir) "spacemacs/")))
              (load (concat spacemacs-start-directory "init.el") t t t))
            (setq dir (cdr dirs))))
        (not (eq user-init-file t)))
      (setq spacemacs-start-directory (file-name-directory user-init-file)))

     ;; Ok, falling back to emacs (xdg).
     (t (setq user-init-file user-init-file-xdg))))

  ;; RMS: This is not the line you are looking for. Move along.
  (when inhibit-startup-screen
    (setq command-line-args (cons (car command-line-args) (cons "-no-splash" (cdr command-line-args))))))

One thing I'm really not happy about is the spec's lack of an XDG_STATE_DIR. That is, the spec doesn't distinguish between static data and state (c.f. /usr/share and /var/lib). In this case, it's not really an issue because I'm using $XDG_DATA_DIR/emacs as the "state" directory and $XDG_DATA_DIR/spacemacs for the spacemacs code.


This obviously doesn't correctly separate cache and state (see #7818).

Stebalien avatar Mar 21 '17 21:03 Stebalien

Note: possibly related emacs bug - https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15539 - would be nice to get your feedback on it.

ghost avatar Jul 03 '17 13:07 ghost

Looks like there is some progress being made for supporting XDG base directories in emacs. https://debbugs.gnu.org/cgi/bugreport.cgi?bug=583

abhigupta912 avatar Aug 29 '19 16:08 abhigupta912

Emacs 27 and newer now have the new XDG config support implemented.

Soundtoxin avatar May 24 '20 11:05 Soundtoxin

I'm bumping the issue as this is an important topic. I decided to give spacemacs another try due to recent emacs release :) Any chance XDG support is implemented soon and the files aren't created in home by default? Thanks

MarcinWieczorek avatar Aug 13 '20 17:08 MarcinWieczorek

Basically:

  • all ~/.spacemacs.d -> dotspacemacs-directory
  • all ~/.emacs.d -> user-emacs-directory It is mainly about Spacemacs config template text and docs.

Anton-Latukha avatar Nov 25 '20 14:11 Anton-Latukha

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please let us know if this issue is still valid!

github-actions[bot] avatar Mar 14 '22 11:03 github-actions[bot]

bump (god, stalebots are so stupid)

Soundtoxin avatar Mar 14 '22 11:03 Soundtoxin

The latest Spacemacs develop branch seems to work correctly with XDG_CONFIG_HOME when setting the SPACEMACSDIR environment variable. That environment variable sets the dotspacemacs-directory value and should make everything point at the right location.

I am going to test this more fully over the weekend, but all seems good so far.

UPDATE: I had some hard coded file locations for recentf and bookmarks in my config that caused errors, but that was easily fixed by using (concat dotspacemacs-directory "relative-path-to/filename")

Migrating to XDG_CONFIG_HOME from an existing .spacemacs.d setup

XDG_CONFIG_HOME set to $HOME/.config

$HOME/.emacs.d moved to $XDG_CONFIG_HOME/emacs (Emacs 28 finds the new location of Spacemacs emacs.d directory but is still looking for the Spacemacs configuration in either ~/.spacemacs.d or ~/.spacemacs)

SPACEMACSDIR set to $XDG_CONFIG_HOME/spacemacs and moved $HOME/.spacemacs.d to $XDG_CONFIG_HOME/spacemacs

Starting Emacs now picks up the existing Spacemacs configuration in $XDG_CONFIG_HOME/spacemacs

From the *messages* buffer I can see that the configuration files have been loaded from the correct location

Loading /home/practicalli/.config/spacemacs/init.el (source)...done
Loading /home/practicalli/.config/spacemacs/emacs-custom-settings.el (source)...done

I am using Emacs 28.1 on Ubuntu Linux, built from source with native compilation enabled.

practicalli-johnny avatar May 07 '22 13:05 practicalli-johnny

Almost 7 years later and this issue has still not been resolved. 🚩🚩🚩 I absolutely love the documentation of Spacemacs (especially compared to Doom) but the fact it does not respect XDG directory spec makes me doubt if I should get into it.

MikiVanousek avatar Jun 02 '22 13:06 MikiVanousek

This issue should have been marked as resolved 7 years ago as the first comment on this issue describes how Spacemacs supports the XDG standard (ideally with some docs)

Ironically Spacemacs has supported the XDG specification far longer than Emacs itself has supported XDG specification

I have be running Spacemacs from the XDG specification locations very successfully for a month without issue, after looking at the first comment on this issue.

Some official documentation could be contributed, especially if people are so passionate about the subject that they would otherwise not use Spacemacs.

The following content can be copied from should someone wish to make a meaningful contribution to the Spacemacs project on this topic (although it's mostly what I wrote in the previous comment - https://github.com/syl20bnr/spacemacs/issues/3589#issuecomment-1120211297 )

https://practical.li/blog/posts/adopt-FreeDesktop.org-XDG-standard-for-configuration-files/

practicalli-johnny avatar Jun 02 '22 15:06 practicalli-johnny

I believe the XDG spec states the location should be used by default. It is nice you are able to change the default home directory polluting behaviour by setting an environmental variable, not every application allows it. But it is a workaround, not following the XDG spec. I do not want to set an Envar every time I install a new app.

I agree the fact this workaround is possible should be stated more clearly in the docs.

MikiVanousek avatar Jun 03 '22 06:06 MikiVanousek

From XDG Base Directory Specification:

$XDG_CONFIG_HOME defines the base directory relative to which user-specific configuration files should be stored. If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used.

MikiVanousek avatar Jun 03 '22 06:06 MikiVanousek

Also note that Spacemacs supports SPACEMACSDIR environment variable.

Users trying to remove ~ pollution aren't too keen on polluting their environments either.

Moreover, I think many users would rather a configuration system that doesn't require logging out and back in for your session to pick it up.

This issue should have been marked as resolved 7 years ago as the first comment on this issue describes how Spacemacs supports the XDG standard (ideally with some docs)

Then how about someone make a simple to use layer for this? Or dead simple guide on how make a local modification. Contributors saying this is easy doesn't really help everyone here still lost.

cornfeedhobo avatar Dec 12 '22 17:12 cornfeedhobo

Even Emacs itself supports XDG by default now. Any chance to see similar support by default in Spacemacs?

zabbal avatar Jan 28 '23 15:01 zabbal

I believe the XDG spec states the location should be used by default.

Also, the suggested workaround doesn't make spacemacs comply with the XDG base directories spec, especially when it comes to spacemacs-cache-directory

That distinction between data and state comes from the XDG spec:

The $XDG_STATE_HOME contains state data that should persist between (application) restarts, but that is not important or portable enough to the user that it should be stored in $XDG_DATA_HOME. It may contain:

  • actions history (logs, history, recently used files, …)
  • current state of the application that can be reused on a restart (view, layout, open files, undo history, …)

I think a first step could be to introduce new API surfaces like:

  • spacemacs-{data, state}-directory, so layer authors have more-sensible options than putting everything under .cache;
  • helpers to assist with migrating data from legacy location; e.g. take a list of locations a layer's files (or directory) can be in, finds the first extent one, and either:
    • returns it as-is;
    • moves it to match the first location it was expected in, i.e. the non-legacy one;
    • returns the preferred location if none of the possible locations was populated.

nicoonoclaste avatar Oct 22 '23 15:10 nicoonoclaste