Skip to content

Commit

Permalink
Use XDG conventions more consistently
Browse files Browse the repository at this point in the history
Fit in better with the XDG conventions.
Something like this was suggested in 2008 (Bug#583)
and the XDG conventions seem to have settled down by now.
* doc/emacs/custom.texi (Init File, Init Syntax, Find Init):
* doc/lispref/files.texi (Standard File Names):
* doc/lispref/os.texi (Init File):
* doc/misc/url.texi (Customization):
* etc/NEWS:
Adjust accordingly.
* lisp/startup.el (startup--load-user-init-file):
If init-file-name is nil, do not load from it; instead
just use the alt-file.
(find-init-path): Remove; no longer used.
(command-line): Don't check twice for XDG.
Look at XDG_CONFIG_HOME instead of assuming it's ~/.config.
Prefer XDG configuration if it exists; the user can disable
this by setting XDG_CONFIG_HOME to some other place.
* lisp/subr.el (user-emacs-directory):
Prefer XDG configuration if it exists.
  • Loading branch information
eggert committed Aug 27, 2019
1 parent fa41fa7 commit 4118297
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 55 deletions.
52 changes: 27 additions & 25 deletions doc/emacs/custom.texi
Expand Up @@ -2220,28 +2220,33 @@ as a function from Lisp programs.
@cindex init file
@cindex .emacs file
@cindex ~/.emacs file
@cindex ~/.config/emacs file
@cindex ~/.config/emacs/init.el file
@cindex Emacs initialization file
@cindex startup (init file)
@cindex XDG_CONFIG_HOME

When Emacs is started, it normally tries to load a Lisp program from
an @dfn{initialization file}, or @dfn{init file} for short. This
file, if it exists, specifies how to initialize Emacs for you. Emacs
looks for your init file using the filenames
@file{~/.config/emacs},. @file{~/.emacs}, @file{~/.config/emacs.el},
@file{~/.emacs.el}, @file{~/.config/emacs.d/init.el} or
@file{~/.emacs.d/init.el}; you can choose to use any one of these
names (@pxref{Find Init}). Here, @file{~/} stands for your home
file, if it exists, specifies how to initialize Emacs for you.
If the directory @file{@var{xdghome}/.config/emacs} exists, Emacs uses
@file{@var{xdghome}/.config/emacs/init.el} as the init file. Here,
@var{xdghome} stands for the value of the environment variable
@env{XDG_CONFIG_HOME}, or for @file{~/.config} if
@env{XDG_CONFIG_HOME} is unset; @file{~/} stands for your home
directory.

While the @file{~/.emacs} and @file{~/.emacs.d/init.el} locations
are backward-compatible to older Emacs versions, and the rest of this
chapter will use them to name your initialization file, it is better practice
to group all of your dotfiles under @file{.config} so that if you have
If @file{~/.config/emacs} does not exist, Emacs looks for your init
file using the filenames @file{~/.emacs}, @file{~/.emacs.el}, or
@file{~/.emacs.d/init.el}; you can choose to use any one of these
names (@pxref{Find Init}). Although this is backward-compatible
with older Emacs versions, modern POSIX platforms prefer putting your
initialization files under @file{.config} so that if you have
to troubleshoot a problem that might be due to a bad init file, or
archive a collection of them, it can be done by renaming or
copying that directory. Note that the @file{.config} versions
don't have a leading dot on the basename part of the file.
For convenience the rest of this section assumes @env{XDG_CONFIG_HOME}
is unset or has a value equivalent to @file{~/.config}.

You can use the command line switch @samp{-q} to prevent loading
your init file, and @samp{-u} (or @samp{--user}) to specify a
Expand Down Expand Up @@ -2313,17 +2318,17 @@ function @code{setq} to set the variable @code{fill-column}

You can set any Lisp variable with @code{setq}, but with certain
variables @code{setq} won't do what you probably want in the
@file{.emacs} file. Some variables automatically become buffer-local
when set with @code{setq}; what you want in @file{.emacs} is to set
init file. Some variables automatically become buffer-local
when set with @code{setq}; what you want in the init file is to set
the default value, using @code{setq-default}. Some customizable minor
mode variables do special things to enable the mode when you set them
with Customize, but ordinary @code{setq} won't do that; to enable the
mode in your @file{.emacs} file, call the minor mode command. The
mode in your init file, call the minor mode command. The
following section has examples of both of these methods.

The second argument to @code{setq} is an expression for the new
value of the variable. This can be a constant, a variable, or a
function call expression. In @file{.emacs}, constants are used most
function call expression. In the init file, constants are used most
of the time. They can be:

@table @asis
Expand Down Expand Up @@ -2646,15 +2651,12 @@ library. @xref{Hooks}.
@node Find Init
@subsection How Emacs Finds Your Init File

Normally Emacs uses your home directory to find
@file{~/.config/emacs} or @file{~/.emacs}; that's what @samp{~} means
in a file name. @xref{General Variables, HOME}. If none of
@file{~/.config/emacs}, @file{~/.emacs}, @file{~/.config/emacs.el} nor
@file{~/.emacs.el} is found, Emacs looks for
@file{~/.config/emacs.d/init.el} or @file{~/.emacs.d/init.el} (these,
like @file{~/.emacs.el}, can be byte-compiled).
Emacs normally finds your init file in a location under your home
directory, e.g., @file{~/.config/emacs/init.el} or
@file{~/.emacs.d/init.el}. @xref{Init File}.

However, if you run Emacs from a shell started by @code{su}, Emacs
However, if you run Emacs from a shell started by @code{su} and
@env{XDG_CONFIG_HOME} is not set in your environment, Emacs
tries to find your own initialization files, not that of the user you are
currently pretending to be. The idea is that you should get your own
editor customizations even if you are running as the super user.
Expand Down Expand Up @@ -2705,8 +2707,8 @@ Type @kbd{C-q}, followed by the key you want to bind, to insert @var{char}.
@subsection The Early Init File
@cindex early init file

Most customizations for Emacs should be put in the normal init file,
@file{.config/emacs} or @file{~/.config/emacs.d/init.el}. However, it is sometimes desirable
Most customizations for Emacs should be put in the normal init file.
@xref{Init File}. However, it is sometimes desirable
to have customizations that take effect during Emacs startup earlier than the
normal init file is processed. Such customizations can be put in the early
init file, @file{~/.config/emacs.d/early-init.el} or @file{~/.emacs.d/early-init.el}. This file is loaded before the
Expand Down
5 changes: 3 additions & 2 deletions doc/lispref/files.texi
Expand Up @@ -2822,8 +2822,9 @@ filter out a directory named @file{foo.elc}.
name for a particular use---typically, to hold configuration data
specified by the current user. Usually, such files should be located
in the directory specified by @code{user-emacs-directory}, which is
@file{~/.emacs.d} by default (@pxref{Init File}). For example, abbrev
definitions are stored by default in @file{~/.emacs.d/abbrev_defs}.
@file{~/.config/emacs} or @file{~/.emacs.d} by default (@pxref{Init
File}). For example, abbrev definitions are stored by default in
@file{~/.config/emacs/abbrev_defs} or @file{~/.emacs.d/abbrev_defs}.
The easiest way to specify such a file name is to use the function
@code{locate-user-emacs-file}.

Expand Down
7 changes: 5 additions & 2 deletions doc/lispref/os.texi
Expand Up @@ -473,8 +473,11 @@ the value refers to the corresponding source file.
@end defvar

@defvar user-emacs-directory
This variable holds the name of the @file{.emacs.d} directory. It is
@file{~/.emacs.d} on all platforms but MS-DOS.
This variable holds the name of the Emacs default directory.
It is @file{@var{xdghome}/emacs/} if that directory exists, otherwise
@file{~/.emacs.d/} on all platforms but MS-DOS. Here, @var{xdghome}
stands for the value of the environment variable @env{XDG_CONFIG_HOME}
if that variable is set, and for @file{~/.config} otherwise.
@end defvar

@node Terminal-Specific
Expand Down
3 changes: 2 additions & 1 deletion doc/misc/url.texi
Expand Up @@ -1267,7 +1267,8 @@ files, etc.

The default value specifies a subdirectory named @file{url/} in the
standard Emacs user data directory specified by the variable
@code{user-emacs-directory} (normally @file{~/.emacs.d}). However,
@code{user-emacs-directory} (normally @file{~/.config/emacs}
or @file{~/.emacs.d}). However,
the old default was @file{~/.url}, and this directory is used instead
if it exists.
@end defopt
Expand Down
9 changes: 9 additions & 0 deletions etc/NEWS
Expand Up @@ -132,6 +132,15 @@ builds respectively.

* Startup Changes in Emacs 27.1

+++
** Emacs now uses the XDG convention for init files.
For example, it looks for init.el in ~/.config/emacs/init.el.
Emacs continues to look for init files in their traditional locations
if ~/.config/emacs does not exist. The XDG_CONFIG_HOME environment
variable (default ~/.config) specifies the parent directory of these
configuration files, so invoking Emacs with XDG_CONFIG_HOME='/nowhere'
might be useful if your new-location init files are scrambled.

+++
** Emacs can now be configured using an early init file.
The file is called 'early-init.el', in 'user-emacs-directory'. It is
Expand Down
48 changes: 27 additions & 21 deletions lisp/startup.el
@@ -1,4 +1,4 @@
;; startup.el --- process Emacs shell arguments -*- lexical-binding: t -*-
;;; startup.el --- process Emacs shell arguments -*- lexical-binding: t -*-

;; Copyright (C) 1985-1986, 1992, 1994-2019 Free Software Foundation,
;; Inc.
Expand Down Expand Up @@ -906,16 +906,19 @@ init-file, or to a default value if loading is not possible."
;; the name of the file that it loads into
;; `user-init-file'.
(setq user-init-file t)
(load (if (equal (file-name-extension init-file-name)
"el")
(file-name-sans-extension init-file-name)
init-file-name)
'noerror 'nomessage)
(when init-file-name
(load (if (equal (file-name-extension init-file-name)
"el")
(file-name-sans-extension init-file-name)
init-file-name)
'noerror 'nomessage))

(when (and (eq user-init-file t) alternate-filename-function)
(let ((alt-file (funcall alternate-filename-function)))
(and (equal (file-name-extension alt-file) "el")
(setq alt-file (file-name-sans-extension alt-file)))
(unless init-file-name
(setq init-file-name alt-file))
(load alt-file 'noerror 'nomessage)))

;; If we did not find the user's init file, set
Expand Down Expand Up @@ -971,18 +974,10 @@ the `--debug-init' option to view a complete error backtrace."
(when debug-on-error-should-be-set
(setq debug-on-error debug-on-error-from-init-file))))

