XEmacs 21.2.41 "Polyhymnia".
[chise/xemacs-chise.git.1] / lisp / startup.el
index 8c2686e..27298b9 100644 (file)
@@ -77,9 +77,9 @@ The frame system uses this to open frames to display messages while
 XEmacs loads the user's initialization file.")
 
 (defvar after-init-hook nil
-  "*Functions to call after loading the init file (`.emacs').
+  "*Functions to call after loading the init file.
 The call is not protected by a condition-case, so you can set `debug-on-error'
-in `.emacs', and put all the actual code on `after-init-hook'.")
+in the init file, and put all the actual code on `after-init-hook'.")
 
 (defvar term-setup-hook nil
   "*Functions to be called after loading terminal-specific Lisp code.
@@ -107,23 +107,36 @@ the user's init file.")
 (defvar user-init-directory-base ".xemacs"
   "Base of directory where user-installed init files may go.")
 
-(defvar user-init-file-base-list (append
-                                 '(".emacs.elc" ".emacs.el" ".emacs")
-                                 (and (eq system-type 'windows-nt)
-                                      '("_emacs.elc" "_emacs.el" "_emacs")))
-  "List of allowed init files.  The first one found takes precedence.")
-
 (defvar user-init-directory
   (file-name-as-directory
    (paths-construct-path (list "~" user-init-directory-base)))
   "Directory where user-installed init files may go.")
 
+(defvar user-init-file-base "init.el"
+  "Default name of the user init file if uncompiled.
+This should be used for migration purposes only.")
+
+(defvar user-init-file-base-list '("init.elc" "init.el")
+  "List of allowed init files in the user's init directory.
+The first one found takes precedence.")
+
+(defvar user-home-init-file-base-list
+  (append '(".emacs.elc" ".emacs.el" ".emacs")
+         (and (eq system-type 'windows-nt)
+              '("_emacs.elc" "_emacs.el" "_emacs")))
+  "List of allowed init files in the user's home directory.
+The first one found takes precedence.")
+
+(defvar load-home-init-file nil
+  "Non-nil if XEmacs should load the init file from the home directory.
+Otherwise, XEmacs will offer migration to the init directory.")
+
 (defvar load-user-init-file-p t
   "Non-nil if XEmacs should load the user's init file.")
 
 ;; #### called `site-run-file' in FSFmacs
 
-(defvar site-start-file (purecopy "site-start")
+(defvar site-start-file "site-start"
   "File containing site-wide run-time initializations.
 This file is loaded at run-time before `.emacs'.  It
 contains inits that need to be in place for the entire site, but
@@ -146,18 +159,17 @@ is less convenient.")
 ;;We do that if this regexp matches the locale name
 ;;specified by the LC_ALL, LC_CTYPE and LANG environment variables.")
 
-(defvar mail-host-address nil
-  "*Name of this machine, for purposes of naming users.")
+(defcustom mail-host-address nil
+  "*Name of this machine, for purposes of naming users."
+  :type 'string
+  :group 'mail)
 
-(defvar user-mail-address nil
+(defcustom user-mail-address nil
   "*Full mailing address of this user.
 This is initialized based on `mail-host-address',
-after your init file is read, in case it sets `mail-host-address'.")
-
-(defvar auto-save-list-file-prefix "~/.saves-"
-  "Prefix for generating auto-save-list-file-name.
-Emacs's pid and the system name will be appended to
-this prefix to create a unique file name.")
+after your init file is read, in case it sets `mail-host-address'."
+  :type 'string
+  :group 'mail)
 
 (defvar init-file-debug nil)
 
@@ -173,23 +185,22 @@ after, and will not be true at any time before.")
 \f
 
 (defvar command-switch-alist
-  (purecopy
-   '(("-help"  . command-line-do-help)
-     ("-version". command-line-do-version)
-     ("-V"     . command-line-do-version)
-     ("-funcall". command-line-do-funcall)
-     ("-f"     . command-line-do-funcall)
-     ("-e"     . command-line-do-funcall-1)
-     ("-eval"  . command-line-do-eval)
-     ("-load"  . command-line-do-load)
-     ("-l"     . command-line-do-load)
-     ("-insert"        . command-line-do-insert)
-     ("-i"     . command-line-do-insert)
-     ("-kill"  . command-line-do-kill)
-     ;; Options like +35 are handled specially.
-     ;; Window-system, site, or package-specific code might add to this.
-     ;; X11 handles its options by letting Xt remove args from this list.
-     ))
+  '(("-help"   . command-line-do-help)
+    ("-version". command-line-do-version)
+    ("-V"      . command-line-do-version)
+    ("-funcall". command-line-do-funcall)
+    ("-f"      . command-line-do-funcall)
+    ("-e"      . command-line-do-funcall-1)
+    ("-eval"   . command-line-do-eval)
+    ("-load"   . command-line-do-load)
+    ("-l"      . command-line-do-load)
+    ("-insert" . command-line-do-insert)
+    ("-i"      . command-line-do-insert)
+    ("-kill"   . command-line-do-kill)
+    ;; Options like +35 are handled specially.
+    ;; Window-system, site, or package-specific code might add to this.
+    ;; X11 handles its options by letting Xt remove args from this list.
+    )
   "Alist of command-line switches.
 Elements look like (SWITCH-STRING . HANDLER-FUNCTION).
 HANDLER-FUNCTION receives switch name as sole arg;
@@ -216,6 +227,9 @@ command line options plus the following:
 In addition, the")
        "The"))
     (princ " following options are accepted:
+  -sd                   Show dump ID.  Ignored when configured without --pdump.
+  -nd                   Don't load the dump file.  Roughly like old temacs.
+                        Ignored when configured without --pdump.
   -t <device>           Use TTY <device> instead of the terminal for input
                         and output.  This implies the -nw option.
   -nw                   Inhibit the use of any window-system-specific
@@ -224,17 +238,15 @@ In addition, the")
   -debug-init           Enter the debugger if an error in the init file occurs.
   -unmapped             Do not map the initial frame.
   -no-site-file         Do not load the site-specific init file (site-start.el).
-  -no-init-file         Do not load the user-specific init file (~/.emacs).
+  -no-init-file         Do not load the user-specific init file.
   -no-early-packages   Do not process early packages.
   -no-autoloads                Do not load global symbol files (auto-autoloads) at
                        startup.  Also implies `-vanilla'.
   -vanilla             Equivalent to -q -no-site-file -no-early-packages.
   -q                    Same as -no-init-file.
   -user-init-file <file> Use <file> as init file.
-  -user-init-directory <directory> use <directory> as init directory.
+  -user-init-directory <directory> Use <directory> as init directory.
   -user <user>          Load user's init file instead of your own.
-                        Equivalent to -user-init-file ~<user>/.emacs
-                                      -user-init-directory ~<user>/.xemacs/
   -u <user>             Same as -user.\n")
    (let ((l command-switch-alist)
          (insert (lambda (&rest x)
@@ -369,11 +381,10 @@ Type ^H^H^H (Control-h Control-h Control-h) to get more help options.\n")
        (princ "\n\n" stream)))
     (when (not suppress-early-error-handler-backtrace)
       (backtrace stream t)))
+  (if (fboundp 'mswindows-message-box)
+      (mswindows-message-box "Initialization error"))
   (kill-emacs -1))
 
-(defvar lock-directory)
-(defvar superlock-file)
-
 (defun normal-top-level ()
   (if command-line-processed
       (message "Back to top level.")
@@ -424,21 +435,22 @@ Type ^H^H^H (Control-h Control-h Control-h) to get more help options.\n")
 
     (unwind-protect
        (command-line)
-      ;; Do this again, in case .emacs defined more abbreviations.
+      ;; Do this again, in case the init file defined more abbreviations.
       (setq default-directory (abbreviate-file-name default-directory))
       ;; Specify the file for recording all the auto save files of
       ;; this session.  This is used by recover-session.
-      (setq auto-save-list-file-name
-           (expand-file-name
-            (format "%s%d-%s"
-                    auto-save-list-file-prefix
-                    (emacs-pid)
-                    (system-name))))
+      (if auto-save-list-file-prefix
+         (setq auto-save-list-file-name
+               (expand-file-name
+                (format "%s%d-%s"
+                        auto-save-list-file-prefix
+                        (emacs-pid)
+                        (system-name)))))
       (run-hooks 'emacs-startup-hook)
       (and term-setup-hook
           (run-hooks 'term-setup-hook))
       (setq term-setup-hook nil)
-      ;;      ;; Modify the initial frame based on what .emacs puts into
+      ;;      ;; Modify the initial frame based on what the init file puts into
       ;;      ;; ...-frame-alist.
       (frame-notice-user-settings)
       ;;      ;;####FSFmacs junk
@@ -448,6 +460,9 @@ Type ^H^H^H (Control-h Control-h Control-h) to get more help options.\n")
       (when window-setup-hook
        (run-hooks 'window-setup-hook))
       (setq window-setup-hook nil))
+
+    (if load-user-init-file-p
+       (maybe-migrate-user-init-file))
     ;;####FSFmacs junk
     ;;      (or menubar-bindings-done
     ;;   (precompute-menubar-bindings))
@@ -531,10 +546,13 @@ Type ^H^H^H (Control-h Control-h Control-h) to get more help options.\n")
            (string= arg "-user"))
        (let* ((user (pop args))
               (home-user (concat "~" user)))
-         (setq user-init-file (find-user-init-file home-user)
-               user-init-directory (file-name-as-directory
+         (setq user-init-directory (file-name-as-directory
                                     (paths-construct-path
-                                     (list home-user user-init-directory-base))))))
+                                     (list home-user user-init-directory-base))))
+         (setq user-init-file
+               (find-user-init-file user-init-directory home-user))
+         (setq custom-file
+               (make-custom-file-name user-init-file))))
        ((string= arg "-debug-init")
        (setq init-file-debug t))
        ((string= arg "-unmapped")
@@ -638,20 +656,154 @@ If this is nil, no message will be displayed.")
            (setq term (substring term 0 hyphend))
          (setq term nil))))))
 
-(defun find-user-init-file (&optional directory)
+(defun find-user-init-directory-init-file (&optional init-directory)
+  "Determine the user's init file if in the init directory."
+  (let ((init-directory (or init-directory user-init-directory)))
+    (catch 'found
+      (dolist (file user-init-file-base-list)
+       (let ((expanded (expand-file-name file init-directory)))
+         (when (file-readable-p expanded)
+           (throw 'found expanded)))))))
+
+(defun find-user-home-directory-init-file (&optional home-directory)
+  "Determine the user's init file if in the home directory."
+  (let ((home-directory (or home-directory "~")))
+    (catch 'found
+      (dolist (file user-home-init-file-base-list)
+       (let ((expanded (expand-file-name file home-directory)))
+         (when (file-readable-p expanded)
+           (throw 'found expanded))))
+      nil)))
+
+(defun find-user-init-file (&optional init-directory home-directory)
   "Determine the user's init file."
-  (unless directory
-    (setq directory "~"))
-  (dolist (file user-init-file-base-list)
-    (let ((expanded (paths-construct-path (list directory file))))
-      (when (file-exists-p expanded)
-       (return expanded)))))
+  (if load-home-init-file
+      (find-user-home-directory-init-file home-directory)
+    (or (find-user-init-directory-init-file init-directory)
+       (find-user-home-directory-init-file home-directory))))
+
+(defun maybe-migrate-user-init-file ()
+  "Ask user if she wants to migrate the init file(s) to new location."
+  (if (and (not load-home-init-file)
+          (not (find-user-init-directory-init-file user-init-directory))
+          (stringp user-init-file)
+          (file-readable-p user-init-file))
+      (if (with-output-to-temp-buffer (help-buffer-name nil)
+           (progn
+             (princ "XEmacs recommends that the initialization code in
+")
+             (princ user-init-file)
+             (princ "
+be migrated to the ")
+             (princ user-init-directory)
+             (princ " directory.  XEmacs can
+perform the migration automatically.
+
+After the migration, init.el/init.elc holds user-written
+initialization code.  Moreover the customize settings will be in
+custom.el.
+
+You can undo the migration at any time with
+M-x maybe-unmigrate-user-init-file.
+
+If you choose not to do this now, XEmacs will not ask you this
+question in the future.  However, you can still make XEmacs
+perform the migration at any time with M-x migrate-user-init-file.")
+             (show-temp-buffer-in-current-frame standard-output)
+             (yes-or-no-p-minibuf (concat "Migrate init file to "
+                                          user-init-directory
+                                          "? "))))
+         (progn
+           (migrate-user-init-file)
+           (maybe-create-compatibility-dot-emacs))
+       (customize-save-variable 'load-home-init-file t))))
+
+(defun maybe-create-compatibility-dot-emacs ()
+  "Ask user if she wants to create a .emacs compatibility file."
+  (if (with-output-to-temp-buffer (help-buffer-name nil)
+       (progn
+         (princ "The initialization code has now been migrated to the ")
+         (princ user-init-directory)
+         (princ "directory.
+
+For backwards compatibility with, for example, older versions of XEmacs,
+XEmacs can create a special old-style .emacs file in your home
+directory which will load the relocated initialization code.")
+         (show-temp-buffer-in-current-frame standard-output)
+         (yes-or-no-p-minibuf "Create compatibility .emacs? ")))
+      (create-compatibility-dot-emacs)))
+
+(defun migrate-user-init-file ()
+  "Migrate the init file from the home directory."
+  (interactive)
+  (if (not (file-exists-p user-init-directory))
+      (progn
+       (message "Creating %s directory..." user-init-directory)
+       (make-directory user-init-directory)))
+  (message "Migrating custom file...")
+  (customize-set-value 'load-home-init-file nil)
+  (custom-migrate-custom-file (make-custom-file-name user-init-file
+                                                    'force-new))
+  (message "Moving init file...")
+  (let ((new-user-init-file (expand-file-name user-init-file-base
+                                             user-init-directory)))
+    (rename-file user-init-file new-user-init-file)
+    (setq user-init-file new-user-init-file))
+  (message "Migration done."))
+
+(defun create-compatibility-dot-emacs ()
+  "Create .emacs compatibility file for migrated setup."
+  (message "Creating .emacs compatibility file.")
+  (with-temp-file (expand-file-name ".emacs" "~")
+    (insert ";;; XEmacs backwards compatibility file\n")
+    (insert "(setq user-init-file\n")
+    (insert "      (expand-file-name \"init.el\"\n")
+    (insert "                  (expand-file-name \".xemacs\" \"~\")))\n")
+    (insert "(setq custom-file\n")
+    (insert "      (expand-file-name \"custom.el\"\n")
+    (insert "                  (expand-file-name \".xemacs\" \"~\")))\n")
+    (insert "\n")
+    (insert "(load-file user-init-file)\n")
+    (insert "(load-file custom-file)"))
+  (message "Created .emacs compatibility file."))
+
+(defun maybe-unmigrate-user-init-file ()
+  "Possibly unmigrate the user's init and custom files."
+  (interactive)
+  (let ((dot-emacs-file-name (expand-file-name ".emacs" "~")))
+    (if (and (not load-home-init-file)
+            (or (not (file-exists-p dot-emacs-file-name))
+                (yes-or-no-p-minibuf (concat "Overwrite " dot-emacs-file-name
+                                             "? "))))
+      (unmigrate-user-init-file dot-emacs-file-name))))
+
+(defun unmigrate-user-init-file (&optional target-file-name)
+  "Unmigrate the user's init and custom files."
+  (interactive)
+  (let ((target-file-name
+        (or target-file-name (expand-file-name ".emacs" "~"))))
+    (rename-file user-init-file target-file-name 'ok-if-already-exists)
+    (setq user-init-file target-file-name)
+    (let ((old-custom-file custom-file))
+      (custom-migrate-custom-file target-file-name)
+      (customize-save-variable 'load-home-init-file t)
+      (delete-file old-custom-file))))
 
 (defun load-user-init-file ()
-  "This function actually reads the init file, .emacs."
-  (if (or user-init-file
-          (setq user-init-file (find-user-init-file)))
+  "This function actually reads the init file."
+  (if (not user-init-file)
+      (setq user-init-file
+           (find-user-init-file user-init-directory)))
+  (if (and user-init-file
+          (file-readable-p user-init-file))
       (load user-init-file t t t))
+  (if (not custom-file)
+      (setq custom-file (make-custom-file-name user-init-file)))
+  (if (and custom-file
+          (or (not user-init-file)
+              (not (string= custom-file user-init-file)))
+          (file-readable-p custom-file))
+      (load custom-file t t t))
   (unless inhibit-default-init
     (let ((inhibit-startup-message nil))
       ;; Users are supposed to be told their rights.
@@ -679,8 +831,9 @@ If this is nil, no message will be displayed.")
         (if (eq init-file-debug t) 'startup init-file-debug)))
     (let ((debug-on-error debug-on-error-initial))
       (if (and load-user-init-file-p init-file-debug)
-         ;; Do this without a condition-case if the user wants to debug.
-         (load-user-init-file)
+         (progn
+           ;; Do this without a condition-case if the user wants to debug.
+           (load-user-init-file))
        (condition-case error
            (progn
              (if load-user-init-file-p
@@ -1146,18 +1299,6 @@ It's idempotent, so call this as often as you like!"
       (princ (format "Info-directory-list:\n%S\n" Info-directory-list)
             'external-debugging-output))
 
-  (if (boundp 'lock-directory)
-      (progn
-       (setq lock-directory (paths-find-lock-directory roots))
-       (setq superlock-file (paths-find-superlock-file lock-directory))
-
-       (if debug-paths
-           (progn
-             (princ (format "lock-directory:\n%S\n" lock-directory)
-                    'external-debugging-output)
-             (princ (format "superlock-file:\n%S\n" superlock-file)
-                    'external-debugging-output)))))
-
   (setq exec-directory (paths-find-exec-directory roots))
 
   (if debug-paths
@@ -1205,20 +1346,15 @@ It's idempotent, so call this as often as you like!"
     (princ (buffer-string) 'external-debugging-output)))
 
 (defun startup-setup-paths-warning ()
-  (let ((lock (if (boundp 'lock-directory) lock-directory 't))
-       (warnings '()))
-    (if (and (stringp lock) (null (file-directory-p lock)))
-       (setq lock nil))
+  (let ((warnings '()))
     (cond
      ((null (and lisp-directory exec-directory data-directory doc-directory
-                load-path
-                lock))
+                load-path))
       (save-excursion
        (set-buffer (get-buffer-create " *warning-tmp*"))
        (erase-buffer)
        (buffer-disable-undo (current-buffer))
        (if (null lisp-directory) (push "lisp-directory" warnings))
-       (if (null lock)           (push "lock-directory" warnings))
        (if (null exec-directory) (push "exec-directory" warnings))
        (if (null data-directory) (push "data-directory" warnings))
        (if (null doc-directory)  (push "doc-directory"  warnings))