From 24acb31c04b4048b85311d794e600ecd7ce60d3b Mon Sep 17 00:00:00 2001 From: Radon Rosborough Date: Sat, 17 Feb 2018 13:36:16 +0200 Subject: [PATCH] Add early init file, stop package-initialize insertion Discussion on emacs-devel leading up to this change (approximately 150 messages): - https://lists.gnu.org/archive/html/emacs-devel/2017-08/msg00154.html - https://lists.gnu.org/archive/html/emacs-devel/2017-08/msg00433.html - https://lists.gnu.org/archive/html/emacs-devel/2017-09/msg00023.html - https://lists.gnu.org/archive/html/emacs-devel/2017-09/msg00599.html - https://lists.gnu.org/archive/html/emacs-devel/2017-10/msg00332.html * lisp/startup.el (early-init-file): New variable. (load-user-init-file): New function. (command-line): Load the early init file using `load-user-init-file'. Move the check for an invalid username to just before that, and move the initialization of the package system to just after. Load the regular init file using `load-user-init-file'. * lisp/emacs-lisp/package.el (package--ensure-init-file): Remove definition, usage, and documentation. (package--init-file-ensured): Remove definition and usage. * src/lread.c (Vuser_init_file): Note change in semantics due to its usage while loading the early init file. * doc/emacs/custom.texi: Document early init file. * doc/emacs/package.texi: Document changes to when package-initialize is called. Change terminology for package 'loading'. * doc/lispref/os.texi: Document early init file. Update startup summary. * doc/lispref/package.texi: Document changes to when package-initialize is called, and advise against calling it in the init file. Change terminology for package 'loading'. * doc/misc/org.texi: Don't recommend to call package-initialize in the init file. --- doc/emacs/custom.texi | 18 ++ doc/emacs/emacs.texi | 1 + doc/emacs/package.texi | 82 ++++---- doc/lispref/os.texi | 39 +++- doc/lispref/package.texi | 30 +-- doc/misc/org.texi | 4 +- etc/NEWS | 19 ++ lisp/emacs-lisp/package.el | 71 +------ lisp/startup.el | 379 ++++++++++++++++++++----------------- src/lread.c | 2 +- 10 files changed, 336 insertions(+), 309 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 2726690f09f..b985d12cde4 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -2167,6 +2167,7 @@ Manual}. * Terminal Init:: Each terminal type can have an init file. * Find Init:: How Emacs finds the init file. * Init Non-ASCII:: Using non-@acronym{ASCII} characters in an init file. +* Early Init File:: Another init file, which is read early on. @end menu @node Init Syntax @@ -2567,3 +2568,20 @@ instance: @noindent Type @kbd{C-q}, followed by the key you want to bind, to insert @var{char}. + +@node Early Init File +@subsection The Early Init File +@cindex early init file + + Most customizations for Emacs can be put in the normal init file, +@file{.emacs} or @file{~/.emacs.d/init.el}. 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{~/.emacs.d/early-init.el}. +This file is loaded before the package system is initialized, so in it +you can customize variables that affect the initialization process, +such as @code{package-enable-at-startup} and @code{package-load-list}. +@xref{Package Installation}. + + For more information on the early init file, @pxref{Early Init +File,,, elisp, The Emacs Lisp Reference Manual}. diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 163b6f23d84..65affeb59fe 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -1163,6 +1163,7 @@ The Emacs Initialization File * Terminal Init:: Each terminal type can have an init file. * Find Init:: How Emacs finds the init file. * Init Non-ASCII:: Using non-@acronym{ASCII} characters in an init file. +* Early Init File:: Another init file, which is read early on. Dealing with Emacs Trouble diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index bc6afb7966a..6c7493790d3 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi @@ -241,57 +241,55 @@ lower-priority archives will not be shown in the menu, if the same package is available from a higher-priority archive. (This is controlled by the value of @code{package-menu-hide-low-priority}.) - Once a package is downloaded and installed, it is @dfn{loaded} into -the current Emacs session. Loading a package is not quite the same as -loading a Lisp library (@pxref{Lisp Libraries}); loading a package -adds its directory to @code{load-path} and loads its autoloads. The -effect of a package's autoloads varies from package to package. Most -packages just make some new commands available, while others have more + Once a package is downloaded and installed, it is made available to +the current Emacs session. Making a package available adds its +directory to @code{load-path} and loads its autoloads. The effect of +a package's autoloads varies from package to package. Most packages +just make some new commands available, while others have more wide-ranging effects on the Emacs session. For such information, consult the package's help buffer. - By default, Emacs also automatically loads all installed packages in -subsequent Emacs sessions. This happens at startup, after processing -the init file (@pxref{Init File}). As an exception, Emacs does not -load packages at startup if invoked with the @samp{-q} or -@samp{--no-init-file} options (@pxref{Initial Options}). + After a package is installed, it is automatically made available by +Emacs in all subsequent sessions. This happens at startup, before +processing the init file but after processing the early init file +(@pxref{Early Init File,,, elisp, The Emacs Lisp Reference Manual}). +As an exception, Emacs does not make packages available at startup if +invoked with the @samp{-q} or @samp{--no-init-file} options +(@pxref{Initial Options}). @vindex package-enable-at-startup - To disable automatic package loading, change the variable -@code{package-enable-at-startup} to @code{nil}. + To keep Emacs from automatically making packages available at +startup, change the variable @code{package-enable-at-startup} to +@code{nil}. You must do this in the early init file (@pxref{Early +Init File,,, elisp, The Emacs Lisp Reference Manual}), as the variable +is read before loading the regular init file. Currently this variable +cannot be set via Customize. @findex package-initialize - The reason automatic package loading occurs after loading the init -file is that user options only receive their customized values after -loading the init file, including user options which affect the -packaging system. In some circumstances, you may want to load -packages explicitly in your init file (usually because some other code -in your init file depends on a package). In that case, your init file -should call the function @code{package-initialize}. It is up to you -to ensure that relevant user options, such as @code{package-load-list} -(see below), are set up prior to the @code{package-initialize} call. -This will automatically set @code{package-enable-at-startup} to @code{nil}, to -avoid loading the packages again after processing the init file. -Alternatively, you may choose to completely inhibit package loading at -startup, and invoke the command @kbd{M-x package-initialize} to load -your packages manually. + If you have set @code{package-enable-at-startup} to @code{nil}, you +can still make packages available either during or after startup. To +make installed packages available during startup, call the function +@code{package-initialize} in your init file. To make installed +packages available after startup, invoke the command @kbd{M-x +package-initialize}. @vindex package-load-list - For finer control over package loading, you can use the variable -@code{package-load-list}. Its value should be a list. A list element -of the form @code{(@var{name} @var{version})} tells Emacs to load -version @var{version} of the package named @var{name}. Here, -@var{version} should be a version string (corresponding to a specific -version of the package), or @code{t} (which means to load any -installed version), or @code{nil} (which means no version; this -disables the package, preventing it from being loaded). A list -element can also be the symbol @code{all}, which means to load the -latest installed version of any package not named by the other list -elements. The default value is just @code{'(all)}. - - For example, if you set @code{package-load-list} to @code{'((muse -"3.20") all)}, then Emacs only loads version 3.20 of the @samp{muse} -package, plus any installed version of packages other than + For finer control over which packages are made available at startup, +you can use the variable @code{package-load-list}. Its value should +be a list. A list element of the form @w{@code{(@var{name} +@var{version})}} tells Emacs to make available version @var{version} of +the package named @var{name}. Here, @var{version} should be a version +string (corresponding to a specific version of the package), or +@code{t} (which means to make available any installed version), or +@code{nil} (which means no version; this disables the package, +preventing it from being made available). A list element can also be +the symbol @code{all}, which means to make available the latest +installed version of any package not named by the other list elements. +The default value is just @code{'(all)}. + + For example, if you set @code{package-load-list} to @w{@code{'((muse +"3.20") all)}}, then Emacs only makes available version 3.20 of the +@samp{muse} package, plus any installed version of packages other than @samp{muse}. Any other version of @samp{muse} that happens to be installed will be ignored. The @samp{muse} package will be listed in the package menu with the @samp{held} status. diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 42be60449de..be2d148a1e2 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -95,6 +95,22 @@ if requested by environment variables such as @env{LANG}. @item It does some basic parsing of the command-line arguments. +@item +It loads your early init file (@pxref{Early Init File,,, emacs, The +GNU Emacs Manual}). This is not done if the options @samp{-q}, +@samp{-Q}, or @samp{--batch} were specified. If the @samp{-u} option +was specified, Emacs looks for the init file in that user's home +directory instead. + +@item +It calls the function @code{package-initialize} to activate any +optional Emacs Lisp package that has been installed. @xref{Packaging +Basics}. However, Emacs doesn't initialize packages when +@code{package-enable-at-startup} is @code{nil} or when it's started +with one of the options @samp{-q}, @samp{-Q}, or @samp{--batch}. To +initialize packages in the latter case, @code{package-initialize} +should be called explicitly (e.g., via the @samp{--funcall} option). + @vindex initial-window-system@r{, and startup} @vindex window-system-initialization-alist @item @@ -154,15 +170,6 @@ It loads your abbrevs from the file specified by (@pxref{Abbrev Files, abbrev-file-name}). This is not done if the option @samp{--batch} was specified. -@item -It calls the function @code{package-initialize} to activate any -optional Emacs Lisp package that has been installed. @xref{Packaging -Basics}. However, Emacs doesn't initialize packages when -@code{package-enable-at-startup} is @code{nil} or when it's started -with one of the options @samp{-q}, @samp{-Q}, or @samp{--batch}. To -initialize packages in the latter case, @code{package-initialize} -should be called explicitly (e.g., via the @samp{--funcall} option). - @vindex after-init-time @item It sets the variable @code{after-init-time} to the value of @@ -361,6 +368,7 @@ Equivalent to @samp{-q --no-site-file --no-splash}. @cindex init file @cindex @file{.emacs} @cindex @file{init.el} +@cindex @file{early-init.el} When you start Emacs, it normally attempts to load your @dfn{init file}. This is either a file named @file{.emacs} or @file{.emacs.el} @@ -384,6 +392,19 @@ file; this way, even if you have su'd, Emacs still loads your own init file. If those environment variables are absent, though, Emacs uses your user-id to find your home directory. +@cindex early init file + Emacs also attempts to load a second init file, called the +@dfn{early init file}, if it exists. This is a file named +@file{early-init.el} in your @file{~/.emacs.d} directory. The +difference between the early init file and the regular init file is +that the early init file is loaded much earlier during the startup +process, so you can use it to customize some things that are +initialized before loading the regular init file. For example, you +can customize the process of initializing the package system, by +setting variables such as @var{package-load-list} or +@var{package-enable-at-startup}. @xref{Package Installation,,, +emacs,The GNU Emacs Manual}. + @cindex default init file An Emacs installation may have a @dfn{default init file}, which is a Lisp library named @file{default.el}. Emacs finds this file through diff --git a/doc/lispref/package.texi b/doc/lispref/package.texi index 21dfe1c2717..877aaf89a35 100644 --- a/doc/lispref/package.texi +++ b/doc/lispref/package.texi @@ -105,24 +105,32 @@ adds the package's content directory to @code{load-path}, and evaluates the autoload definitions in @file{@var{name}-autoloads.el}. Whenever Emacs starts up, it automatically calls the function -@code{package-initialize} to load installed packages. This is done -after loading the init file and abbrev file (if any) and before -running @code{after-init-hook} (@pxref{Startup Summary}). Automatic -package loading is disabled if the user option -@code{package-enable-at-startup} is @code{nil}. +@code{package-initialize} to make installed packages available to the +current session. This is done after loading the early init file, but +before loading the regular init file (@pxref{Startup Summary}). +Packages are not automatically made available if the user option +@code{package-enable-at-startup} is set to @code{nil} in the early +init file. @deffn Command package-initialize &optional no-activate This function initializes Emacs' internal record of which packages are -installed, and loads them. The user option @code{package-load-list} -specifies which packages to load; by default, all installed packages -are loaded. If called during startup, this function also sets +installed, and makes the packages available to the current session. +The user option @code{package-load-list} specifies which packages to +make available; by default, all installed packages are made available. +If called during startup, this function also sets @code{package-enable-at-startup} to @code{nil}, to avoid accidentally -loading the packages twice. @xref{Package Installation,,, emacs, The -GNU Emacs Manual}. +evaluating package autoloads more than once. @xref{Package +Installation,,, emacs, The GNU Emacs Manual}. The optional argument @var{no-activate}, if non-@code{nil}, causes Emacs to update its record of installed packages without actually -loading them; it is for internal use only. +making them available; it is for internal use only. + +In most cases, you should not need to call @code{package-initialize}, +as this is done automatically during startup. Simply make sure to put +any code that should run before @code{package-initialize} in the early +init file, and any code that should run after it in the primary init +file (@xref{Init File,,, emacs, The GNU Emacs Manual}). @end deffn @node Simple Packages diff --git a/doc/misc/org.texi b/doc/misc/org.texi index aa3b029ab7c..68aa01ca18c 100644 --- a/doc/misc/org.texi +++ b/doc/misc/org.texi @@ -890,9 +890,7 @@ Elisp libraries. You can install Org with @kbd{M-x package-install RET org}. been visited, i.e., where no Org built-in function have been loaded. Otherwise autoload Org functions will mess up the installation. -Then, to make sure your Org configuration is taken into account, initialize -the package system with @code{(package-initialize)} in your Emacs init file -before setting any Org option. If you want to use Org's package repository, +If you want to use Org's package repository, check out the @uref{http://orgmode.org/elpa.html, Org ELPA page}. @subsubheading Downloading Org as an archive diff --git a/etc/NEWS b/etc/NEWS index 71569c95adf..b6b884b816e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -49,6 +49,25 @@ to reduce differences between developer and production builds. * Startup Changes in Emacs 27.1 ++++ +** Emacs can now be configured using an early init file. +The file is called 'early-init.el', in 'user-emacs-directory'. It is +loaded very early in the startup process: before graphical elements +such as the tool bar are initialized, and before the package manager +is initialized. The primary purpose is to allow customizing how the +package system is initialized given that initialization now happens +before loading the regular init file (see below). + ++++ +** Emacs now calls 'package-initialize' before loading the init file. +This is part of a change intended to eliminate the behavior of +package.el inserting a call to 'package-initialize' into the init +file, which was previously done when Emacs was started. As a result +of this change, it is no longer necessary to call 'package-initialize' +in your init file. However, if your init file changes the values of +'package-load-list' or 'package-user-dir', then that code needs to be +moved to the early init file (see above). + * Changes in Emacs 27.1 diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 71d1c41ec3c..ab02d4255b1 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -1431,16 +1431,11 @@ If successful, set `package-archive-contents'." ;; available on disk. (defvar package--initialized nil) -(defvar package--init-file-ensured nil - "Whether we know the init file has package-initialize.") - ;;;###autoload (defun package-initialize (&optional no-activate) "Load Emacs Lisp packages, and activate them. The variable `package-load-list' controls which packages to load. If optional arg NO-ACTIVATE is non-nil, don't activate packages. -If `user-init-file' does not mention `(package-initialize)', add -it to the file. If called as part of loading `user-init-file', set `package-enable-at-startup' to nil, to prevent accidentally loading packages twice. @@ -1449,13 +1444,7 @@ individual packages after calling `package-initialize' -- this is taken care of by `package-initialize'." (interactive) (setq package-alist nil) - (if after-init-time - (package--ensure-init-file) - ;; If `package-initialize' is before we finished loading the init - ;; file, it's obvious we don't need to ensure-init. - (setq package--init-file-ensured t - ;; And likely we don't need to run it again after init. - package-enable-at-startup nil)) + (setq package-enable-at-startup nil) (package-load-all-descriptors) (package-read-all-archive-contents) (unless no-activate @@ -1872,64 +1861,6 @@ PACKAGES are satisfied, i.e. that PACKAGES is computed using `package-compute-transaction'." (mapc #'package-install-from-archive packages)) -(defun package--ensure-init-file () - "Ensure that the user's init file has `package-initialize'. -`package-initialize' doesn't have to be called, as long as it is -present somewhere in the file, even as a comment. If it is not, -add a call to it along with some explanatory comments." - ;; Don't mess with the init-file from "emacs -Q". - (when (and (stringp user-init-file) - (not package--init-file-ensured) - (file-readable-p user-init-file) - (file-writable-p user-init-file)) - (let* ((buffer (find-buffer-visiting user-init-file)) - buffer-name - (contains-init - (if buffer - (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (re-search-forward "(package-initialize\\_>" nil 'noerror)))) - ;; Don't visit the file if we don't have to. - (with-temp-buffer - (insert-file-contents user-init-file) - (goto-char (point-min)) - (re-search-forward "(package-initialize\\_>" nil 'noerror))))) - (unless contains-init - (with-current-buffer (or buffer - (let ((delay-mode-hooks t) - (find-file-visit-truename t)) - (find-file-noselect user-init-file))) - (when buffer - (setq buffer-name (buffer-file-name)) - (set-visited-file-name (file-chase-links user-init-file))) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (while (and (looking-at-p "[[:blank:]]*\\(;\\|$\\)") - (not (eobp))) - (forward-line 1)) - (insert - "\n" - ";; Added by Package.el. This must come before configurations of\n" - ";; installed packages. Don't delete this line. If you don't want it,\n" - ";; just comment it out by adding a semicolon to the start of the line.\n" - ";; You may delete these explanatory comments.\n" - "(package-initialize)\n") - (unless (looking-at-p "$") - (insert "\n")) - (let ((file-precious-flag t)) - (save-buffer)) - (if buffer - (progn - (set-visited-file-name buffer-name) - (set-buffer-modified-p nil)) - (kill-buffer (current-buffer))))))))) - (setq package--init-file-ensured t)) - ;;;###autoload (defun package-install (pkg &optional dont-select) "Install the package PKG. diff --git a/lisp/startup.el b/lisp/startup.el index 8c36c19e828..69bc8fa7816 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -312,6 +312,12 @@ see `tty-setup-hook'.") Currently this applies to: `emacs-startup-hook', `term-setup-hook', and `window-setup-hook'.") +(defvar early-init-file nil + "File name, including directory, of user's early init file. +See `user-init-file'. The only difference is that +`early-init-file' is not set during the course of evaluating the +early init file.") + (defvar keyboard-type nil "The brand of keyboard you are using. This variable is used to define the proper function and keypad @@ -870,6 +876,103 @@ If STYLE is nil, display appropriately for the terminal." (when standard-display-table (aset standard-display-table char nil))))))) +(defun load-user-init-file + (filename-function &optional alternate-filename-function load-defaults) + "Load a user init-file. +FILENAME-FUNCTION is called with no arguments and should return +the name of the init-file to load. If this file cannot be +loaded, and ALTERNATE-FILENAME-FUNCTION is non-nil, then it is +called with no arguments and should return the name of an +alternate init-file to load. If LOAD-DEFAULTS is non-nil, then +load default.el after the init-file. + +This function sets `user-init-file' to the name of the loaded +init-file, or to a default value if loading is not possible." + (let ((debug-on-error-from-init-file nil) + (debug-on-error-should-be-set nil) + (debug-on-error-initial + (if (eq init-file-debug t) + 'startup + init-file-debug))) + (let ((debug-on-error debug-on-error-initial) + ;; We create an anonymous function here so that we can call + ;; it in different contexts depending on the value of + ;; `debug-on-error'. + (read-init-file + (lambda () + (when init-file-user + (let ((init-file-name (funcall filename-function))) + + ;; If `user-init-file' is t, then `load' will store + ;; the name of the file that it loads into + ;; `user-init-file'. + (setq user-init-file t) + (load init-file-name 'noerror 'nomessage) + + (when (and (eq user-init-file t) alternate-filename-function) + (load (funcall alternate-filename-function) + 'noerror 'nomessage)) + + ;; If we did not find the user's init file, set + ;; user-init-file conclusively. Don't let it be + ;; set from default.el. + (when (eq user-init-file t) + (setq user-init-file init-file-name))) + + ;; If we loaded a compiled file, set `user-init-file' to + ;; the source version if that exists. + (when (equal (file-name-extension user-init-file) + "elc") + (let* ((source (file-name-sans-extension user-init-file)) + (alt (concat source ".el"))) + (setq source (cond ((file-exists-p alt) alt) + ((file-exists-p source) source) + (t nil))) + (when source + (when (file-newer-than-file-p source user-init-file) + (message "Warning: %s is newer than %s" + source user-init-file) + (sit-for 1)) + (setq user-init-file source)))) + + (when load-defaults + + ;; Prevent default.el from changing the value of + ;; `inhibit-startup-screen'. + (let ((inhibit-startup-screen nil)) + (load "default" 'noerror 'nomessage))))))) + ;; Now call our anonymous function. + (if init-file-debug + ;; Do this without a `condition-case' if the user wants to + ;; debug. + (funcall read-init-file) + (condition-case error + (funcall read-init-file) + (error + (display-warning + 'initialization + (format-message "\ +An error occurred while loading `%s':\n\n%s%s%s\n\n\ +To ensure normal operation, you should investigate and remove the +cause of the error in your initialization file. Start Emacs with +the `--debug-init' option to view a complete error backtrace." + user-init-file + (get (car error) 'error-message) + (if (cdr error) ": " "") + (mapconcat (lambda (s) (prin1-to-string s t)) + (cdr error) ", ")) + :warning) + (setq init-file-had-error t)))) + + ;; If we can tell that the init file altered debug-on-error, + ;; arrange to preserve the value that it set up. + (or (eq debug-on-error debug-on-error-initial) + (setq debug-on-error-should-be-set t + debug-on-error-from-init-file debug-on-error))) + + (when debug-on-error-should-be-set + (setq debug-on-error debug-on-error-from-init-file)))) + (defun command-line () "A subroutine of `normal-top-level'. Amongst another things, it parses the command-line arguments." @@ -1021,6 +1124,69 @@ please check its value") (and command-line-args (setcdr command-line-args args))) + ;; Warn for invalid user name. + (when init-file-user + (if (string-match "[~/:\n]" init-file-user) + (display-warning 'initialization + (format "Invalid user name %s" + init-file-user) + :error) + (if (file-directory-p (expand-file-name + ;; We don't support ~USER on MS-Windows + ;; and MS-DOS except for the current + ;; user, and always load .emacs from + ;; the current user's home directory + ;; (see below). So always check "~", + ;; even if invoked with "-u USER", or + ;; if $USER or $LOGNAME are set to + ;; something different. + (if (memq system-type '(windows-nt ms-dos)) + "~" + (concat "~" init-file-user)))) + nil + (display-warning 'initialization + (format "User %s has no home directory" + (if (equal init-file-user "") + (user-real-login-name) + init-file-user)) + :error)))) + + ;; Load the early init file, if found. + (load-user-init-file + (lambda () + (expand-file-name + "early-init" + (file-name-as-directory + (concat "~" init-file-user "/.emacs.d"))))) + (setq early-init-file user-init-file) + + ;; If any package directory exists, initialize the package system. + (and user-init-file + package-enable-at-startup + (catch 'package-dir-found + (let (dirs) + (if (boundp 'package-directory-list) + (setq dirs package-directory-list) + (dolist (f load-path) + (and (stringp f) + (equal (file-name-nondirectory f) "site-lisp") + (push (expand-file-name "elpa" f) dirs)))) + (push (if (boundp 'package-user-dir) + package-user-dir + (locate-user-emacs-file "elpa")) + dirs) + (dolist (dir dirs) + (when (file-directory-p dir) + (dolist (subdir (directory-files dir)) + (when (let ((subdir (expand-file-name subdir dir))) + (and (file-directory-p subdir) + (file-exists-p + (expand-file-name + (package--description-file subdir) + subdir)))) + (throw 'package-dir-found t))))))) + (package-initialize)) + ;; Make sure window system's init file was loaded in loadup.el if ;; using a window system. ;; Initialize the window-system only after processing the command-line @@ -1128,153 +1294,47 @@ please check its value") ;; the startup screen. (setq inhibit-startup-screen nil) - ;; Warn for invalid user name. - (when init-file-user - (if (string-match "[~/:\n]" init-file-user) - (display-warning 'initialization - (format "Invalid user name %s" - init-file-user) - :error) - (if (file-directory-p (expand-file-name - ;; We don't support ~USER on MS-Windows - ;; and MS-DOS except for the current - ;; user, and always load .emacs from - ;; the current user's home directory - ;; (see below). So always check "~", - ;; even if invoked with "-u USER", or - ;; if $USER or $LOGNAME are set to - ;; something different. - (if (memq system-type '(windows-nt ms-dos)) - "~" - (concat "~" init-file-user)))) - nil - (display-warning 'initialization - (format "User %s has no home directory" - (if (equal init-file-user "") - (user-real-login-name) - init-file-user)) - :error)))) - ;; Load that user's init file, or the default one, or none. - (let (debug-on-error-from-init-file - debug-on-error-should-be-set - (debug-on-error-initial - (if (eq init-file-debug t) 'startup init-file-debug))) - (let ((debug-on-error debug-on-error-initial) - ;; This function actually reads the init files. - (inner - (function - (lambda () - (if init-file-user - (let ((user-init-file-1 - (cond - ((eq system-type 'ms-dos) - (concat "~" init-file-user "/_emacs")) - ((not (eq system-type 'windows-nt)) - (concat "~" init-file-user "/.emacs")) - ;; Else deal with the Windows situation - ((directory-files "~" nil "^\\.emacs\\(\\.elc?\\)?$") - ;; Prefer .emacs on Windows. - "~/.emacs") - ((directory-files "~" nil "^_emacs\\(\\.elc?\\)?$") - ;; Also support _emacs for compatibility, but warn about it. - (push `(initialization - ,(format-message - "`_emacs' init file is deprecated, please use `.emacs'")) - delayed-warnings-list) - "~/_emacs") - (t ;; But default to .emacs if _emacs does not exist. - "~/.emacs")))) - ;; This tells `load' to store the file name found - ;; into user-init-file. - (setq user-init-file t) - (load user-init-file-1 t t) - - (when (eq user-init-file t) - ;; If we did not find ~/.emacs, try - ;; ~/.emacs.d/init.el. - (let ((otherfile - (expand-file-name - "init" - (file-name-as-directory - (concat "~" init-file-user "/.emacs.d"))))) - (load otherfile t t) - - ;; If we did not find the user's init file, - ;; set user-init-file conclusively. - ;; Don't let it be set from default.el. - (when (eq user-init-file t) - (setq user-init-file user-init-file-1)))) - - ;; If we loaded a compiled file, set - ;; `user-init-file' to the source version if that - ;; exists. - (when (and user-init-file - (equal (file-name-extension user-init-file) - "elc")) - (let* ((source (file-name-sans-extension user-init-file)) - (alt (concat source ".el"))) - (setq source (cond ((file-exists-p alt) alt) - ((file-exists-p source) source) - (t nil))) - (when source - (when (file-newer-than-file-p source user-init-file) - (message "Warning: %s is newer than %s" - source user-init-file) - (sit-for 1)) - (setq user-init-file source)))) - - (unless inhibit-default-init - (let ((inhibit-startup-screen nil)) - ;; Users are supposed to be told their rights. - ;; (Plus how to get help and how to undo.) - ;; Don't you dare turn this off for anyone - ;; except yourself. - (load "default" t t))))))))) - (if init-file-debug - ;; Do this without a condition-case if the user wants to debug. - (funcall inner) - (condition-case error - (progn - (funcall inner) - (setq init-file-had-error nil)) - (error - (display-warning - 'initialization - (format-message "\ -An error occurred while loading `%s':\n\n%s%s%s\n\n\ -To ensure normal operation, you should investigate and remove the -cause of the error in your initialization file. Start Emacs with -the `--debug-init' option to view a complete error backtrace." - user-init-file - (get (car error) 'error-message) - (if (cdr error) ": " "") - (mapconcat (lambda (s) (prin1-to-string s t)) - (cdr error) ", ")) - :warning) - (setq init-file-had-error t)))) - - (if (and deactivate-mark transient-mark-mode) - (with-current-buffer (window-buffer) - (deactivate-mark))) - - ;; If the user has a file of abbrevs, read it (unless -batch). - (when (and (not noninteractive) - (file-exists-p abbrev-file-name) - (file-readable-p abbrev-file-name)) - (quietly-read-abbrev-file abbrev-file-name)) - - ;; If the abbrevs came entirely from the init file or the - ;; abbrevs file, they do not need saving. - (setq abbrevs-changed nil) - - ;; If we can tell that the init file altered debug-on-error, - ;; arrange to preserve the value that it set up. - (or (eq debug-on-error debug-on-error-initial) - (setq debug-on-error-should-be-set t - debug-on-error-from-init-file debug-on-error))) - (if debug-on-error-should-be-set - (setq debug-on-error debug-on-error-from-init-file))) + (load-user-init-file + (lambda () + (cond + ((eq system-type 'ms-dos) + (concat "~" init-file-user "/_emacs")) + ((not (eq system-type 'windows-nt)) + (concat "~" init-file-user "/.emacs")) + ;; Else deal with the Windows situation. + ((directory-files "~" nil "^\\.emacs\\(\\.elc?\\)?$") + ;; Prefer .emacs on Windows. + "~/.emacs") + ((directory-files "~" nil "^_emacs\\(\\.elc?\\)?$") + ;; Also support _emacs for compatibility, but warn about it. + (push `(initialization + ,(format-message + "`_emacs' init file is deprecated, please use `.emacs'")) + delayed-warnings-list) + "~/_emacs") + (t ;; But default to .emacs if _emacs does not exist. + "~/.emacs"))) + (lambda () + (expand-file-name + "init" + (file-name-as-directory + (concat "~" init-file-user "/.emacs.d")))) + (not inhibit-default-init)) + + (when (and deactivate-mark transient-mark-mode) + (with-current-buffer (window-buffer) + (deactivate-mark))) + + ;; If the user has a file of abbrevs, read it (unless -batch). + (when (and (not noninteractive) + (file-exists-p abbrev-file-name) + (file-readable-p abbrev-file-name)) + (quietly-read-abbrev-file abbrev-file-name)) + + ;; If the abbrevs came entirely from the init file or the + ;; abbrevs file, they do not need saving. + (setq abbrevs-changed nil) ;; Do this here in case the init file sets mail-host-address. (and mail-host-address @@ -1296,33 +1356,6 @@ the `--debug-init' option to view a complete error backtrace." (eq face-ignored-fonts old-face-ignored-fonts)) (clear-face-cache))) - ;; If any package directory exists, initialize the package system. - (and user-init-file - package-enable-at-startup - (catch 'package-dir-found - (let (dirs) - (if (boundp 'package-directory-list) - (setq dirs package-directory-list) - (dolist (f load-path) - (and (stringp f) - (equal (file-name-nondirectory f) "site-lisp") - (push (expand-file-name "elpa" f) dirs)))) - (push (if (boundp 'package-user-dir) - package-user-dir - (locate-user-emacs-file "elpa")) - dirs) - (dolist (dir dirs) - (when (file-directory-p dir) - (dolist (subdir (directory-files dir)) - (when (let ((subdir (expand-file-name subdir dir))) - (and (file-directory-p subdir) - (file-exists-p - (expand-file-name - (package--description-file subdir) - subdir)))) - (throw 'package-dir-found t))))))) - (package-initialize)) - (setq after-init-time (current-time)) ;; Display any accumulated warnings after all functions in ;; `after-init-hook' like `desktop-read' have finalized possible diff --git a/src/lread.c b/src/lread.c index 7cacd47d510..d009bd0cd2a 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4922,7 +4922,7 @@ directory. These file names are converted to absolute at startup. */); If the file loaded had extension `.elc', and the corresponding source file exists, this variable contains the name of source file, suitable for use by functions like `custom-save-all' which edit the init file. -While Emacs loads and evaluates the init file, value is the real name +While Emacs loads and evaluates any init file, value is the real name of the file, regardless of whether or not it has the `.elc' extension. */); Vuser_init_file = Qnil; -- 2.39.2