diff options
Diffstat (limited to 'lisp/startup.el')
-rw-r--r-- | lisp/startup.el | 401 |
1 files changed, 204 insertions, 197 deletions
diff --git a/lisp/startup.el b/lisp/startup.el index 9d16b59defd..4105c1db2d6 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -123,15 +123,17 @@ the remaining command-line args are in the variable `command-line-args-left'.") (defvar command-line-args-left nil "List of command-line args not yet processed.") -(defvaralias 'argv 'command-line-args-left - "List of command-line args not yet processed. -This is a convenience alias, so that one can write \(pop argv) +(with-no-warnings + (defvaralias 'argv 'command-line-args-left + "List of command-line args not yet processed. +This is a convenience alias, so that one can write (pop argv) inside of --eval command line arguments in order to access -following arguments.") +following arguments.")) (internal-make-var-non-special 'argv) -(defvar argi nil - "Current command-line argument.") +(with-no-warnings + (defvar argi nil + "Current command-line argument.")) (internal-make-var-non-special 'argi) (defvar command-line-functions nil ;; lrs 7/31/89 @@ -312,6 +314,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 @@ -781,7 +789,7 @@ to prepare for opening the first frame (e.g. open a connection to an X server)." argval (let ((case-fold-search t) i) - (setq argval (invocation-name)) + (setq argval (copy-sequence invocation-name)) ;; Change any . or * characters in name to ;; hyphens, so as to emulate behavior on X. @@ -870,6 +878,92 @@ 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)) + (condition-case-unless-debug error + (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)))) + (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 +1115,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,170 +1285,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)) - (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 - ,(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)) - (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))) + (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 @@ -1313,33 +1347,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 |