>From 05d573e312b840cb26fa5353cc6d74e5e3b5afd7 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 27 Jul 2019 11:38:16 -0700 Subject: [PATCH] Use XDG conventions more consistently * 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. --- doc/emacs/custom.texi | 52 ++++++++++++++++++++++-------------------- doc/lispref/files.texi | 5 ++-- doc/lispref/os.texi | 7 ++++-- doc/misc/url.texi | 3 ++- etc/NEWS | 8 +++++++ lisp/startup.el | 48 +++++++++++++++++++++----------------- lisp/subr.el | 13 +++++++---- 7 files changed, 81 insertions(+), 55 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index adea9351ea..d0c3b67f07 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -2219,28 +2219,33 @@ Init File @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 @@ -2312,17 +2317,17 @@ Init Syntax 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 @@ -2645,15 +2650,12 @@ Terminal Init @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. @@ -2704,8 +2706,8 @@ Early Init File @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 diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 6be5a52837..d53fed4ee8 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -2822,8 +2822,9 @@ Standard File Names 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}. diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index fef954eb7a..a0615004a8 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -475,8 +475,11 @@ Init 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 diff --git a/doc/misc/url.texi b/doc/misc/url.texi index 0cdfcac24e..bad7701daf 100644 --- a/doc/misc/url.texi +++ b/doc/misc/url.texi @@ -1267,7 +1267,8 @@ Customization 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 diff --git a/etc/NEWS b/etc/NEWS index d876c95e68..7703fc1e79 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -135,6 +135,14 @@ 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. + +++ ** Emacs can now be configured using an early init file. The file is called 'early-init.el', in 'user-emacs-directory'. It is diff --git a/lisp/startup.el b/lisp/startup.el index 564428580b..4d584a0cb5 100644 --- a/lisp/startup.el +++ b/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. @@ -906,16 +906,19 @@ startup--load-user-init-file ;; 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 @@ -971,18 +974,10 @@ startup--load-user-init-file (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) @@ -1171,6 +1166,18 @@ command-line 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 () @@ -1180,8 +1187,7 @@ command-line ;; 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. @@ -1319,10 +1325,11 @@ command-line (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. @@ -1339,8 +1346,7 @@ command-line (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) @@ -1456,7 +1462,7 @@ command-line (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. diff --git a/lisp/subr.el b/lisp/subr.el index eea4e045dd..8b50748a59 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2930,10 +2930,15 @@ temp-buffer-setup-hook 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. -- 2.17.1