(defun find-init-path (fn)
"Look in ~/.config/FOO or ~/.FOO for the dotfile or dot directory FOO.
It is expected that the output will undergo ~ expansion. Implements the
XDG convention for dotfiles."
(let* ((xdg-path (concat "~" init-file-user "/.config/" fn))
(oldstyle-path (concat "~" init-file-user "/." fn))
(found-path (if (file-exists-p xdg-path) xdg-path oldstyle-path)))
found-path))

(defun command-line ()
"A subroutine of `normal-top-level'.
Amongst another things, it parses the command-line arguments."
(let (xdg-dir startup-init-directory)
(setq before-init-time (current-time)
after-init-time nil
command-line-default-directory default-directory)
Expand Down Expand Up @@ -1171,6 +1166,18 @@ please check its value")
init-file-user))
:error))))

;; Calculate the name of the Emacs init directory.
;; This is typically equivalent to ~/.config/emacs if the user is
;; following the XDG convention, and is ~INIT-FILE-USER/.emacs.d
;; on other systems.
(setq xdg-dir
(let* ((dir (concat (or (getenv "XDG_CONFIG_HOME")
(concat "~" init-file-user "/.config"))
"/emacs/")))
(if (file-exists-p dir) dir)))
(setq startup-init-directory
(or xdg-dir (concat "~" init-file-user "/.emacs.d/")))

