From e15fd3120a995e38708ca73d293973dd8e596b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20F=C3=A9votte?= Date: Thu, 2 Apr 2015 09:17:03 +0200 Subject: [PATCH] Look for an `EMACS_USER_DIRECTORY' environment variable. This sets `user-emacs-directory' and looks for `init.el' in it. Fixes: bug#15539 --- doc/emacs/cmdargs.texi | 9 +- doc/emacs/custom.texi | 8 + lisp/custom.el | 1 + lisp/startup.el | 832 ++++++++++++++++++++++++------------------------ 4 files changed, 439 insertions(+), 411 deletions(-) diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index 071cd68..30d3472 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -349,7 +349,9 @@ Do not reload any saved desktop. @xref{Saving Emacs Sessions}. @opindex --user @cindex load init file of another user Load @var{user}'s initialization file instead of your -own@footnote{This option has no effect on MS-Windows.}. +own@footnote{This option has no effect on MS-Windows, nor when the +@env{EMACS_USER_DIRECTORY} environment variable is set (@pxref{General +Variables}).}. @item --debug-init @opindex --debug-init @@ -642,6 +644,11 @@ does not use @env{TZ} at all. @vindex USER, environment variable The user's login name. See also @env{LOGNAME}. On MS-DOS, this defaults to @samp{root}. +@item EMACS_USER_DIRECTORY +This specifies a directory in which the initialization file will be +looked for; @xref{Find Init}. This directory will also be used as the +default place where user-specific configuration data will be stored; +@xref{Standard File Names,,, elisp}. @item VERSION_CONTROL @vindex VERSION_CONTROL, environment variable Used to initialize the @code{version-control} variable (@pxref{Backup diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 9fd823b..1e1d482 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -2516,6 +2516,14 @@ otherwise, it looks up the home directory corresponding to that user name in the system's data base of users. @c LocalWords: backtab + The whole mechanism described above is bypassed if the +@env{EMACS_USER_DIRECTORY} environment variable is specified, in which +case Emacs directly looks for @file{init.el} inside the directory +specified by @env{EMACS_USER_DIRECTORY} (@pxref{General Variables}). +This directory is also used to hold user-specific configuration +(@pxref{Standard File Names,,, elisp}). + + @node Init Non-ASCII @subsection Non-@acronym{ASCII} Characters in Init Files @cindex international characters in @file{.emacs} diff --git a/lisp/custom.el b/lisp/custom.el index e5fe0eb..36983aa 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -1119,6 +1119,7 @@ directory. By default, Emacs searches for custom themes in this directory first---see `custom-theme-load-path'." :type 'string :group 'customize + :initialize 'custom-initialize-delay :version "22.1") (defcustom custom-theme-load-path (list 'custom-theme-directory t) diff --git a/lisp/startup.el b/lisp/startup.el index 7fa929a..1c403c6 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -397,7 +397,8 @@ Set this to nil if you want to prevent `auto-save-list-file-name' from being initialized." :type '(choice (const :tag "Don't record a session's auto save list" nil) string) - :group 'auto-save) + :group 'auto-save + :initialize 'custom-initialize-delay) (defvar emacs-basic-display nil) @@ -814,420 +815,431 @@ Amongst another things, it parses the command-line arguments." ((member vc '("never" "simple")) (setq version-control 'never)))) - ;;! This has been commented out; I currently find the behavior when - ;;! split-window-keep-point is nil disturbing, but if I can get used - ;;! to it, then it would be better to eliminate the option. - ;;! ;; Choose a good default value for split-window-keep-point. - ;;! (setq split-window-keep-point (> baud-rate 2400)) - - ;; Convert preloaded file names in load-history to absolute. - (let ((simple-file-name - ;; Look for simple.el or simple.elc and use their directory - ;; as the place where all Lisp files live. - (locate-file "simple" load-path (get-load-suffixes))) - lisp-dir) - ;; Don't abort if simple.el cannot be found, but print a warning. - ;; Although in most usage we are going to cryptically abort a moment - ;; later anyway, due to missing required bidi data files (eg bug#13430). - (if (null simple-file-name) - (let ((standard-output 'external-debugging-output) - (lispdir (expand-file-name "../lisp" data-directory))) - (princ "Warning: Could not find simple.el or simple.elc") - (terpri) - (when (getenv "EMACSLOADPATH") - (princ "The EMACSLOADPATH environment variable is set, \ + ;; Set `user-emacs-directory' early so that delayed init variables + ;; can be updated. + (let ((user-emacs-directory--from-env (getenv "EMACS_USER_DIRECTORY"))) + (when user-emacs-directory--from-env + (setq user-emacs-directory (file-name-as-directory user-emacs-directory--from-env))) + + ;;! This has been commented out; I currently find the behavior when + ;;! split-window-keep-point is nil disturbing, but if I can get used + ;;! to it, then it would be better to eliminate the option. + ;;! ;; Choose a good default value for split-window-keep-point. + ;;! (setq split-window-keep-point (> baud-rate 2400)) + + ;; Convert preloaded file names in load-history to absolute. + (let ((simple-file-name + ;; Look for simple.el or simple.elc and use their directory + ;; as the place where all Lisp files live. + (locate-file "simple" load-path (get-load-suffixes))) + lisp-dir) + ;; Don't abort if simple.el cannot be found, but print a warning. + ;; Although in most usage we are going to cryptically abort a moment + ;; later anyway, due to missing required bidi data files (eg bug#13430). + (if (null simple-file-name) + (let ((standard-output 'external-debugging-output) + (lispdir (expand-file-name "../lisp" data-directory))) + (princ "Warning: Could not find simple.el or simple.elc") + (terpri) + (when (getenv "EMACSLOADPATH") + (princ "The EMACSLOADPATH environment variable is set, \ please check its value") - (terpri)) - (unless (file-readable-p lispdir) - (princ (format "Lisp directory %s not readable?" lispdir)) - (terpri))) - (setq lisp-dir (file-truename (file-name-directory simple-file-name))) - (setq load-history - (mapcar (lambda (elt) - (if (and (stringp (car elt)) - (not (file-name-absolute-p (car elt)))) - (cons (concat lisp-dir - (car elt)) - (cdr elt)) - elt)) - load-history)))) - - ;; Convert the arguments to Emacs internal representation. - (let ((args command-line-args)) - (while args - (setcar args - (decode-coding-string (car args) locale-coding-system t)) - (pop args))) - - (let ((done nil) - (args (cdr command-line-args)) - display-arg) - - ;; Figure out which user's init file to load, - ;; either from the environment or from the options. - (setq init-file-user (if noninteractive nil (user-login-name))) - ;; If user has not done su, use current $HOME to find .emacs. - (and init-file-user - (equal init-file-user (user-real-login-name)) - (setq init-file-user "")) - - ;; Process the command-line args, and delete the arguments - ;; processed. This is consistent with the way main in emacs.c - ;; does things. - (while (and (not done) args) - (let* ((longopts '(("--no-init-file") ("--no-site-file") - ("--no-x-resources") ("--debug-init") - ("--user") ("--iconic") ("--icon-type") ("--quick") - ("--no-blinking-cursor") ("--basic-display"))) - (argi (pop args)) - (orig-argi argi) - argval) - ;; Handle --OPTION=VALUE format. - (when (string-match "\\`\\(--[^=]*\\)=" argi) - (setq argval (substring argi (match-end 0)) - argi (match-string 1 argi))) - (when (string-match "\\`--." orig-argi) - (let ((completion (try-completion argi longopts))) - (cond ((eq completion t) - (setq argi (substring argi 1))) - ((stringp completion) - (let ((elt (assoc completion longopts))) - (unless elt - (error "Option `%s' is ambiguous" argi)) - (setq argi (substring (car elt) 1)))) - (t - (setq argval nil - argi orig-argi))))) - (cond - ;; The --display arg is handled partly in C, partly in Lisp. - ;; When it shows up here, we just put it back to be handled - ;; by `command-line-1'. - ((member argi '("-d" "-display")) - (setq display-arg (list argi (pop args)))) - ((member argi '("-Q" "-quick")) - (setq init-file-user nil - site-run-file nil - inhibit-x-resources t)) - ((member argi '("-no-x-resources")) - (setq inhibit-x-resources t)) - ((member argi '("-D" "-basic-display")) - (setq no-blinking-cursor t - emacs-basic-display t) - (push '(vertical-scroll-bars . nil) initial-frame-alist)) - ((member argi '("-q" "-no-init-file")) - (setq init-file-user nil)) - ((member argi '("-u" "-user")) - (setq init-file-user (or argval (pop args)) - argval nil)) - ((equal argi "-no-site-file") - (setq site-run-file nil)) - ((equal argi "-debug-init") - (setq init-file-debug t)) - ((equal argi "-iconic") - (push '(visibility . icon) initial-frame-alist)) - ((member argi '("-nbc" "-no-blinking-cursor")) - (setq no-blinking-cursor t)) - ;; Push the popped arg back on the list of arguments. - (t - (push argi args) - (setq done t))) - ;; Was argval set but not used? - (and argval - (error "Option `%s' doesn't allow an argument" argi)))) - - ;; Re-attach the --display arg. - (and display-arg (setq args (append display-arg args))) - - ;; Re-attach the program name to the front of the arg list. - (and command-line-args - (setcdr command-line-args args))) - - ;; 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 - ;; args so that -Q can influence this initialization. - (condition-case error - (unless noninteractive - (if (and initial-window-system - (not (featurep - (intern - (concat (symbol-name initial-window-system) "-win"))))) - (error "Unsupported window system `%s'" initial-window-system)) - ;; Process window-system specific command line parameters. - (setq command-line-args - (funcall - (gui-method handle-args-function initial-window-system) - command-line-args)) - ;; Initialize the window system. (Open connection, etc.) - (funcall - (gui-method window-system-initialization initial-window-system)) - (put initial-window-system 'window-system-initialized t)) - ;; If there was an error, print the error message and exit. - (error - (princ - (if (eq (car error) 'error) - (apply 'concat (cdr error)) - (if (memq 'file-error (get (car error) 'error-conditions)) - (format "%s: %s" - (nth 1 error) + (terpri)) + (unless (file-readable-p lispdir) + (princ (format "Lisp directory %s not readable?" lispdir)) + (terpri))) + (setq lisp-dir (file-truename (file-name-directory simple-file-name))) + (setq load-history + (mapcar (lambda (elt) + (if (and (stringp (car elt)) + (not (file-name-absolute-p (car elt)))) + (cons (concat lisp-dir + (car elt)) + (cdr elt)) + elt)) + load-history)))) + + ;; Convert the arguments to Emacs internal representation. + (let ((args command-line-args)) + (while args + (setcar args + (decode-coding-string (car args) locale-coding-system t)) + (pop args))) + + (let ((done nil) + (args (cdr command-line-args)) + display-arg) + + ;; Figure out which user's init file to load, + ;; either from the environment or from the options. + (setq init-file-user (if noninteractive nil (user-login-name))) + ;; If user has not done su, use current $HOME to find .emacs. + (and init-file-user + (equal init-file-user (user-real-login-name)) + (setq init-file-user "")) + + ;; Process the command-line args, and delete the arguments + ;; processed. This is consistent with the way main in emacs.c + ;; does things. + (while (and (not done) args) + (let* ((longopts '(("--no-init-file") ("--no-site-file") + ("--no-x-resources") ("--debug-init") + ("--user") ("--iconic") ("--icon-type") ("--quick") + ("--no-blinking-cursor") ("--basic-display"))) + (argi (pop args)) + (orig-argi argi) + argval) + ;; Handle --OPTION=VALUE format. + (when (string-match "\\`\\(--[^=]*\\)=" argi) + (setq argval (substring argi (match-end 0)) + argi (match-string 1 argi))) + (when (string-match "\\`--." orig-argi) + (let ((completion (try-completion argi longopts))) + (cond ((eq completion t) + (setq argi (substring argi 1))) + ((stringp completion) + (let ((elt (assoc completion longopts))) + (unless elt + (error "Option `%s' is ambiguous" argi)) + (setq argi (substring (car elt) 1)))) + (t + (setq argval nil + argi orig-argi))))) + (cond + ;; The --display arg is handled partly in C, partly in Lisp. + ;; When it shows up here, we just put it back to be handled + ;; by `command-line-1'. + ((member argi '("-d" "-display")) + (setq display-arg (list argi (pop args)))) + ((member argi '("-Q" "-quick")) + (setq init-file-user nil + site-run-file nil + inhibit-x-resources t)) + ((member argi '("-no-x-resources")) + (setq inhibit-x-resources t)) + ((member argi '("-D" "-basic-display")) + (setq no-blinking-cursor t + emacs-basic-display t) + (push '(vertical-scroll-bars . nil) initial-frame-alist)) + ((member argi '("-q" "-no-init-file")) + (setq init-file-user nil)) + ((member argi '("-u" "-user")) + (setq init-file-user (or argval (pop args)) + argval nil)) + ((equal argi "-no-site-file") + (setq site-run-file nil)) + ((equal argi "-debug-init") + (setq init-file-debug t)) + ((equal argi "-iconic") + (push '(visibility . icon) initial-frame-alist)) + ((member argi '("-nbc" "-no-blinking-cursor")) + (setq no-blinking-cursor t)) + ;; Push the popped arg back on the list of arguments. + (t + (push argi args) + (setq done t))) + ;; Was argval set but not used? + (and argval + (error "Option `%s' doesn't allow an argument" argi)))) + + ;; Re-attach the --display arg. + (and display-arg (setq args (append display-arg args))) + + ;; Re-attach the program name to the front of the arg list. + (and command-line-args + (setcdr command-line-args args))) + + ;; 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 + ;; args so that -Q can influence this initialization. + (condition-case error + (unless noninteractive + (if (and initial-window-system + (not (featurep + (intern + (concat (symbol-name initial-window-system) "-win"))))) + (error "Unsupported window system `%s'" initial-window-system)) + ;; Process window-system specific command line parameters. + (setq command-line-args + (funcall + (gui-method handle-args-function initial-window-system) + command-line-args)) + ;; Initialize the window system. (Open connection, etc.) + (funcall + (gui-method window-system-initialization initial-window-system)) + (put initial-window-system 'window-system-initialized t)) + ;; If there was an error, print the error message and exit. + (error + (princ + (if (eq (car error) 'error) + (apply 'concat (cdr error)) + (if (memq 'file-error (get (car error) 'error-conditions)) + (format "%s: %s" + (nth 1 error) + (mapconcat (lambda (obj) (prin1-to-string obj t)) + (cdr (cdr error)) ", ")) + (format "%s: %s" + (get (car error) 'error-message) (mapconcat (lambda (obj) (prin1-to-string obj t)) - (cdr (cdr error)) ", ")) - (format "%s: %s" - (get (car error) 'error-message) - (mapconcat (lambda (obj) (prin1-to-string obj t)) - (cdr error) ", ")))) - 'external-debugging-output) - (terpri 'external-debugging-output) - (setq initial-window-system nil) - (kill-emacs))) - - (run-hooks 'before-init-hook) - - ;; Under X, create the X frame and delete the terminal frame. - (unless (daemonp) - (if (or noninteractive emacs-basic-display) - (setq menu-bar-mode nil - tool-bar-mode nil - no-blinking-cursor t)) - (frame-initialize)) - - (when (fboundp 'x-create-frame) - ;; Set up the tool-bar (even in tty frames, since Emacs might open a - ;; graphical frame later). - (unless noninteractive - (tool-bar-setup))) - - ;; Turn off blinking cursor if so specified in X resources. This is here - ;; only because all other settings of no-blinking-cursor are here. - (unless (or noninteractive - emacs-basic-display - (and (memq window-system '(x w32 ns)) - (not (member (x-get-resource "cursorBlink" "CursorBlink") - '("no" "off" "false" "0"))))) - (setq no-blinking-cursor t)) - - ;; Re-evaluate predefined variables whose initial value depends on - ;; the runtime context. - (mapc 'custom-reevaluate-setting - ;; Initialize them in the same order they were loaded, in case there - ;; are dependencies between them. - (prog1 (nreverse custom-delayed-init-variables) - (setq custom-delayed-init-variables nil))) - - (normal-erase-is-backspace-setup-frame) - - ;; Register default TTY colors for the case the terminal hasn't a - ;; terminal init file. We do this regardless of whether the terminal - ;; supports colors or not and regardless the current display type, - ;; since users can connect to color-capable terminals and also - ;; switch color support on or off in mid-session by setting the - ;; tty-color-mode frame parameter. - ;; Exception: the `pc' ``window system'' has only 16 fixed colors, - ;; and they are already set at this point by a suitable function in - ;; window-system-initialization-alist. - (or (eq initial-window-system 'pc) - (tty-register-default-colors)) - - (let ((old-scalable-fonts-allowed scalable-fonts-allowed) - (old-face-ignored-fonts face-ignored-fonts)) - - ;; Run the site-start library if it exists. The point of this file is - ;; that it is run before .emacs. There is no point in doing this after - ;; .emacs; that is useless. - ;; Note that user-init-file is nil at this point. Code that might - ;; be loaded from site-run-file and wants to test if -q was given - ;; should check init-file-user instead, since that is already set. - ;; See cus-edit.el for an example. - (if site-run-file - (load site-run-file t t)) - - ;; Sites should not disable this. Only individuals should disable - ;; 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)) - (orig-enable-multibyte (default-value 'enable-multibyte-characters))) - (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 - "`_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 - ;; Postpone displaying the warning until all hooks - ;; in `after-init-hook' like `desktop-read' will finalize - ;; possible changes in the window configuration. - (add-hook - 'after-init-hook - (lambda () - (display-warning - 'initialization - (format "An error occurred while loading `%s':\n\n%s%s%s\n\n\ + (cdr error) ", ")))) + 'external-debugging-output) + (terpri 'external-debugging-output) + (setq initial-window-system nil) + (kill-emacs))) + + (run-hooks 'before-init-hook) + + ;; Under X, create the X frame and delete the terminal frame. + (unless (daemonp) + (if (or noninteractive emacs-basic-display) + (setq menu-bar-mode nil + tool-bar-mode nil + no-blinking-cursor t)) + (frame-initialize)) + + (when (fboundp 'x-create-frame) + ;; Set up the tool-bar (even in tty frames, since Emacs might open a + ;; graphical frame later). + (unless noninteractive + (tool-bar-setup))) + + ;; Turn off blinking cursor if so specified in X resources. This is here + ;; only because all other settings of no-blinking-cursor are here. + (unless (or noninteractive + emacs-basic-display + (and (memq window-system '(x w32 ns)) + (not (member (x-get-resource "cursorBlink" "CursorBlink") + '("no" "off" "false" "0"))))) + (setq no-blinking-cursor t)) + + ;; Re-evaluate predefined variables whose initial value depends on + ;; the runtime context. + (mapc 'custom-reevaluate-setting + ;; Initialize them in the same order they were loaded, in case there + ;; are dependencies between them. + (prog1 (nreverse custom-delayed-init-variables) + (setq custom-delayed-init-variables nil))) + + (normal-erase-is-backspace-setup-frame) + + ;; Register default TTY colors for the case the terminal hasn't a + ;; terminal init file. We do this regardless of whether the terminal + ;; supports colors or not and regardless the current display type, + ;; since users can connect to color-capable terminals and also + ;; switch color support on or off in mid-session by setting the + ;; tty-color-mode frame parameter. + ;; Exception: the `pc' ``window system'' has only 16 fixed colors, + ;; and they are already set at this point by a suitable function in + ;; window-system-initialization-alist. + (or (eq initial-window-system 'pc) + (tty-register-default-colors)) + + (let ((old-scalable-fonts-allowed scalable-fonts-allowed) + (old-face-ignored-fonts face-ignored-fonts)) + + ;; Run the site-start library if it exists. The point of this file is + ;; that it is run before .emacs. There is no point in doing this after + ;; .emacs; that is useless. + ;; Note that user-init-file is nil at this point. Code that might + ;; be loaded from site-run-file and wants to test if -q was given + ;; should check init-file-user instead, since that is already set. + ;; See cus-edit.el for an example. + (if site-run-file + (load site-run-file t t)) + + ;; Sites should not disable this. Only individuals should disable + ;; 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)) + (orig-enable-multibyte (default-value 'enable-multibyte-characters))) + (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 + "`_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) + + ;; Don't load `~/.emacs' if EMACS_USER_DIRECTORY was set + (unless user-emacs-directory--from-env + (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 + (if user-emacs-directory--from-env + user-emacs-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 + ;; Postpone displaying the warning until all hooks + ;; in `after-init-hook' like `desktop-read' will finalize + ;; possible changes in the window configuration. + (add-hook + 'after-init-hook + (lambda () + (display-warning + 'initialization + (format "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)) - t) - (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)) - (unless (or (default-value 'enable-multibyte-characters) - (eq orig-enable-multibyte (default-value - 'enable-multibyte-characters))) - ;; Init file changed to unibyte. Reset existing multibyte - ;; buffers (probably *scratch*, *Messages*, *Minibuf-0*). - ;; Arguably this should only be done if they're free of - ;; multibyte characters. - (mapc (lambda (buffer) - (with-current-buffer buffer - (if enable-multibyte-characters - (set-buffer-multibyte nil)))) - (buffer-list)) - ;; Also re-set the language environment in case it was - ;; originally done before unibyte was set and is sensitive to - ;; unibyte (display table, terminal coding system &c). - (set-language-environment current-language-environment))) - - ;; Do this here in case the init file sets mail-host-address. - (if (equal user-mail-address "") - (setq user-mail-address (or (getenv "EMAIL") - (concat (user-login-name) "@" - (or mail-host-address - (system-name)))))) - - ;; If parameter have been changed in the init file which influence - ;; face realization, clear the face cache so that new faces will - ;; be realized. - (unless (and (eq scalable-fonts-allowed old-scalable-fonts-allowed) - (eq face-ignored-fonts old-face-ignored-fonts)) - (clear-face-cache))) + user-init-file + (get (car error) 'error-message) + (if (cdr error) ": " "") + (mapconcat (lambda (s) (prin1-to-string s t)) + (cdr error) ", ")) + :warning)) + t) + (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)) + (unless (or (default-value 'enable-multibyte-characters) + (eq orig-enable-multibyte (default-value + 'enable-multibyte-characters))) + ;; Init file changed to unibyte. Reset existing multibyte + ;; buffers (probably *scratch*, *Messages*, *Minibuf-0*). + ;; Arguably this should only be done if they're free of + ;; multibyte characters. + (mapc (lambda (buffer) + (with-current-buffer buffer + (if enable-multibyte-characters + (set-buffer-multibyte nil)))) + (buffer-list)) + ;; Also re-set the language environment in case it was + ;; originally done before unibyte was set and is sensitive to + ;; unibyte (display table, terminal coding system &c). + (set-language-environment current-language-environment))) + + ;; Do this here in case the init file sets mail-host-address. + (if (equal user-mail-address "") + (setq user-mail-address (or (getenv "EMAIL") + (concat (user-login-name) "@" + (or mail-host-address + (system-name)))))) + + ;; If parameter have been changed in the init file which influence + ;; face realization, clear the face cache so that new faces will + ;; be realized. + (unless (and (eq scalable-fonts-allowed old-scalable-fonts-allowed) + (eq face-ignored-fonts old-face-ignored-fonts)) + (clear-face-cache)))) ;; If any package directory exists, initialize the package system. (and user-init-file -- 1.7.2.5