emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 24acb31: Add early init file, stop package-initiali


From: Eli Zaretskii
Subject: [Emacs-diffs] master 24acb31: Add early init file, stop package-initialize insertion
Date: Sat, 17 Feb 2018 06:38:04 -0500 (EST)

branch: master
commit 24acb31c04b4048b85311d794e600ecd7ce60d3b
Author: Radon Rosborough <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    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 2726690..b985d12 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 address@hidden 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}.
+
address@hidden Early Init File
address@hidden The Early Init File
address@hidden early init file
+
+  Most customizations for Emacs can be put in the normal init file,
address@hidden 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}.
address@hidden 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 163b6f2..65affeb 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 address@hidden 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 bc6afb7..6c74937 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
address@hidden 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
address@hidden to @code{nil}.
+  To keep Emacs from automatically making packages available at
+startup, change the variable @code{package-enable-at-startup} to
address@hidden  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
address@hidden 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
address@hidden  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,
address@hidden 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 @address@hidden(@var{name}
address@hidden)}} 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
address@hidden (which means to make available any installed version), or
address@hidden (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 @address@hidden'((muse
+"3.20") all)}}, then Emacs only makes available version 3.20 of the
address@hidden 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 42be604..be2d148 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.
 
address@hidden
+It loads your early init file (@pxref{Early Init File,,, emacs, The
+GNU Emacs Manual}).  This is not done if the options @samp{-q},
address@hidden, 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.
+
address@hidden
+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
address@hidden 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 address@hidden, 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.
 
address@hidden
-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
address@hidden 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}
address@hidden @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.
 
address@hidden early init file
+  Emacs also attempts to load a second init file, called the
address@hidden init file}, if it exists.  This is a file named
address@hidden 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
address@hidden  @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 21dfe1c..877aaf8 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 @address@hidden
 
   Whenever Emacs starts up, it automatically calls the function
address@hidden 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
address@hidden is @code{nil}.
address@hidden 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
address@hidden 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 address@hidden, 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 aa3b029..68aa01c 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 71569c9..b6b884b 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 71d1c41..ab02d42 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 8c36c19..69bc8fa 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 7cacd47..d009bd0 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;
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]