;; Load the early init file, if found.
(startup--load-user-init-file
(lambda ()
Expand All @@ -1180,8 +1187,7 @@ please check its value")
;; with the .el extension, if the file doesn't exist, not just
;; "early-init" without an extension, as it does for ".emacs".
"early-init.el"
(file-name-as-directory
(find-init-path "emacs.d")))))
startup-init-directory)))
(setq early-init-file user-init-file)

;; If any package directory exists, initialize the package system.
Expand Down Expand Up @@ -1319,10 +1325,11 @@ please check its value")
(startup--load-user-init-file
(lambda ()
(cond
(xdg-dir nil)
((eq system-type 'ms-dos)
(concat "~" init-file-user "/_emacs"))
((not (eq system-type 'windows-nt))
(find-init-path "emacs"))
(concat "~" init-file-user "/.emacs"))
;; Else deal with the Windows situation.
((directory-files "~" nil "^\\.emacs\\(\\.elc?\\)?$")
;; Prefer .emacs on Windows.
Expand All @@ -1339,8 +1346,7 @@ please check its value")
(lambda ()
(expand-file-name
"init"
(file-name-as-directory
(find-init-path "emacs.d"))))
startup-init-directory))
(not inhibit-default-init))

(when (and deactivate-mark transient-mark-mode)
Expand Down Expand Up @@ -1456,7 +1462,7 @@ Consider using a subdirectory instead, e.g.: %s"
(if (and (boundp 'x-session-previous-id)
(stringp x-session-previous-id))
(with-no-warnings
(emacs-session-restore x-session-previous-id))))
(emacs-session-restore x-session-previous-id)))))

(defun x-apply-session-resources ()
"Apply X resources which specify initial values for Emacs variables.
Expand Down
13 changes: 9 additions & 4 deletions lisp/subr.el
Expand Up @@ -2938,10 +2938,15 @@ This hook is normally set up with a function to put the buffer in Help
mode.")

(defconst user-emacs-directory
(if (eq system-type 'ms-dos)
;; MS-DOS cannot have initial dot.
"~/_emacs.d/"
"~/.emacs.d/")
(let ((config-dir (concat (or (getenv-internal "XDG_CONFIG_HOME")
"~/.config")
"/emacs/")))
(if (file-exists-p config-dir)
config-dir
(if (eq system-type 'ms-dos)
;; MS-DOS cannot have initial dot.
"~/_emacs.d/"
"~/.emacs.d/")))
"Directory beneath which additional per-user Emacs-specific files are placed.
Various programs in Emacs store information in this directory.
Note that this should end with a directory separator.
Expand Down

0 comments on commit 4118297

Please sign in to comment.