mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-24 07:20:37 +00:00
8903106bb7
* lisp/subr.el (if-let*, when-let*, if-let, when-let): Mark if-let and when-let obsolete (bug#73853 and elsewhere). Move docstring text around so that if-let* and when-let* descriptions no longer refer to if-let and when-let. * etc/NEWS: Announce the change. * admin/admin.el (reminder-for-release-blocking-bugs): * doc/misc/erc.texi (display-buffer): * lisp/ansi-color.el (ansi-color-apply) (ansi-color--face-vec-face): * lisp/ansi-osc.el (ansi-osc-apply-on-region) (ansi-osc-hyperlink): * lisp/arc-mode.el (archive-goto-file) (archive-next-file-displayer): * lisp/auth-source-pass.el (auth-source-pass-search) (auth-source-pass--parse-data) (auth-source-pass--find-match-many): * lisp/autorevert.el (auto-revert-notify-rm-watch): * lisp/buff-menu.el (Buffer-menu-unmark-all-buffers) (Buffer-menu-group-by-root): * lisp/calendar/parse-time.el (parse-iso8601-time-string): * lisp/cedet/pulse.el (pulse-tick): * lisp/comint.el (comint--fontify-input-ppss-flush-indirect) (comint--intersect-regions): * lisp/completion-preview.el (completion-preview--try-table) (completion-preview--capf-wrapper, completion-preview--update): * lisp/cus-edit.el (setopt--set) (custom-dirlocals-maybe-update-cons, custom-dirlocals-validate): * lisp/custom.el (load-theme): * lisp/descr-text.el (describe-char): * lisp/desktop.el (desktop--emacs-pid-running-p): * lisp/dired-x.el (menu): * lisp/dired.el (dired-font-lock-keywords) (dired-insert-directory, dired--insert-disk-space, dired-mode): * lisp/dnd.el (dnd-handle-multiple-urls): * lisp/dom.el (dom-remove-attribute): * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): * lisp/emacs-lisp/bytecomp.el (bytecomp--custom-declare): * lisp/emacs-lisp/comp-common.el (comp-function-type-spec): * lisp/emacs-lisp/comp-cstr.el (comp--all-classes) (comp-cstr-set-range-for-arithm, comp--cstr-union-1-no-mem) (comp-cstr-intersection-no-mem, comp-cstr-fixnum-p) (comp-cstr-type-p): * lisp/emacs-lisp/comp-run.el (comp-subr-trampoline-install) (native--compile-async): * lisp/emacs-lisp/comp.el (comp--get-function-cstr) (comp--function-pure-p, comp--intern-func-in-ctxt) (comp--addr-to-bb-name, comp--emit-assume, comp--maybe-add-vmvar) (comp--add-call-cstr, comp--compute-dominator-tree) (comp--dom-tree-walker, comp--ssa-rename) (comp--function-call-maybe-fold, comp--fwprop-call) (comp--call-optim-func): * lisp/emacs-lisp/edebug.el (edebug-global-prefix) (edebug-remove-instrumentation): * lisp/emacs-lisp/eieio.el (initialize-instance): * lisp/emacs-lisp/ert-x.el (ert-resource-directory): * lisp/emacs-lisp/ert.el (ert--expand-should-1) (ert-test-location, ert-write-junit-test-report) (ert-test--erts-test): * lisp/emacs-lisp/icons.el (icon-complete-spec, icon-string) (icons--create): * lisp/emacs-lisp/lisp-mode.el (lisp--local-defform-body-p): * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--make-autoload) (loaddefs-generate--parse-file): * lisp/emacs-lisp/multisession.el (multisession-edit-mode--revert, multisession-edit-value): * lisp/emacs-lisp/package-vc.el (package-vc--read-archive-data) (package-vc--version, package-vc--clone): * lisp/emacs-lisp/package.el (package--reload-previously-loaded): * lisp/emacs-lisp/pp.el (pp--insert-lisp): * lisp/emacs-lisp/subr-x.el (add-display-text-property): * lisp/emacs-lisp/tabulated-list.el (tabulated-list-print): * lisp/emacs-lisp/timer.el (run-at-time): * lisp/emacs-lisp/vtable.el (vtable-goto-table) (vtable-goto-column, vtable-update-object, vtable--insert-line) (vtable--compute-widths, vtable--make-keymap): * lisp/emacs-lisp/warnings.el (display-warning): * lisp/epa-file.el (epa-file-insert-file-contents): * lisp/epa.el (epa-show-key): * lisp/erc/erc-backend.el (erc--split-line, erc--conceal-prompt) (PRIVMSG, erc--get-isupport-entry): * lisp/erc/erc-button.el (erc-button-add-nickname-buttons) (erc--button-next): * lisp/erc/erc-common.el (erc--find-group): * lisp/erc/erc-fill.el (erc-fill, erc-fill-static) (erc-fill--wrap-escape-hidden-speaker) (erc-fill--wrap-unmerge-on-date-stamp) (erc-fill--wrap-massage-initial-message-post-clear) (erc-fill-wrap, erc-fill--wrap-rejigger-region): * lisp/erc/erc-goodies.el (erc--scrolltobottom-all) (erc--keep-place-indicator-on-window-buffer-change) (keep-place-indicator, erc--keep-place-indicator-adjust-on-clear) (erc-keep-place-move, erc--command-indicator-display): * lisp/erc/erc-ibuffer.el (erc-members): * lisp/erc/erc-join.el (erc-join--remove-requested-channel) (erc-autojoin--join): * lisp/erc/erc-networks.el (erc-networks--id-qualifying-init-parts, erc-networks--id-reload) (erc-networks--id-ensure-comparable) (erc-networks--reclaim-orphaned-target-buffers) (erc-networks--server-select): * lisp/erc/erc-nicks.el (erc-nicks-invert) (erc-nicks--redirect-face-widget-link, erc-nicks--highlight) (erc-nicks--highlight-button) (erc-nicks--list-faces-help-button-action, erc-nicks-list-faces) (erc-nicks-refresh, erc-nicks--colors-from-faces) (erc-nicks--track-prioritize) (erc-nicks--remember-face-for-track): * lisp/erc/erc-notify.el (querypoll, erc--querypoll-get-next) (erc--querypoll-on-352, erc--querypoll-send): * lisp/erc/erc-sasl.el (erc-sasl--read-password): * lisp/erc/erc-services.el (erc-services-issue-ghost-and-retry-nick): * lisp/erc/erc-speedbar.el (erc-speedbar--ensure, nickbar) (erc-speedbar-toggle-nicknames-window-lock) (erc-speedbar--compose-nicks-face): * lisp/erc/erc-stamp.el (erc-stamp--recover-on-reconnect) (erc-stamp-prefix-log-filter, erc--conceal-prompt) (erc--insert-timestamp-left, erc-insert-timestamp-right) (erc-stamp--defer-date-insertion-on-post-modify) (erc-insert-timestamp-left-and-right) (erc-stamp--redo-right-stamp-post-clear) (erc-stamp--reset-on-clear, erc-stamp--dedupe-date-stamps): * lisp/erc/erc-status-sidebar.el (bufbar) (erc-status-sidebar-prefer-target-as-name) (erc-status-sidebar-default-allsort, erc-status-sidebar-click): * lisp/erc/erc-track.el (erc-track--shortened-names-get) (erc-track--setup, erc-track--select-mode-line-face) (erc-track-modified-channels, erc-track--collect-faces-in) (erc-track--switch-buffer, erc-track--replace-killed-buffer): * lisp/erc/erc-truncate.el (erc-truncate--setup) (erc-truncate-buffer): * lisp/erc/erc.el (erc--ensure-query-member) (erc--ensure-query-members, erc--remove-channel-users-but) (erc--cusr-change-status, erc--find-mode, erc--update-modules) (erc-log-irc-protocol, erc--refresh-prompt) (erc--restore-important-text-props) (erc--order-text-properties-from-hash, erc-send-input-line) (erc-cmd-IGNORE, erc--unignore-user, erc-cmd-QUERY) (erc-cmd-BANLIST, erc--speakerize-nick) (erc--format-speaker-input-message, erc-channel-receive-names) (erc-send-current-line, erc-format-target-and/or-network) (erc-kill-buffer-function, erc-restore-text-properties) (erc--get-eq-comparable-cmd): * lisp/eshell/em-alias.el (eshell-maybe-replace-by-alias--which) (eshell-maybe-replace-by-alias): * lisp/eshell/em-glob.el (eshell-glob-convert): * lisp/eshell/em-pred.el (eshell-pred-user-or-group) (eshell-pred-file-time, eshell-pred-file-type) (eshell-pred-file-mode, eshell-pred-file-links) (eshell-pred-file-size): * lisp/eshell/em-prompt.el (eshell-forward-paragraph) (eshell-next-prompt): * lisp/eshell/esh-arg.el (eshell-resolve-current-argument): * lisp/eshell/esh-cmd.el (eshell-do-eval, eshell/which) (eshell-plain-command--which, eshell-plain-command): * lisp/eshell/esh-io.el (eshell-duplicate-handles) (eshell-protect-handles, eshell-get-target, eshell-close-target): * lisp/eshell/esh-proc.el (eshell-sentinel): * lisp/eshell/esh-var.el (eshell-parse-variable-ref) (eshell-get-variable, eshell-set-variable): * lisp/faces.el (face-at-point): * lisp/ffap.el (ffap-in-project): * lisp/filenotify.el (file-notify--rm-descriptor): * lisp/files-x.el (read-dir-locals-file) (connection-local-update-profile-variables) (connection-local-value): * lisp/files.el (file-remote-p, abbreviate-file-name) (set-auto-mode, hack-local-variables) (revert-buffer-restore-read-only): * lisp/find-dired.el (find-dired-sort-by-filename): * lisp/font-lock.el (font-lock--filter-keywords): * lisp/gnus/gnus-art.el (article-emojize-symbols): * lisp/gnus/gnus-int.el (gnus-close-server): * lisp/gnus/gnus-search.el (gnus-search-transform) (gnus-search-indexed-parse-output, gnus-search-server-to-engine): * lisp/gnus/gnus-sum.el (gnus-collect-urls, gnus-shorten-url): * lisp/gnus/gnus.el (gnus-check-backend-function): * lisp/gnus/message.el (message-send-mail): * lisp/gnus/mml.el (mml-generate-mime, mml-insert-mime-headers): * lisp/gnus/nnatom.el (nnatom--read-feed, nnatom--read-article) (nnatom--read-article-or-group-authors, nnatom--read-publish) (nnatom--read-update, nnatom--read-links): * lisp/gnus/nnfeed.el (nnfeed--read-server, nnfeed--write-server) (nnfeed--parse-feed, nnfeed--group-data, nnfeed-retrieve-article) (nnfeed-retrieve-headers, nnfeed--print-part) (nnfeed-request-article, nnfeed-request-group) (nnfeed-request-list, nnfeed--group-description) (nnfeed-request-group-description) (nnfeed-request-list-newsgroups, nnfeed-request-rename-group): * lisp/gnus/nnmh.el (nnmh-update-gnus-unreads): * lisp/help-fns.el (help-find-source) (help-fns--insert-menu-bindings, help-fns--mention-first-release) (help-fns--mention-shortdoc-groups) (help-fns--customize-variable-version) (help-fns--face-custom-version-info, describe-mode): * lisp/help-mode.el (help-make-xrefs): * lisp/help.el (help-key-description, help--describe-command): * lisp/hfy-cmap.el (htmlfontify-load-rgb-file): * lisp/ibuf-ext.el (ibuffer-jump-to-filter-group) (ibuffer-kill-filter-group, ibuffer-kill-line) (ibuffer-save-filter-groups, ibuffer-save-filters, filename) (basename, file-extension, ibuffer-diff-buffer-with-file-1) (ibuffer-mark-by-file-name-regexp) (ibuffer-mark-by-content-regexp): * lisp/ibuf-macs.el (ibuffer-aif, ibuffer-awhen): * lisp/ibuffer.el (ibuffer-mouse-toggle-mark) (ibuffer-toggle-marks, ibuffer-mark-interactive) (ibuffer-compile-format, process, ibuffer-map-lines): * lisp/image.el (image--compute-map) (image--compute-original-map): * lisp/image/exif.el (exif-parse-buffer): * lisp/image/image-converter.el (image-convert-p, image-convert) (image-converter--find-converter): * lisp/image/image-dired-util.el (image-dired-file-name-at-point): * lisp/image/image-dired.el (image-dired-track-original-file) (image-dired--on-file-in-dired-buffer) (image-dired--with-thumbnail-buffer) (image-dired-jump-original-dired-buffer) (image-dired--slideshow-step, image-dired-display-image): * lisp/image/wallpaper.el (wallpaper--init-action-kill) (wallpaper--find-setter, wallpaper--find-command) (wallpaper--find-command-args, wallpaper--x-monitor-name): * lisp/info-look.el (info-lookup-interactive-arguments) (info-complete)::(:mode): * lisp/info.el (info-pop-to-buffer, Info-read-node-name-1): * lisp/international/emoji.el (emoji--adjust-displayable-1) (emoji--add-recent): * lisp/jsonrpc.el (jsonrpc--call-deferred) (jsonrpc--process-sentinel, jsonrpc--remove): * lisp/keymap.el (keymap-local-lookup): * lisp/mail/emacsbug.el (report-emacs-bug-hook) (submit-emacs-patch): * lisp/mail/ietf-drums.el (ietf-drums-parse-addresses): * lisp/mail/mailclient.el (mailclient-send-it): * lisp/mail/rfc6068.el (rfc6068-parse-mailto-url): * lisp/mail/undigest.el (rmail-digest-parse-mixed-mime): * lisp/minibuffer.el (completion-metadata-get) (completions--after-change) (minibuffer-visible-completions--filter): * lisp/net/browse-url.el (browse-url-url-at-point) (browse-url-file-url, browse-url-emacs): * lisp/net/dbus.el (dbus-byte-array-to-string) (dbus-monitor-goto-serial): * lisp/net/dictionary.el (dictionary-search): * lisp/net/eww.el (eww--download-directory) (eww-auto-rename-buffer, eww-open-in-new-buffer, eww-submit) (eww-follow-link, eww-read-alternate-url) (eww-copy-alternate-url): * lisp/net/goto-addr.el (goto-address-at-point): * lisp/net/mailcap.el (mailcap-mime-info): * lisp/net/rcirc.el (rcirc, rcirc-connect, rcirc-send-string) (rcirc-kill-buffer-hook, rcirc-print, rcirc-when) (rcirc-color-attributes, rcirc-handler-NICK) (rcirc-handler-TAGMSG, rcirc-handler-BATCH): * lisp/net/shr.el (shr-descend, shr-adaptive-fill-function) (shr-correct-dom-case, shr-tag-a): * lisp/net/sieve.el (sieve-manage-quit): * lisp/outline.el (outline-cycle-buffer): * lisp/pcmpl-git.el (pcmpl-git--tracked-file-predicate): * lisp/proced.el (proced-auto-update-timer): * lisp/progmodes/bug-reference.el (bug-reference-try-setup-from-vc): * lisp/progmodes/c-ts-common.el (c-ts-common--fill-paragraph): * lisp/progmodes/c-ts-mode.el (c-ts-mode--preproc-offset) (c-ts-mode--anchor-prev-sibling, c-ts-mode-indent-defun): * lisp/progmodes/compile.el (compilation-error-properties) (compilation-find-file-1): * lisp/progmodes/eglot.el (eglot--check-object) (eglot--read-server, eglot-upgrade-eglot) (eglot-handle-notification, eglot--CompletionParams) (eglot-completion-at-point, eglot--sig-info) (eglot-register-capability): * lisp/progmodes/elisp-mode.el (emacs-lisp-native-compile-and-load) (elisp-eldoc-var-docstring-with-value): * lisp/progmodes/erts-mode.el (erts-mode--goto-start-of-test): * lisp/progmodes/flymake.el (flymake--update-eol-overlays) (flymake-eldoc-function): * lisp/progmodes/gdb-mi.el (gdb-breakpoints-list-handler-custom) (gdb-frame-handler): * lisp/progmodes/go-ts-mode.el (go-ts-mode-docstring) (go-ts-mode--comment-on-previous-line-p) (go-ts-mode--get-test-regexp-at-point) (go-ts-mode-test-this-file): * lisp/progmodes/grep.el (lgrep, rgrep-default-command) (grep-file-at-point): * lisp/progmodes/perl-mode.el (perl--end-of-format-p): * lisp/progmodes/php-ts-mode.el (php-ts-mode--anchor-prev-sibling, php-ts-mode--indent-defun): * lisp/progmodes/project.el (project--other-place-command) (project--find-default-from, project--transplant-file-name) (project-prefixed-buffer-name, project--remove-from-project-list) (project-prompt-project-name, project-remember-projects-under) (project--switch-project-command) (project-uniquify-dirname-transform, project-mode-line-format): * lisp/progmodes/python.el (python-font-lock-keywords-maximum-decoration) (python--treesit-fontify-union-types) (python-shell-get-process-name, python-shell-restart) (python-shell-completion-at-point, python-ffap-module-path) (python-util-comint-end-of-output-p, python--import-sources) (python-add-import, python-remove-import, python-fix-imports): * lisp/progmodes/xref.el (xref--add-log-current-defun): * lisp/repeat.el (repeat-echo-message-string): * lisp/saveplace.el (save-place-dired-hook): * lisp/server.el (server-save-buffers-kill-terminal): * lisp/shadowfile.el (shadow-make-fullname) (shadow-contract-file-name, shadow-define-literal-group): * lisp/shell.el (shell-highlight-undef-mode): * lisp/simple.el (command-completion-using-modes-p) (command-execute, file-user-uid, file-group-gid) (first-completion, last-completion, switch-to-completions): * lisp/startup.el (startup--load-user-init-file): * lisp/tab-line.el (tab-line-tabs-buffer-group-by-project): * lisp/tar-mode.el (tar-goto-file, tar-next-file-displayer): * lisp/term/android-win.el (android-encode-select-string) (gui-backend-set-selection): * lisp/term/haiku-win.el (haiku-dnd-convert-string) (haiku-select-encode-xstring, haiku-select-encode-utf-8-string): * lisp/textmodes/emacs-news-mode.el (emacs-news--buttonize): * lisp/textmodes/ispell.el (ispell-completion-at-point): * lisp/textmodes/sgml-mode.el (sgml-validate) (html-mode--complete-at-point): * lisp/textmodes/tex-mode.el (tex-recenter-output-buffer) (xref-backend-references): * lisp/thingatpt.el (thing-at-point-file-at-point) (thing-at-point-face-at-point): * lisp/thread.el (thread-list--get-status): * lisp/time.el (world-clock-copy-time-as-kill, world-clock): * lisp/touch-screen.el (touch-screen-handle-touch): * lisp/treesit.el (treesit-language-at, treesit-node-at) (treesit-node-on, treesit-buffer-root-node) (treesit-node-field-name, treesit-local-parsers-at) (treesit-local-parsers-on, treesit--cleanup-local-range-overlays) (treesit-font-lock-recompute-features) (treesit-font-lock-fontify-region, treesit-transpose-sexps) (treesit-add-log-current-defun, treesit-major-mode-setup) (treesit--explorer-refresh, treesit-install-language-grammar): * lisp/url/url.el (url-retrieve-synchronously): * lisp/vc/smerge-mode.el (smerge-diff): * lisp/vc/vc-dir.el (vc-dir): * lisp/vc/vc-dispatcher.el (vc-do-async-command): * lisp/vc/vc-git.el (vc-git-dir--branch-headers) (vc-git-dir--stash-headers, vc-git--log-edit-summary-check) (vc-git-stash-list): * lisp/vc/vc.el (vc-responsible-backend, vc-buffer-sync-fileset) (vc-clone): * lisp/visual-wrap.el (visual-wrap--apply-to-line): * lisp/wid-edit.el (widget-text) (widget-editable-list-insert-before): * lisp/window-tool-bar.el (window-tool-bar--keymap-entry-to-string): * lisp/window.el (display-buffer, display-buffer-full-frame) (window-point-context-set, window-point-context-use) (window-point-context-use-default-function): * lisp/xdg.el (xdg-current-desktop): * lisp/xwidget.el (xwidget-webkit-callback): * lisp/yank-media.el (yank-media--get-selection) (yank-media-types): * test/lisp/comint-tests.el (comint-tests/test-password-function): * test/lisp/completion-preview-tests.el (completion-preview-tests--capf): * test/lisp/cus-edit-tests.el (with-cus-edit-test): * test/lisp/erc/erc-scenarios-base-local-modules.el (-phony-sblm-): * test/lisp/erc/erc-scenarios-stamp.el (erc-scenarios-stamp--on-post-modify): * test/lisp/erc/erc-services-tests.el (erc-services-tests--asp-parse-entry): * test/lisp/erc/erc-tests.el (erc-modules--internal-property) (erc--find-mode, erc-tests--update-modules): * test/lisp/erc/resources/erc-d/erc-d-i.el (erc-d-i--parse-message): * test/lisp/erc/resources/erc-d/erc-d-t.el (erc-d-t-kill-related-buffers, erc-d-t-with-cleanup): * test/lisp/erc/resources/erc-d/erc-d-tests.el (erc-d-i--parse-message--irc-parser-tests): * test/lisp/erc/resources/erc-d/erc-d-u.el (erc-d-u--read-exchange-slowly): * test/lisp/erc/resources/erc-d/erc-d.el (erc-d--expire) (erc-d--finalize-done, erc-d--command-handle-all): * test/lisp/erc/resources/erc-scenarios-common.el (erc-scenarios-common-with-cleanup): * test/lisp/erc/resources/erc-tests-common.el (erc-tests--common-display-message) (erc-tests-common-create-subprocess): * test/lisp/ibuffer-tests.el (ibuffer-test-Bug25058): * test/lisp/international/mule-tests.el (mule-cmds-tests--ucs-names-missing-names): * test/lisp/progmodes/python-tests.el (python-tests-get-shell-interpreter) (python-tests--get-interpreter-info): * test/lisp/progmodes/ruby-ts-mode-tests.el (ruby-ts-resource-file): * test/lisp/replace-tests.el (replace-tests-with-undo): * test/src/emacs-tests.el (emacs-tests--seccomp-debug): * test/src/process-tests.el (process-tests--emacs-command) (process-tests--emacs-binary, process-tests--dump-file): * test/src/treesit-tests.el (treesit--ert-test-defun-navigation): Replace use of the now-obsolete if-let and when-let.
2982 lines
124 KiB
EmacsLisp
2982 lines
124 KiB
EmacsLisp
;;; startup.el --- process Emacs shell arguments -*- lexical-binding: t -*-
|
||
|
||
;; Copyright (C) 1985-1986, 1992, 1994-2024 Free Software Foundation,
|
||
;; Inc.
|
||
|
||
;; Maintainer: emacs-devel@gnu.org
|
||
;; Keywords: internal
|
||
;; Package: emacs
|
||
|
||
;; This file is part of GNU Emacs.
|
||
|
||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||
;; it under the terms of the GNU General Public License as published by
|
||
;; the Free Software Foundation, either version 3 of the License, or
|
||
;; (at your option) any later version.
|
||
|
||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
;; GNU General Public License for more details.
|
||
|
||
;; You should have received a copy of the GNU General Public License
|
||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||
|
||
;;; Commentary:
|
||
|
||
;; This file parses the command line and gets Emacs running. Options
|
||
;; on the command line are handled in precedence order. For priorities
|
||
;; see the structure standard_args in the emacs.c file.
|
||
|
||
;;; Code:
|
||
|
||
(setq top-level '(normal-top-level))
|
||
|
||
(defvar command-line-processed nil
|
||
"Non-nil once command line has been processed.")
|
||
|
||
(defgroup initialization nil
|
||
"Emacs start-up procedure."
|
||
:group 'environment)
|
||
|
||
(defcustom initial-buffer-choice nil
|
||
"Buffer to show after starting Emacs.
|
||
If the value is nil and `inhibit-startup-screen' is nil, show the
|
||
startup screen. If the value is a string, switch to a buffer
|
||
visiting the file or directory that the string specifies. If the
|
||
value is a function, call it with no arguments and switch to the buffer
|
||
that it returns. If t, open the `*scratch*' buffer.
|
||
|
||
When `initial-buffer-choice' is non-nil, the startup screen is
|
||
inhibited.
|
||
|
||
If you use `emacsclient' with no target file, then it obeys any
|
||
string or function value that this variable has."
|
||
:type '(choice
|
||
(const :tag "Startup screen" nil)
|
||
(directory :tag "Directory" :value "~/")
|
||
(file :tag "File" :value "~/.emacs")
|
||
;; Note sure about hard-coding this as an option...
|
||
(const :tag "Remember Mode notes buffer" remember-notes)
|
||
(function :tag "Function")
|
||
(const :tag "Lisp scratch buffer" t))
|
||
:version "23.1")
|
||
|
||
(defvaralias 'inhibit-splash-screen 'inhibit-startup-screen)
|
||
(defvaralias 'inhibit-startup-message 'inhibit-startup-screen)
|
||
|
||
(defcustom inhibit-startup-screen nil
|
||
"Non-nil inhibits the startup screen.
|
||
|
||
This is for use in your personal init file (but NOT site-start.el),
|
||
once you are familiar with the contents of the startup screen."
|
||
:type 'boolean)
|
||
|
||
(defvar startup-screen-inhibit-startup-screen nil)
|
||
|
||
;; The mechanism used to ensure that only end users can disable this
|
||
;; message is not complex. Clearly, it is possible for a determined
|
||
;; system administrator to inhibit this message anyway, but at least
|
||
;; they will do so with knowledge of why the Emacs developers think
|
||
;; this is a bad idea.
|
||
(defcustom inhibit-startup-echo-area-message nil
|
||
"Non-nil inhibits the initial startup echo area message.
|
||
|
||
The startup message is in the echo area as it provides information
|
||
about GNU Emacs and the GNU system in general, which we want all
|
||
users to see. As this is the least intrusive startup message,
|
||
this variable gets specialized treatment to prevent the message
|
||
from being disabled site-wide by systems administrators, while
|
||
still allowing individual users to do so.
|
||
|
||
Setting this variable takes effect only if you do it with the
|
||
customization buffer or if your init file contains a line of this
|
||
form:
|
||
(setq inhibit-startup-echo-area-message \"YOUR-USER-NAME\")
|
||
If your init file is byte-compiled, use the following form
|
||
instead:
|
||
(eval \\='(setq inhibit-startup-echo-area-message \"YOUR-USER-NAME\"))
|
||
Thus, someone else using a copy of your init file will see the
|
||
startup message unless he personally acts to inhibit it."
|
||
:type '(choice (const :tag "Don't inhibit")
|
||
(string :tag "Enter your user name, to inhibit")))
|
||
|
||
(defcustom inhibit-default-init nil
|
||
"Non-nil inhibits loading the `default' library."
|
||
:type 'boolean)
|
||
|
||
(defcustom inhibit-startup-buffer-menu nil
|
||
"Non-nil inhibits display of buffer list when more than 2 files are loaded."
|
||
:type 'boolean)
|
||
|
||
(defvar command-switch-alist nil
|
||
"Alist of command-line switches.
|
||
Elements look like (SWITCH-STRING . HANDLER-FUNCTION).
|
||
HANDLER-FUNCTION receives the switch string as its sole argument;
|
||
the remaining command-line args are in the variable `command-line-args-left'.")
|
||
|
||
(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.
|
||
|
||
See also `server-eval-args-left' for a similar variable which
|
||
works for invocations of \"emacsclient --eval\"."))
|
||
(internal-make-var-non-special 'argv)
|
||
|
||
(defvar command-line-args-left nil
|
||
"List of command-line args not yet processed.")
|
||
|
||
(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
|
||
"List of functions to process unrecognized command-line arguments.
|
||
Each function should access the dynamically bound variables
|
||
`argi' (the current argument) and `command-line-args-left' (the remaining
|
||
arguments). The function should return non-nil only if it recognizes and
|
||
processes `argi'. If it does so, it may consume successive arguments by
|
||
altering `command-line-args-left' to remove them.")
|
||
|
||
(defvar command-line-default-directory nil
|
||
"Default directory to use for command line arguments.
|
||
This is normally copied from `default-directory' when Emacs starts.")
|
||
|
||
;; This is here, rather than in x-win.el, so that we can ignore these
|
||
;; options when we are not using X.
|
||
(defconst command-line-x-option-alist
|
||
'(("-bw" 1 x-handle-numeric-switch border-width)
|
||
("-d" 1 x-handle-display)
|
||
("-display" 1 x-handle-display)
|
||
("-name" 1 x-handle-name-switch)
|
||
("-title" 1 x-handle-switch title)
|
||
("-T" 1 x-handle-switch title)
|
||
("-r" 0 x-handle-switch reverse t)
|
||
("-rv" 0 x-handle-switch reverse t)
|
||
("-reverse" 0 x-handle-switch reverse t)
|
||
("-reverse-video" 0 x-handle-switch reverse t)
|
||
("-fn" 1 x-handle-switch font)
|
||
("-font" 1 x-handle-switch font)
|
||
("-fs" 0 x-handle-initial-switch fullscreen fullboth)
|
||
("-fw" 0 x-handle-initial-switch fullscreen fullwidth)
|
||
("-fh" 0 x-handle-initial-switch fullscreen fullheight)
|
||
("-mm" 0 x-handle-initial-switch fullscreen maximized)
|
||
("-ib" 1 x-handle-numeric-switch internal-border-width)
|
||
("-g" 1 x-handle-geometry)
|
||
("-lsp" 1 x-handle-numeric-switch line-spacing)
|
||
("-geometry" 1 x-handle-geometry)
|
||
("-fg" 1 x-handle-switch foreground-color)
|
||
("-foreground" 1 x-handle-switch foreground-color)
|
||
("-bg" 1 x-handle-switch background-color)
|
||
("-background" 1 x-handle-switch background-color)
|
||
("-ms" 1 x-handle-switch mouse-color)
|
||
("-nbi" 0 x-handle-switch icon-type nil)
|
||
("-iconic" 0 x-handle-iconic)
|
||
("-xrm" 1 x-handle-xrm-switch)
|
||
("-cr" 1 x-handle-switch cursor-color)
|
||
("-vb" 0 x-handle-switch vertical-scroll-bars t)
|
||
("-hb" 0 x-handle-switch horizontal-scroll-bars t)
|
||
("-bd" 1 x-handle-switch)
|
||
("--border-width" 1 x-handle-numeric-switch border-width)
|
||
("--display" 1 x-handle-display)
|
||
("--name" 1 x-handle-name-switch)
|
||
("--title" 1 x-handle-switch title)
|
||
("--reverse-video" 0 x-handle-switch reverse t)
|
||
("--font" 1 x-handle-switch font)
|
||
("--fullscreen" 0 x-handle-initial-switch fullscreen fullboth)
|
||
("--fullwidth" 0 x-handle-initial-switch fullscreen fullwidth)
|
||
("--fullheight" 0 x-handle-initial-switch fullscreen fullheight)
|
||
("--maximized" 0 x-handle-initial-switch fullscreen maximized)
|
||
("--internal-border" 1 x-handle-numeric-switch internal-border-width)
|
||
("--geometry" 1 x-handle-geometry)
|
||
("--foreground-color" 1 x-handle-switch foreground-color)
|
||
("--background-color" 1 x-handle-switch background-color)
|
||
("--mouse-color" 1 x-handle-switch mouse-color)
|
||
("--no-bitmap-icon" 0 x-handle-no-bitmap-icon)
|
||
("--iconic" 0 x-handle-iconic)
|
||
("--xrm" 1 x-handle-xrm-switch)
|
||
("--cursor-color" 1 x-handle-switch cursor-color)
|
||
("--vertical-scroll-bars" 0 x-handle-switch vertical-scroll-bars t)
|
||
("--line-spacing" 1 x-handle-numeric-switch line-spacing)
|
||
("--border-color" 1 x-handle-switch border-color)
|
||
("--smid" 1 x-handle-smid)
|
||
("--parent-id" 1 x-handle-parent-id))
|
||
"Alist of X Windows options.
|
||
Each element has the form
|
||
(NAME NUMARGS HANDLER FRAME-PARAM VALUE)
|
||
where NAME is the option name string, NUMARGS is the number of arguments
|
||
that the option accepts, HANDLER is a function to call to handle the option.
|
||
FRAME-PARAM (optional) is the frame parameter this option specifies,
|
||
and VALUE is the value which is given to that frame parameter
|
||
\(most options use the argument for this, so VALUE is not present).")
|
||
|
||
(defconst command-line-ns-option-alist
|
||
'(("-NSAutoLaunch" 1 ns-ignore-1-arg)
|
||
("-NXAutoLaunch" 1 ns-ignore-1-arg)
|
||
("-macosx" 0 ignore)
|
||
("-NSHost" 1 ns-ignore-1-arg)
|
||
("-_NSMachLaunch" 1 ns-ignore-1-arg)
|
||
("-MachLaunch" 1 ns-ignore-1-arg)
|
||
("-NXOpen" 1 ns-ignore-1-arg)
|
||
("-NSOpen" 1 ns-handle-nxopen)
|
||
("-NXOpenTemp" 1 ns-ignore-1-arg)
|
||
("-NSOpenTemp" 1 ns-handle-nxopentemp)
|
||
("-GSFilePath" 1 ns-handle-nxopen)
|
||
;;("-bw" . x-handle-numeric-switch)
|
||
;;("-d" . x-handle-display)
|
||
;;("-display" . x-handle-display)
|
||
("-name" 1 x-handle-name-switch)
|
||
("-title" 1 x-handle-switch title)
|
||
("-T" 1 x-handle-switch title)
|
||
("-r" 0 x-handle-switch reverse t)
|
||
("-rv" 0 x-handle-switch reverse t)
|
||
("-reverse" 0 x-handle-switch reverse t)
|
||
("-fn" 1 x-handle-switch font)
|
||
("-font" 1 x-handle-switch font)
|
||
("-ib" 1 x-handle-numeric-switch internal-border-width)
|
||
("-g" 1 x-handle-geometry)
|
||
("-geometry" 1 x-handle-geometry)
|
||
("-fg" 1 x-handle-switch foreground-color)
|
||
("-foreground" 1 x-handle-switch foreground-color)
|
||
("-bg" 1 x-handle-switch background-color)
|
||
("-background" 1 x-handle-switch background-color)
|
||
; ("-ms" 1 x-handle-switch mouse-color)
|
||
("-itype" 0 x-handle-switch icon-type t)
|
||
("-i" 0 x-handle-switch icon-type t)
|
||
("-iconic" 0 x-handle-iconic icon-type t)
|
||
;;("-xrm" . x-handle-xrm-switch)
|
||
("-cr" 1 x-handle-switch cursor-color)
|
||
("-vb" 0 x-handle-switch vertical-scroll-bars t)
|
||
("-hb" 0 x-handle-switch horizontal-scroll-bars t)
|
||
("-bd" 1 x-handle-switch)
|
||
;; ("--border-width" 1 x-handle-numeric-switch border-width)
|
||
;; ("--display" 1 ns-handle-display)
|
||
("--name" 1 x-handle-name-switch)
|
||
("--title" 1 x-handle-switch title)
|
||
("--reverse-video" 0 x-handle-switch reverse t)
|
||
("--font" 1 x-handle-switch font)
|
||
("--internal-border" 1 x-handle-numeric-switch internal-border-width)
|
||
("--geometry" 1 x-handle-geometry)
|
||
("--foreground-color" 1 x-handle-switch foreground-color)
|
||
("--background-color" 1 x-handle-switch background-color)
|
||
("--mouse-color" 1 x-handle-switch mouse-color)
|
||
("--icon-type" 0 x-handle-switch icon-type t)
|
||
("--iconic" 0 x-handle-iconic)
|
||
;; ("--xrm" 1 ns-handle-xrm-switch)
|
||
("--cursor-color" 1 x-handle-switch cursor-color)
|
||
("--vertical-scroll-bars" 0 x-handle-switch vertical-scroll-bars t)
|
||
("--border-color" 1 x-handle-switch border-width))
|
||
"Alist of NS options.
|
||
Each element has the form
|
||
(NAME NUMARGS HANDLER FRAME-PARAM VALUE)
|
||
where NAME is the option name string, NUMARGS is the number of arguments
|
||
that the option accepts, HANDLER is a function to call to handle the option.
|
||
FRAME-PARAM (optional) is the frame parameter this option specifies,
|
||
and VALUE is the value which is given to that frame parameter
|
||
\(most options use the argument for this, so VALUE is not present).")
|
||
|
||
|
||
(defvar before-init-hook nil
|
||
"Normal hook run after handling urgent options but before loading init files.")
|
||
|
||
(defvar after-init-hook nil
|
||
"Normal hook run after initializing the Emacs session.
|
||
It is run after Emacs loads the init file, `default' library, the
|
||
abbrevs file, and additional Lisp packages (if any), and setting
|
||
the value of `after-init-time'.
|
||
|
||
There is no `condition-case' around the running of this hook;
|
||
therefore, if `debug-on-error' is non-nil, an error in one of
|
||
these functions will invoke the debugger.")
|
||
|
||
(defvar emacs-startup-hook nil
|
||
"Normal hook run after loading init files and handling the command line.")
|
||
|
||
(defvar term-setup-hook nil
|
||
"Normal hook run immediately after `emacs-startup-hook'.
|
||
In new code, there is no reason to use this instead of `emacs-startup-hook'.
|
||
If you want to execute terminal-specific Lisp code, for example
|
||
to override the definitions made by the terminal-specific file,
|
||
see `tty-setup-hook'.")
|
||
|
||
(make-obsolete-variable 'term-setup-hook
|
||
"use either `emacs-startup-hook' or \
|
||
`tty-setup-hook' instead." "24.4")
|
||
|
||
(defvar inhibit-startup-hooks nil
|
||
"Non-nil means don't run some startup hooks, because we already did.
|
||
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
|
||
keys for use under X. It is used in a fashion analogous to the
|
||
environment variable TERM.")
|
||
(make-obsolete-variable 'keyboard-type nil "28.1")
|
||
(internal-make-var-non-special 'keyboard-type)
|
||
|
||
(defvar window-setup-hook nil
|
||
"Normal hook run after loading init files and handling the command line.
|
||
This is very similar to `emacs-startup-hook'. The only difference
|
||
is that this hook runs after frame parameters have been set up in
|
||
response to any settings from your init file. Unless this matters
|
||
to you, use `emacs-startup-hook' instead. (The name of this hook
|
||
is due to historical reasons, and does not reflect its purpose very well.)")
|
||
|
||
(defcustom initial-major-mode 'lisp-interaction-mode
|
||
"Major mode command symbol to use for the initial `*scratch*' buffer."
|
||
:type 'function)
|
||
|
||
(defvar init-file-user nil
|
||
"Identity of user whose init file is or was read.
|
||
The value is nil if `-q' or `--no-init-file' was specified,
|
||
meaning do not load any init file.
|
||
|
||
Otherwise, the value may be an empty string, meaning
|
||
use the init file for the user who originally logged in,
|
||
or it may be a string containing a user's name meaning
|
||
use that person's init file.
|
||
|
||
In either of the latter cases, `(concat \"~\" init-file-user \"/\")'
|
||
evaluates to the name of the directory where the init file was
|
||
looked for.
|
||
|
||
Setting `init-file-user' does not prevent Emacs from loading
|
||
`site-start.el'. The only way to do that is to use `--no-site-file'.")
|
||
|
||
(defcustom site-run-file (purecopy "site-start")
|
||
"File containing site-wide run-time initializations.
|
||
This file is loaded at run-time before `user-init-file'. It contains
|
||
inits that need to be in place for the entire site, but which, due to
|
||
their higher incidence of change, don't make sense to put into Emacs's
|
||
dump file. Thus, the run-time load order is: 1. file described in
|
||
this variable, if non-nil; 2. `user-init-file'; 3. `default.el'.
|
||
|
||
Don't use the `site-start.el' file for things some users may not like.
|
||
Put them in `default.el' instead, so that users can more easily
|
||
override them. Users can prevent loading `default.el' with the `-q'
|
||
option or by setting `inhibit-default-init' in their own init files,
|
||
but inhibiting `site-start.el' requires `--no-site-file', which
|
||
is less convenient.
|
||
|
||
This variable is defined for customization so as to make
|
||
it visible in the relevant context. However, actually customizing it
|
||
is not allowed, since it would not work anyway. The only way to set
|
||
this variable usefully is to set it while building and dumping Emacs."
|
||
:type '(choice (const :tag "none" nil) string)
|
||
:initialize #'custom-initialize-default
|
||
:set (lambda (_variable _value)
|
||
(error "Customizing `site-run-file' does not work")))
|
||
|
||
(make-obsolete-variable 'system-name "use (system-name) instead" "25.1")
|
||
|
||
(defcustom mail-host-address nil
|
||
"The name of this machine, for use in constructing email addresses.
|
||
If this is nil, Emacs uses `system-name'."
|
||
:type '(choice (const nil) string)
|
||
:group 'mail)
|
||
|
||
(defcustom user-mail-address
|
||
(or (getenv "EMAIL")
|
||
(concat (user-login-name) "@" (or mail-host-address (system-name))))
|
||
"The email address of the current user.
|
||
This defaults to either: the value of EMAIL environment variable; or
|
||
user@host, using `user-login-name' and `mail-host-address' (or `system-name')."
|
||
:initialize #'custom-initialize-delay
|
||
:set-after '(mail-host-address)
|
||
:type 'string
|
||
:group 'mail)
|
||
|
||
(defcustom auto-save-list-file-prefix
|
||
(cond ((eq system-type 'ms-dos)
|
||
;; MS-DOS cannot have initial dot, and allows only 8.3 names
|
||
(concat user-emacs-directory "auto-save.list/_s"))
|
||
(t
|
||
(concat user-emacs-directory "auto-save-list/.saves-")))
|
||
"Prefix for generating `auto-save-list-file-name'.
|
||
This is used after reading your init file to initialize
|
||
`auto-save-list-file-name', by appending Emacs's pid and the system name,
|
||
if you have not already set `auto-save-list-file-name' yourself.
|
||
Directories in the prefix will be created if necessary.
|
||
Set this to nil if you want to prevent `auto-save-list-file-name'
|
||
from being initialized."
|
||
:initialize #'custom-initialize-delay
|
||
:type '(choice (const :tag "Don't record a session's auto save list" nil)
|
||
string)
|
||
:group 'auto-save)
|
||
|
||
(defvar emacs-basic-display nil)
|
||
|
||
(defvar init-file-debug nil)
|
||
|
||
(defvar init-file-had-error nil
|
||
"Non-nil if there was an error loading the user's init file.")
|
||
|
||
(defvar normal-top-level-add-subdirs-inode-list nil)
|
||
|
||
(defvar no-blinking-cursor nil)
|
||
|
||
(defvar pure-space-overflow nil
|
||
"Non-nil if building Emacs overflowed pure space.")
|
||
|
||
(defvar pure-space-overflow-message (purecopy "\
|
||
Warning Warning!!! Pure space overflow !!!Warning Warning
|
||
\(See the node Pure Storage in the Lisp manual for details.)\n"))
|
||
|
||
(defcustom tutorial-directory
|
||
(file-name-as-directory (expand-file-name "tutorials" data-directory))
|
||
"Directory containing the Emacs TUTORIAL files."
|
||
:group 'installation
|
||
:type 'directory
|
||
:initialize #'custom-initialize-delay)
|
||
|
||
(defun normal-top-level-add-subdirs-to-load-path ()
|
||
"Recursively add all subdirectories of `default-directory' to `load-path'.
|
||
More precisely, this uses only the subdirectories whose names
|
||
start with letters or digits; it excludes any subdirectory named `RCS'
|
||
or `CVS', and any subdirectory that contains a file named `.nosearch'."
|
||
(let (dirs
|
||
attrs
|
||
(pending (list default-directory)))
|
||
;; This loop does a breadth-first tree walk on DIR's subtree,
|
||
;; putting each subdir into DIRS as its contents are examined.
|
||
(while pending
|
||
(push (pop pending) dirs)
|
||
(let* ((this-dir (car dirs))
|
||
(contents (directory-files this-dir))
|
||
(default-directory this-dir)
|
||
(canonicalized (if (fboundp 'w32-untranslated-canonical-name)
|
||
(w32-untranslated-canonical-name this-dir))))
|
||
;; The Windows version doesn't report meaningful inode numbers, so
|
||
;; use the canonicalized absolute file name of the directory instead.
|
||
(setq attrs (or canonicalized
|
||
(file-attribute-file-identifier
|
||
(file-attributes this-dir))))
|
||
(unless (member attrs normal-top-level-add-subdirs-inode-list)
|
||
(push attrs normal-top-level-add-subdirs-inode-list)
|
||
(dolist (file contents)
|
||
(and (string-match "\\`[[:alnum:]]" file)
|
||
;; The lower-case variants of RCS and CVS are for DOS/Windows.
|
||
(not (member file '("RCS" "CVS" "rcs" "cvs")))
|
||
(file-directory-p file)
|
||
(let ((expanded (expand-file-name file)))
|
||
(or (file-exists-p (expand-file-name ".nosearch" expanded))
|
||
(setq pending (nconc pending (list expanded))))))))))
|
||
(normal-top-level-add-to-load-path (cdr (nreverse dirs)))))
|
||
|
||
(defun normal-top-level-add-to-load-path (dirs)
|
||
"This function is called from a subdirs.el file.
|
||
It assumes that `default-directory' is the directory in which the
|
||
subdirs.el file exists, and it adds to `load-path' the subdirs of
|
||
that directory as specified in DIRS. Normally the elements of
|
||
DIRS are relative."
|
||
(let ((tail load-path)
|
||
(thisdir (directory-file-name default-directory)))
|
||
(while (and tail
|
||
;;Don't go all the way to the nil terminator.
|
||
(cdr tail)
|
||
(not (equal thisdir (car tail)))
|
||
(not (and (memq system-type '(ms-dos windows-nt))
|
||
(equal (downcase thisdir) (downcase (car tail))))))
|
||
(setq tail (cdr tail)))
|
||
;;Splice the new section in.
|
||
(when tail
|
||
(setcdr tail (append (mapcar #'expand-file-name dirs) (cdr tail))))))
|
||
|
||
;; The default location for XDG-convention Emacs init files.
|
||
(defconst startup--xdg-config-default "~/.config/emacs/")
|
||
;; The location for XDG-convention Emacs init files.
|
||
(defvar startup--xdg-config-home-emacs)
|
||
|
||
;; Return the name of the init file directory for Emacs, assuming
|
||
;; XDG-DIR is the XDG location and USER-NAME is the user name. If
|
||
;; USER-NAME is nil or "", use the current user. Prefer the XDG
|
||
;; location only if the .emacs.d location does not exist.
|
||
(defun startup--xdg-or-homedot (xdg-dir user-name)
|
||
(let ((emacs-d-dir (concat "~" user-name
|
||
(if (eq system-type 'ms-dos)
|
||
"/_emacs.d/"
|
||
"/.emacs.d/"))))
|
||
(cond
|
||
((or (file-exists-p emacs-d-dir)
|
||
(if (eq system-type 'windows-nt)
|
||
(if (file-directory-p (concat "~" user-name))
|
||
(directory-files (concat "~" user-name) nil
|
||
"\\`[._]emacs\\(\\.elc?\\)?\\'"))
|
||
(file-exists-p (concat "~" init-file-user
|
||
(if (eq system-type 'ms-dos)
|
||
"/_emacs"
|
||
"/.emacs")))))
|
||
emacs-d-dir)
|
||
((file-exists-p xdg-dir)
|
||
xdg-dir)
|
||
(t emacs-d-dir))))
|
||
|
||
(defvar native-comp-eln-load-path)
|
||
(defvar native-comp-jit-compilation)
|
||
(defvar native-comp-enable-subr-trampolines)
|
||
|
||
(defvar startup--original-eln-load-path nil
|
||
"Original value of `native-comp-eln-load-path'.")
|
||
|
||
(defun startup-redirect-eln-cache (cache-directory)
|
||
"Redirect the user's eln-cache directory to CACHE-DIRECTORY.
|
||
CACHE-DIRECTORY must be a single directory, a string.
|
||
This function destructively changes `native-comp-eln-load-path'
|
||
so that its first element is CACHE-DIRECTORY. If CACHE-DIRECTORY
|
||
is not an absolute file name, it is interpreted relative
|
||
to `user-emacs-directory'.
|
||
For best results, call this function in your early-init file,
|
||
so that the rest of initialization and package loading uses
|
||
the updated value."
|
||
;; Remove the original eln-cache.
|
||
(setq native-comp-eln-load-path (cdr native-comp-eln-load-path))
|
||
;; Add the new eln-cache.
|
||
(push (expand-file-name (file-name-as-directory cache-directory)
|
||
user-emacs-directory)
|
||
native-comp-eln-load-path))
|
||
|
||
(defun startup--update-eln-cache ()
|
||
"Update the user eln-cache directory due to user customizations."
|
||
;; Don't override user customizations!
|
||
(when (equal native-comp-eln-load-path
|
||
startup--original-eln-load-path)
|
||
(startup-redirect-eln-cache "eln-cache")
|
||
(setq startup--original-eln-load-path
|
||
(copy-sequence native-comp-eln-load-path))))
|
||
|
||
(defun startup--rescale-elt-match-p (font-pattern font-object)
|
||
"Test whether FONT-OBJECT matches an element of `face-font-rescale-alist'.
|
||
FONT-OBJECT is a font-object that specifies a font to test.
|
||
FONT-PATTERN is the car of an element of `face-font-rescale-alist',
|
||
which can be either a regexp matching a font name or a font-spec."
|
||
(if (stringp font-pattern)
|
||
;; FONT-PATTERN is a regexp, we need the name of FONT-OBJECT to match.
|
||
(string-match-p font-pattern (font-xlfd-name font-object))
|
||
;; FONT-PATTERN is a font-spec.
|
||
(font-match-p font-pattern font-object)))
|
||
|
||
(defvar android-fonts-enumerated nil
|
||
"Whether or not fonts have been enumerated already.
|
||
On Android, Emacs uses this variable internally at startup.")
|
||
|
||
(defun normal-top-level ()
|
||
"Emacs calls this function when it first starts up.
|
||
It sets `command-line-processed', processes the command-line,
|
||
reads the initialization files, etc.
|
||
It is the default value of the variable `top-level'."
|
||
;; Initialize the Android font driver late.
|
||
;; This is done here because it needs the `mac-roman' coding system
|
||
;; to be loaded.
|
||
(when (and (featurep 'android)
|
||
(fboundp 'android-enumerate-fonts)
|
||
(not android-fonts-enumerated))
|
||
(funcall 'android-enumerate-fonts)
|
||
(setq android-fonts-enumerated t))
|
||
|
||
(if command-line-processed
|
||
(message internal--top-level-message)
|
||
(setq command-line-processed t)
|
||
|
||
(setq startup--xdg-config-home-emacs
|
||
(let ((xdg-config-home (getenv-internal "XDG_CONFIG_HOME")))
|
||
(if xdg-config-home
|
||
(concat xdg-config-home "/emacs/")
|
||
startup--xdg-config-default)))
|
||
(setq user-emacs-directory
|
||
(startup--xdg-or-homedot startup--xdg-config-home-emacs nil))
|
||
|
||
(when (featurep 'native-compile)
|
||
(unless (native-comp-available-p)
|
||
;; Disable deferred async compilation and trampoline synthesis
|
||
;; in this session. This is necessary if libgccjit is not
|
||
;; available on MS-Windows, but Emacs was built with
|
||
;; native-compilation support.
|
||
(setq native-comp-jit-compilation nil
|
||
native-comp-enable-subr-trampolines nil))
|
||
|
||
;; Form `native-comp-eln-load-path'.
|
||
(let ((path-env (getenv "EMACSNATIVELOADPATH")))
|
||
(when path-env
|
||
(dolist (path (split-string path-env path-separator))
|
||
(unless (string= "" path)
|
||
(push path native-comp-eln-load-path)))))
|
||
(push (expand-file-name "eln-cache/" user-emacs-directory)
|
||
native-comp-eln-load-path))
|
||
|
||
;; Look in each dir in load-path for a subdirs.el file. If we
|
||
;; find one, load it, which will add the appropriate subdirs of
|
||
;; that dir into load-path. This needs to be done before setting
|
||
;; the locale environment, because the latter might need to load
|
||
;; some support files.
|
||
;; Look for a leim-list.el file too. Loading it will register
|
||
;; available input methods.
|
||
(let ((tail load-path)
|
||
(lispdir (expand-file-name "../lisp" data-directory))
|
||
dir)
|
||
(while tail
|
||
(setq dir (car tail))
|
||
(let ((default-directory dir))
|
||
(load (expand-file-name "subdirs.el") t t t))
|
||
;; Do not scan standard directories that won't contain a leim-list.el.
|
||
;; https://lists.gnu.org/r/emacs-devel/2009-10/msg00502.html
|
||
;; (Except the preloaded one in lisp/leim.)
|
||
(or (string-prefix-p lispdir dir)
|
||
(let ((default-directory dir))
|
||
(load (expand-file-name "leim-list.el") t t t)))
|
||
;; We don't use a dolist loop and we put this "setq-cdr" command at
|
||
;; the end, because the subdirs.el files may add elements to the end
|
||
;; of load-path and we want to take it into account.
|
||
(setq tail (cdr tail))))
|
||
|
||
;; Set the default strings to display in mode line for end-of-line
|
||
;; formats that aren't native to this platform. This should be
|
||
;; done before calling set-locale-environment, as the latter might
|
||
;; use these mnemonics.
|
||
(cond
|
||
((memq system-type '(ms-dos windows-nt))
|
||
(setq eol-mnemonic-unix "(Unix)"
|
||
eol-mnemonic-mac "(Mac)"))
|
||
(t ; this is for Unix/GNU/Linux systems
|
||
(setq eol-mnemonic-dos "(DOS)"
|
||
eol-mnemonic-mac "(Mac)")))
|
||
|
||
(if (and (featurep 'android)
|
||
(eq system-type 'android)
|
||
(fboundp 'android-locale-for-system-language)
|
||
initial-window-system)
|
||
;; If Android windowing is enabled, derive a proper locale
|
||
;; from the system's language preferences. On Android, LANG
|
||
;; and LC_* must be set to one of the two locales the C
|
||
;; library supports, but, by contrast with other systems, the
|
||
;; C library locale does not reflect the configured system
|
||
;; language.
|
||
;;
|
||
;; For this reason, the locale from which Emacs derives a
|
||
;; default language environment is computed from such
|
||
;; preferences, rather than environment variables that the C
|
||
;; library refers to.
|
||
(set-locale-environment
|
||
(funcall 'android-locale-for-system-language))
|
||
(set-locale-environment nil))
|
||
;; Decode all default-directory's (probably, only *scratch* exists
|
||
;; at this point). default-directory of *scratch* is the basis
|
||
;; for many other file-name variables and directory lists, so it
|
||
;; is important to decode it ASAP.
|
||
(when locale-coding-system
|
||
(let ((coding (if (eq system-type 'windows-nt)
|
||
;; MS-Windows build converts all file names to
|
||
;; UTF-8 during startup.
|
||
'utf-8
|
||
locale-coding-system)))
|
||
(save-excursion
|
||
(dolist (elt (buffer-list))
|
||
(set-buffer elt)
|
||
(if default-directory
|
||
(setq default-directory
|
||
(if (eq system-type 'windows-nt)
|
||
;; We pass the decoded default-directory as
|
||
;; the 2nd arg to expand-file-name to make
|
||
;; sure it sees a multibyte string as the
|
||
;; default directory; this avoids the side
|
||
;; effect of returning a unibyte string from
|
||
;; expand-file-name because it still sees
|
||
;; the undecoded value of default-directory.
|
||
(let ((defdir (decode-coding-string default-directory
|
||
coding t)))
|
||
;; Convert backslashes to forward slashes.
|
||
(expand-file-name defdir defdir))
|
||
(decode-coding-string default-directory coding t))))))
|
||
|
||
;; Decode all the important variables and directory lists, now
|
||
;; that we know the locale's encoding. This is because the
|
||
;; values of these variables are until here unibyte undecoded
|
||
;; strings created by build_unibyte_string. data-directory in
|
||
;; particular is used to construct many other standard
|
||
;; directory names, so it must be decoded ASAP. Note that
|
||
;; charset-map-path cannot be decoded here, since we could
|
||
;; then be trapped in infinite recursion below, when we load
|
||
;; subdirs.el, because encoding a directory name might need to
|
||
;; load a charset map, which will want to encode
|
||
;; charset-map-path, which will want to load the same charset
|
||
;; map... So decoding of charset-map-path is delayed until
|
||
;; further down below.
|
||
(dolist (pathsym '(load-path exec-path))
|
||
(let ((path (symbol-value pathsym)))
|
||
(if (listp path)
|
||
(set pathsym (mapcar (lambda (dir)
|
||
(decode-coding-string dir coding t))
|
||
path)))))
|
||
(when (featurep 'native-compile)
|
||
(let ((npath (symbol-value 'native-comp-eln-load-path)))
|
||
(set 'native-comp-eln-load-path
|
||
(mapcar (lambda (dir)
|
||
;; Call expand-file-name to remove all the
|
||
;; pesky ".." from the directory names in
|
||
;; native-comp-eln-load-path.
|
||
(expand-file-name
|
||
(decode-coding-string dir coding t)))
|
||
npath)))
|
||
(setq startup--original-eln-load-path
|
||
(copy-sequence native-comp-eln-load-path)))
|
||
(dolist (filesym '(data-directory doc-directory exec-directory
|
||
installation-directory
|
||
invocation-directory invocation-name
|
||
source-directory
|
||
shared-game-score-directory))
|
||
(let ((file (symbol-value filesym)))
|
||
(if (stringp file)
|
||
(set filesym (decode-coding-string file coding t)))))))
|
||
|
||
(let ((dir default-directory))
|
||
(with-current-buffer "*Messages*"
|
||
(messages-buffer-mode)
|
||
;; Give *Messages* the same default-directory as *scratch*,
|
||
;; just to keep things predictable.
|
||
(setq default-directory (or dir (expand-file-name "~/")))))
|
||
;; `user-full-name' is now known; reset its standard-value here.
|
||
(put 'user-full-name 'standard-value
|
||
(list (default-value 'user-full-name)))
|
||
;; If the PWD environment variable isn't accurate, delete it.
|
||
(let ((pwd (getenv "PWD")))
|
||
(and pwd
|
||
(or (and default-directory
|
||
(ignore-errors
|
||
(equal (file-attributes
|
||
(file-name-as-directory pwd))
|
||
(file-attributes
|
||
(file-name-as-directory default-directory)))))
|
||
(setq process-environment
|
||
(delete (concat "PWD=" pwd)
|
||
process-environment)))))
|
||
;; Now, that other directories were searched, and any charsets we
|
||
;; need for encoding them are already loaded, we are ready to
|
||
;; decode charset-map-path.
|
||
(if (listp charset-map-path)
|
||
(let ((coding (if (eq system-type 'windows-nt)
|
||
'utf-8
|
||
locale-coding-system)))
|
||
(setq charset-map-path
|
||
(mapcar (lambda (dir)
|
||
(decode-coding-string dir coding t))
|
||
charset-map-path))))
|
||
(if default-directory
|
||
(setq default-directory (abbreviate-file-name default-directory))
|
||
(display-warning 'initialization "Error setting default-directory"))
|
||
(let ((old-face-font-rescale-alist face-font-rescale-alist))
|
||
(unwind-protect
|
||
(command-line)
|
||
|
||
;; Do this again, in case .emacs defined more abbreviations.
|
||
(if default-directory
|
||
(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.
|
||
(or auto-save-list-file-name
|
||
(and auto-save-list-file-prefix
|
||
(setq auto-save-list-file-name
|
||
;; Under MS-DOS our PID is almost always reused between
|
||
;; Emacs invocations. We need something more unique.
|
||
(cond ((eq system-type 'ms-dos)
|
||
;; We are going to access the auto-save
|
||
;; directory, so make sure it exists.
|
||
(make-directory
|
||
(file-name-directory auto-save-list-file-prefix)
|
||
t)
|
||
(concat
|
||
(make-temp-name
|
||
(expand-file-name
|
||
auto-save-list-file-prefix))
|
||
"~"))
|
||
(t
|
||
(expand-file-name
|
||
(format "%s%d-%s~"
|
||
auto-save-list-file-prefix
|
||
(emacs-pid)
|
||
(system-name))))))))
|
||
(unless inhibit-startup-hooks
|
||
(run-hooks 'emacs-startup-hook 'term-setup-hook))
|
||
|
||
;; Don't do this if we failed to create the initial frame,
|
||
;; for instance due to a dense colormap.
|
||
(when (or frame-initial-frame
|
||
;; If frame-initial-frame has no meaning, do this anyway.
|
||
(not (and initial-window-system
|
||
(not noninteractive)
|
||
(not (eq initial-window-system 'pc)))))
|
||
|
||
;; FIXME: The user's init file may change
|
||
;; face-font-rescale-alist. However, the default face
|
||
;; already has an assigned font object, which does not take
|
||
;; face-font-rescale-alist into account. For such
|
||
;; situations, we ought to have a way to find all font
|
||
;; objects and regenerate them; currently we do not. As a
|
||
;; workaround, we specifically reset the default face's :font
|
||
;; attribute here, if it was rescaled. See bug#1785.
|
||
(when (and (display-multi-font-p)
|
||
(not (eq face-font-rescale-alist
|
||
old-face-font-rescale-alist))
|
||
(assoc (face-attribute 'default :font)
|
||
face-font-rescale-alist
|
||
#'startup--rescale-elt-match-p))
|
||
(set-face-attribute 'default nil :font (font-spec)))
|
||
|
||
;; Modify the initial frame based on what .emacs puts into
|
||
;; ...-frame-alist.
|
||
(if (fboundp 'frame-notice-user-settings)
|
||
(frame-notice-user-settings))
|
||
;; Set the faces for the initial background mode even if
|
||
;; frame-notice-user-settings didn't (such as on a tty).
|
||
;; frame-set-background-mode is idempotent, so it won't
|
||
;; cause any harm if it's already been done.
|
||
(if (fboundp 'frame-set-background-mode)
|
||
(frame-set-background-mode (selected-frame))))
|
||
|
||
;; Now we know the user's default font, so add it to the menu.
|
||
(if (fboundp 'font-menu-add-default)
|
||
(font-menu-add-default))
|
||
(unless inhibit-startup-hooks
|
||
(run-hooks 'window-setup-hook))))
|
||
|
||
;; Subprocesses of Emacs do not have direct access to the terminal, so
|
||
;; unless told otherwise they should only assume a dumb terminal.
|
||
;; We are careful to do it late (after term-setup-hook), although the
|
||
;; new multi-tty code does not use $TERM any more there anyway.
|
||
(setenv "TERM" "dumb")
|
||
;; Similarly, a subprocess should not try to invoke a pager, as most
|
||
;; pagers will fail in a dumb terminal. Many programs default to
|
||
;; using "less" when PAGER is unset, so set PAGER to "cat"; using cat
|
||
;; as a pager is equivalent to not using a pager at all.
|
||
(when (executable-find "cat")
|
||
(setenv "PAGER" "cat"))
|
||
;; Remove DISPLAY from the process-environment as well. This allows
|
||
;; `callproc.c' to give it a useful adaptive default which is either
|
||
;; the value of the `display' frame-parameter or the DISPLAY value
|
||
;; from initial-environment.
|
||
(let ((display (frame-parameter nil 'display)))
|
||
;; Be careful which DISPLAY to remove from process-environment: follow
|
||
;; the logic of `callproc.c'.
|
||
(if (stringp display)
|
||
(setq display (concat "DISPLAY=" display))
|
||
(let ((env initial-environment))
|
||
(while (and env (or (not (string-match "\\`DISPLAY=" (car env)))
|
||
(progn
|
||
(setq display (car env))
|
||
nil)))
|
||
(setq env (cdr env)))))
|
||
(when display
|
||
(setq process-environment (delete display process-environment))))))
|
||
|
||
;; Precompute the keyboard equivalents in the menu bar items.
|
||
;; Command-line options supported by tty's:
|
||
(defconst tty-long-option-alist
|
||
'(("--name" . "-name")
|
||
("--title" . "-T")
|
||
("--reverse-video" . "-reverse")
|
||
("--foreground-color" . "-fg")
|
||
("--background-color" . "-bg")
|
||
("--color" . "-color")))
|
||
|
||
;; FIXME: this var unused?
|
||
(defconst tool-bar-images-pixel-height 24
|
||
"Height in pixels of images in the tool-bar.")
|
||
|
||
(cl-defgeneric handle-args-function (args)
|
||
"Method for processing window-system dependent command-line arguments.
|
||
Window system startup files should add their own function to this
|
||
method, which should parse the command line arguments. Those
|
||
pertaining to the window system should be processed and removed
|
||
from the returned command line.")
|
||
(cl-defmethod handle-args-function (args &context (window-system nil))
|
||
(tty-handle-args args))
|
||
|
||
(cl-defgeneric window-system-initialization (&optional _display)
|
||
"Method for window-system initialization.
|
||
Window-system startup files should add their own implementation
|
||
to this method. The function should initialize the window system environment
|
||
to prepare for opening the first frame (e.g. open a connection to an X server)."
|
||
nil)
|
||
|
||
(defun tty-handle-args (args)
|
||
"Handle the X-like command-line arguments \"-fg\", \"-bg\", \"-name\", etc."
|
||
(let (rest)
|
||
(while (and args
|
||
(not (equal (car args) "--")))
|
||
(let* ((argi (pop args))
|
||
(orig-argi argi)
|
||
argval completion)
|
||
;; Check for long options with attached arguments
|
||
;; and separate out the attached option argument into argval.
|
||
(when (string-match "^\\(--[^=]*\\)=" argi)
|
||
(setq argval (substring argi (match-end 0))
|
||
argi (match-string 1 argi)))
|
||
(when (string-match "^--" argi)
|
||
(setq completion (try-completion argi tty-long-option-alist))
|
||
(if (eq completion t)
|
||
;; Exact match for long option.
|
||
(setq argi (cdr (assoc argi tty-long-option-alist)))
|
||
(if (stringp completion)
|
||
(let ((elt (assoc completion tty-long-option-alist)))
|
||
;; Check for abbreviated long option.
|
||
(or elt
|
||
(error "Option `%s' is ambiguous" argi))
|
||
(setq argi (cdr elt)))
|
||
;; Check for a short option.
|
||
(setq argval nil
|
||
argi orig-argi))))
|
||
(cond ((member argi '("-fg" "-foreground"))
|
||
(push (cons 'foreground-color (or argval (pop args)))
|
||
default-frame-alist))
|
||
((member argi '("-bg" "-background"))
|
||
(push (cons 'background-color (or argval (pop args)))
|
||
default-frame-alist))
|
||
((member argi '("-T" "-name"))
|
||
(unless argval (setq argval (pop args)))
|
||
(push (cons 'title
|
||
(if (stringp argval)
|
||
argval
|
||
(let ((case-fold-search t)
|
||
i)
|
||
(setq argval (copy-sequence invocation-name))
|
||
|
||
;; Change any . or * characters in name to
|
||
;; hyphens, so as to emulate behavior on X.
|
||
(while
|
||
(setq i (string-match "[.*]" argval))
|
||
(aset argval i ?-))
|
||
argval)))
|
||
default-frame-alist))
|
||
((member argi '("-r" "-rv" "-reverse"))
|
||
(push '(reverse . t)
|
||
default-frame-alist))
|
||
((equal argi "-color")
|
||
(unless argval (setq argval 8)) ; default --color means 8 ANSI colors
|
||
(push (cons 'tty-color-mode
|
||
(cond
|
||
((numberp argval) argval)
|
||
((string-match "-?[0-9]+" argval)
|
||
(string-to-number argval))
|
||
(t (intern argval))))
|
||
default-frame-alist))
|
||
(t
|
||
(push argi rest)))))
|
||
(nconc (nreverse rest) args)))
|
||
|
||
(declare-function x-get-resource "frame.c"
|
||
(attribute class &optional component subclass))
|
||
(declare-function tool-bar-mode "tool-bar" (&optional arg))
|
||
(declare-function tool-bar-setup "tool-bar")
|
||
|
||
(defvar server-name)
|
||
(defvar server-process)
|
||
|
||
(defun startup--setup-quote-display (&optional style)
|
||
"If needed, display ASCII approximations to curved quotes.
|
||
Do this by modifying `standard-display-table'. Optional STYLE
|
||
specifies the desired quoting style, as in `text-quoting-style'.
|
||
If STYLE is nil, display appropriately for the terminal."
|
||
(let ((repls (let ((style-repls (assq style '((grave . "`'\"\"")
|
||
(straight . "''\"\"")))))
|
||
(if style-repls (cdr style-repls) (make-vector 4 nil))))
|
||
glyph-count)
|
||
;; REPLS is a sequence of the four replacements for "‘’“”", respectively.
|
||
;; If STYLE is nil, infer REPLS from terminal characteristics.
|
||
(unless style
|
||
;; On a terminal that supports glyph codes,
|
||
;; GLYPH-COUNT[i] is the number of times that glyph code I
|
||
;; represents either an ASCII character or one of the 4
|
||
;; quote characters. This assumes glyph codes are valid
|
||
;; Elisp characters, which is a safe assumption in practice.
|
||
(when (integerp (internal-char-font nil (max-char)))
|
||
(setq glyph-count (make-char-table nil 0))
|
||
(dotimes (i 132)
|
||
(let ((glyph (internal-char-font
|
||
nil (if (< i 128) i (aref "‘’“”" (- i 128))))))
|
||
(when (<= 0 glyph)
|
||
(aset glyph-count glyph (1+ (aref glyph-count glyph)))))))
|
||
(dotimes (i 2)
|
||
(let ((lq (aref "‘“" i)) (rq (aref "’”" i))
|
||
(lr (aref "`\"" i)) (rr (aref "'\"" i))
|
||
(i2 (* i 2)))
|
||
(unless (if glyph-count
|
||
;; On a terminal that supports glyph codes, use
|
||
;; ASCII replacements unless both quotes are displayable.
|
||
;; If not using ASCII replacements, highlight
|
||
;; quotes unless they are both unique among the
|
||
;; 128 + 4 characters of concern.
|
||
(let ((lglyph (internal-char-font nil lq))
|
||
(rglyph (internal-char-font nil rq)))
|
||
(when (and (<= 0 lglyph) (<= 0 rglyph))
|
||
(setq lr lq rr rq)
|
||
(and (= 1 (aref glyph-count lglyph))
|
||
(= 1 (aref glyph-count rglyph)))))
|
||
;; On a terminal that does not support glyph codes, use
|
||
;; ASCII replacements unless both quotes are displayable.
|
||
(and (char-displayable-p lq)
|
||
(char-displayable-p rq)))
|
||
(aset repls i2 lr)
|
||
(aset repls (1+ i2) rr)))))
|
||
(dotimes (i 4)
|
||
(let ((char (aref "‘’“”" i))
|
||
(repl (aref repls i)))
|
||
(if repl
|
||
(aset (or standard-display-table
|
||
(setq standard-display-table (make-display-table)))
|
||
char (vector (make-glyph-code repl 'homoglyph)))
|
||
(when standard-display-table
|
||
(aset standard-display-table char nil)))))))
|
||
|
||
(defun startup--debug (err)
|
||
(funcall debugger 'error err :backtrace-base #'startup--debug))
|
||
|
||
(defun startup--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, unless `inhibit-default-init'
|
||
is non-nil.
|
||
|
||
This function sets `user-init-file' to the name of the loaded
|
||
init-file, or to a default value if loading is not possible."
|
||
;; The init file might contain byte-code with embedded NULs,
|
||
;; which can cause problems when read back, so disable nul
|
||
;; byte detection. (Bug#52554)
|
||
(let ((inhibit-null-byte-detection t)
|
||
(body
|
||
(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)
|
||
(when init-file-name
|
||
(load (if (equal (file-name-extension init-file-name)
|
||
"el")
|
||
(file-name-sans-extension init-file-name)
|
||
init-file-name)
|
||
'noerror 'nomessage))
|
||
|
||
(when (and (eq user-init-file t) alternate-filename-function)
|
||
(let ((alt-file (funcall alternate-filename-function)))
|
||
(unless init-file-name
|
||
(setq init-file-name alt-file))
|
||
(and (equal (file-name-extension alt-file) "el")
|
||
(setq alt-file (file-name-sans-extension alt-file)))
|
||
(load alt-file '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.
|
||
(if (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)))
|
||
;; Else, perhaps the user init file was compiled
|
||
(when (and (equal (file-name-extension user-init-file) "eln")
|
||
;; The next test is for builds without native
|
||
;; compilation support or builds with unexec.
|
||
(boundp 'comp-eln-to-el-h))
|
||
(if-let* ((source (gethash (file-name-nondirectory
|
||
user-init-file)
|
||
comp-eln-to-el-h)))
|
||
;; source exists or the .eln file would not load
|
||
(setq user-init-file source)
|
||
(message "Warning: unknown source file for init file %S"
|
||
user-init-file)
|
||
(sit-for 1))))
|
||
|
||
(when (and load-defaults
|
||
(not inhibit-default-init))
|
||
;; Prevent default.el from changing the value of
|
||
;; `inhibit-startup-screen'.
|
||
(let ((inhibit-startup-screen nil))
|
||
(load "default" 'noerror 'nomessage)))))))
|
||
(if (eq init-file-debug t)
|
||
(handler-bind ((error #'startup--debug))
|
||
(funcall body))
|
||
(condition-case-unless-debug error
|
||
(funcall body)
|
||
(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))))))
|
||
|
||
(defvar lisp-directory nil
|
||
"Directory where Emacs's own *.el and *.elc Lisp files are installed.")
|
||
|
||
(defun command-line ()
|
||
"A subroutine of `normal-top-level'.
|
||
Amongst another things, it parses the command-line arguments."
|
||
(let (xdg-dir startup-init-directory)
|
||
(setq before-init-time (current-time)
|
||
after-init-time nil
|
||
command-line-default-directory default-directory)
|
||
|
||
;; Force recomputation, in case it was computed during the dump.
|
||
(setq abbreviated-home-dir nil)
|
||
|
||
;; See if we should import version-control from the environment variable.
|
||
(let ((vc (getenv "VERSION_CONTROL")))
|
||
(cond ((eq vc nil)) ;don't do anything if not set
|
||
((member vc '("t" "numbered"))
|
||
(setq version-control t))
|
||
((member vc '("nil" "existing"))
|
||
(setq version-control nil))
|
||
((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))))
|
||
;; 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-directory
|
||
(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-directory
|
||
(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")
|
||
("--dump-file") ("--temacs") ("--seccomp")
|
||
("--init-directory" "--no-comp-spawn")))
|
||
(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)))))
|
||
|
||
;; We handle "-scripteval" further down, but we have to
|
||
;; inhibit loading the user init file first. (This is for
|
||
;; "emacs -x" handling.)
|
||
(when (equal argi "-scripteval")
|
||
(setq init-file-user nil
|
||
noninteractive t))
|
||
|
||
(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)
|
||
;; Stop it showing up in emacs -Q's customize-rogue.
|
||
(put 'site-run-file 'standard-value '(nil)))
|
||
((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 '("-init-directory"))
|
||
(setq user-emacs-directory (or argval (pop args))
|
||
user-emacs-directory (if (stringp user-emacs-directory)
|
||
(file-name-as-directory
|
||
(expand-file-name
|
||
user-emacs-directory
|
||
command-line-default-directory))
|
||
user-emacs-directory)
|
||
argval 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)
|
||
(put 'site-run-file 'standard-value '(nil)))
|
||
((equal argi "-no-comp-spawn")
|
||
(defvar comp-no-spawn)
|
||
(setq comp-no-spawn t))
|
||
((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))
|
||
((member argi '("-dump-file" "-temacs" "-seccomp"))
|
||
;; Handled in C
|
||
(or argval (pop args))
|
||
(setq argval nil))
|
||
;; 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)))
|
||
|
||
;; Re-evaluate predefined variables whose initial value depends on
|
||
;; the runtime context. But delay the warning about
|
||
;; `user-emacs-directory' being inaccessible until after processing
|
||
;; the init file and the command-line arguments, in case the user
|
||
;; customized `user-emacs-directory-warning' to nil via those.
|
||
(let ((user-emacs-directory-warning nil))
|
||
(when (listp custom-delayed-init-variables)
|
||
(mapc #'custom-reevaluate-setting
|
||
;; Initialize them in the same order they were loaded, in
|
||
;; case there are dependencies between them.
|
||
(reverse custom-delayed-init-variables))))
|
||
(setq custom-delayed-init-variables t)
|
||
|
||
;; 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))))
|
||
|
||
;; Calculate the name of the Emacs init directory.
|
||
;; This is typically ~INIT-FILE-USER/.config/emacs unless the user
|
||
;; is following the ~INIT-FILE-USER/.emacs.d convention.
|
||
(setq xdg-dir startup--xdg-config-home-emacs)
|
||
(setq startup-init-directory
|
||
(if (or (zerop (length init-file-user))
|
||
(and (eq xdg-dir user-emacs-directory)
|
||
(not (eq xdg-dir startup--xdg-config-default))))
|
||
user-emacs-directory
|
||
;; The name is not obvious, so access more directories
|
||
;; to calculate it.
|
||
(setq xdg-dir (concat "~" init-file-user "/.config/emacs/"))
|
||
(startup--xdg-or-homedot xdg-dir init-file-user)))
|
||
|
||
;; Load the early init file, if found.
|
||
(startup--load-user-init-file
|
||
(lambda ()
|
||
(expand-file-name
|
||
;; We use an explicit .el extension here to force
|
||
;; startup--load-user-init-file to set user-init-file to "early-init.el",
|
||
;; with the .el extension, if the file doesn't exist, not just
|
||
;; "early-init" without an extension, as it does for ".emacs".
|
||
"early-init.el"
|
||
startup-init-directory)))
|
||
(setq early-init-file user-init-file)
|
||
|
||
;; Amend `native-comp-eln-load-path', since the early-init file may
|
||
;; have altered `user-emacs-directory' and/or changed the eln-cache
|
||
;; directory.
|
||
(when (featurep 'native-compile)
|
||
(startup--update-eln-cache))
|
||
|
||
;; If any package directory exists, initialize the package system.
|
||
(and user-init-file
|
||
package-enable-at-startup
|
||
(not (bound-and-true-p package--activated))
|
||
(catch 'package-dir-found
|
||
(let ((dirs (cons package-user-dir package-directory-list)))
|
||
(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-activate-all))
|
||
|
||
;; 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
|
||
(let ((window-system initial-window-system)) ;Hack attack!
|
||
(handle-args-function command-line-args)))
|
||
;; Initialize the window system. (Open connection, etc.)
|
||
(let ((window-system initial-window-system)) ;Hack attack!
|
||
(window-system-initialization))
|
||
(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 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
|
||
tab-bar-mode nil
|
||
tool-bar-mode nil))
|
||
(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)))
|
||
|
||
(unless noninteractive
|
||
(startup--setup-quote-display)
|
||
(setq internal--text-quoting-flag t))
|
||
|
||
(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 method of
|
||
;; window-system-initialization.
|
||
(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
|
||
;; Sites should not disable the startup screen.
|
||
;; Only individuals should disable the startup screen.
|
||
(let ((inhibit-startup-screen inhibit-startup-screen))
|
||
(load site-run-file t t)))
|
||
|
||
;; Load that user's init file, or the default one, or none.
|
||
(startup--load-user-init-file
|
||
(lambda ()
|
||
(cond
|
||
((eq startup-init-directory xdg-dir) nil)
|
||
((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.el"
|
||
startup-init-directory))
|
||
t)
|
||
|
||
;; Amend `native-comp-eln-load-path' again, since the early-init
|
||
;; file may have altered `user-emacs-directory' and/or changed the
|
||
;; eln-cache directory.
|
||
(when (featurep 'native-compile)
|
||
(startup--update-eln-cache))
|
||
|
||
(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
|
||
;; Check that user-mail-address has not been set by hand.
|
||
;; Yes, this is ugly, but slightly less so than leaving
|
||
;; user-mail-address uninitialized during init file processing.
|
||
;; Perhaps we should make :set-after do something like this?
|
||
;; Ie, extend it to also mean (re)initialize-after. See etc/TODO.
|
||
(equal user-mail-address
|
||
(let (mail-host-address)
|
||
(ignore-errors
|
||
(custom--standard-value 'user-mail-address))))
|
||
(custom-reevaluate-setting 'user-mail-address))
|
||
|
||
;; 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)))
|
||
|
||
(setq after-init-time (current-time))
|
||
;; Display any accumulated warnings after all functions in
|
||
;; `after-init-hook' like `desktop-read' have finalized possible
|
||
;; changes in the window configuration.
|
||
(run-hooks 'after-init-hook 'delayed-warnings-hook)
|
||
|
||
;; If *scratch* exists and init file didn't change its mode, initialize it.
|
||
(if (get-buffer "*scratch*")
|
||
(with-current-buffer "*scratch*"
|
||
(if (eq major-mode 'fundamental-mode)
|
||
(funcall initial-major-mode))))
|
||
|
||
;; Load library for our terminal type.
|
||
;; User init file can set term-file-prefix to nil to prevent this.
|
||
(unless (or noninteractive
|
||
initial-window-system
|
||
(daemonp))
|
||
(tty-run-terminal-initialization (selected-frame) nil t))
|
||
|
||
;; Update the out-of-memory error message based on user's key bindings
|
||
;; for save-some-buffers.
|
||
(setq memory-signal-data
|
||
(list 'error
|
||
(substitute-command-keys "Memory exhausted--use \\[save-some-buffers] then exit and restart Emacs")))
|
||
|
||
;; Reevaluate `user-emacs-directory-warning' before processing
|
||
;; '--eval' arguments, so that the user could override the default
|
||
;; value in the '--eval' forms.
|
||
(custom-reevaluate-setting 'user-emacs-directory-warning)
|
||
|
||
;; Process the remaining args.
|
||
(command-line-1 (cdr command-line-args))
|
||
|
||
;; Check if `user-emacs-directory' is accessible and warn if it
|
||
;; isn't, unless `user-emacs-directory-warning' was customized to
|
||
;; disable that warning.
|
||
(when (and user-emacs-directory-warning
|
||
(not (file-accessible-directory-p user-emacs-directory)))
|
||
(locate-user-emacs-file ""))
|
||
|
||
;; This is a problem because, e.g. if emacs.d/gnus.el exists,
|
||
;; trying to load gnus could load the wrong file.
|
||
;; OK, it would not matter if .emacs.d were at the end of load-path.
|
||
;; but for the sake of simplicity, we discourage it full-stop.
|
||
;; Ref eg https://lists.gnu.org/r/emacs-devel/2012-03/msg00056.html
|
||
;;
|
||
;; A bad element could come from user-emacs-file, the command line,
|
||
;; or EMACSLOADPATH, so we basically always have to check.
|
||
(let (warned)
|
||
(dolist (dir load-path)
|
||
(and (not noninteractive)
|
||
(not warned)
|
||
(stringp dir)
|
||
(string-equal (file-name-as-directory (expand-file-name dir))
|
||
(expand-file-name user-emacs-directory))
|
||
(setq warned t)
|
||
(display-warning 'initialization
|
||
(format-message "\
|
||
Your `load-path' seems to contain\n\
|
||
your `user-emacs-directory': %s\n\
|
||
This is likely to cause problems...\n\
|
||
Consider using a subdirectory instead, e.g.: %s"
|
||
dir (expand-file-name
|
||
"lisp" user-emacs-directory))
|
||
:warning))))
|
||
|
||
;; If -batch, terminate after processing the command options.
|
||
(if noninteractive (kill-emacs t))
|
||
|
||
;; In daemon mode, start the server to allow clients to connect.
|
||
;; This is done after loading the user's init file and after
|
||
;; processing all command line arguments to allow e.g. `server-name'
|
||
;; to be changed before the server starts.
|
||
(let ((dn (daemonp)))
|
||
(when dn
|
||
(when (stringp dn) (setq server-name dn))
|
||
(condition-case err
|
||
(server-start)
|
||
(error (error "Unable to start daemon: %s; exiting" (error-message-string err))))
|
||
(if server-process
|
||
(daemon-initialized)
|
||
(if (stringp dn)
|
||
(message
|
||
"Unable to start daemon: Emacs server named %S already running"
|
||
server-name)
|
||
(message "Unable to start the daemon.\nAnother instance of Emacs is running the server, either as daemon or interactively.\nYou can use emacsclient to connect to that Emacs process."))
|
||
(kill-emacs 1))))
|
||
|
||
;; Run emacs-session-restore (session management) if started by
|
||
;; the session manager and we have a session manager connection.
|
||
(if (and (boundp 'x-session-previous-id)
|
||
(stringp x-session-previous-id))
|
||
(with-no-warnings
|
||
(emacs-session-restore x-session-previous-id)))))
|
||
|
||
(defun x-apply-session-resources ()
|
||
"Apply X resources which specify initial values for Emacs variables.
|
||
This is called from a window-system initialization function, such
|
||
as `window-system-initialization' for X, either at startup (prior
|
||
to reading the init file), or afterwards when the user first
|
||
opens a graphical frame.
|
||
|
||
This can set the values of `menu-bar-mode', `tool-bar-mode',
|
||
`tab-bar-mode', and `blink-cursor-mode', as well as the `cursor' face.
|
||
Changed settings will be marked as \"CHANGED outside of Customize\"."
|
||
(let ((no-vals '("no" "off" "false" "0"))
|
||
(settings '(("menuBar" "MenuBar" menu-bar-mode nil)
|
||
("toolBar" "ToolBar" tool-bar-mode nil)
|
||
("scrollBar" "ScrollBar" scroll-bar-mode nil)
|
||
("cursorBlink" "CursorBlink" blink-cursor-mode nil))))
|
||
(dolist (x settings)
|
||
(if (member (x-get-resource (nth 0 x) (nth 1 x)) no-vals)
|
||
(set (nth 2 x) (nth 3 x)))))
|
||
(let ((yes-vals '("yes" "on" "true" "1"))
|
||
(settings '(("tabBar" "TabBar" tab-bar-mode 1))))
|
||
(dolist (x settings)
|
||
(if (member (x-get-resource (nth 0 x) (nth 1 x)) yes-vals)
|
||
(funcall (nth 2 x) (nth 3 x)))))
|
||
(let ((color (x-get-resource "cursorColor" "Foreground")))
|
||
(when color
|
||
(put 'cursor 'theme-face
|
||
`((changed ((t :background ,color)))))
|
||
(put 'cursor 'face-modified t))))
|
||
|
||
(defcustom initial-scratch-message (purecopy "\
|
||
;; This buffer is for text that is not saved, and for Lisp evaluation.
|
||
;; To create a file, visit it with `\\[find-file]' and enter text in its buffer.
|
||
|
||
")
|
||
"Initial documentation displayed in *scratch* buffer at startup.
|
||
If this is nil, no message will be displayed."
|
||
:type '(choice (text :tag "Message")
|
||
(const :tag "none" nil)))
|
||
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;; Fancy splash screen
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
(defconst fancy-startup-text
|
||
`((:face (variable-pitch font-lock-comment-face)
|
||
"Welcome to "
|
||
:link ("GNU Emacs"
|
||
,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/software/emacs/")))
|
||
"Browse https://www.gnu.org/software/emacs/")
|
||
", one component of the "
|
||
:link
|
||
,(lambda ()
|
||
(if (eq system-type 'gnu/linux)
|
||
`("GNU/Linux"
|
||
,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/gnu/linux-and-gnu.html")))
|
||
"Browse https://www.gnu.org/gnu/linux-and-gnu.html")
|
||
`("GNU" ,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/gnu/thegnuproject.html")))
|
||
"Browse https://www.gnu.org/gnu/thegnuproject.html")))
|
||
" operating system.\n\n"
|
||
:face variable-pitch
|
||
:link ("Emacs Tutorial" ,(lambda (_button) (help-with-tutorial)))
|
||
"\tLearn basic keystroke commands"
|
||
,(lambda ()
|
||
(let* ((en "TUTORIAL")
|
||
(tut (or (get-language-info current-language-environment
|
||
'tutorial)
|
||
en))
|
||
(title (with-temp-buffer
|
||
(insert-file-contents
|
||
(expand-file-name tut tutorial-directory)
|
||
;; We used to read only the first 256 bytes of
|
||
;; the tutorial, but that prevents the coding:
|
||
;; setting, if any, in file-local variables
|
||
;; section to be seen by insert-file-contents,
|
||
;; and results in gibberish when the language
|
||
;; environment's preferred encoding is
|
||
;; different from what the file-local variable
|
||
;; says. One case in point is Hebrew.
|
||
nil)
|
||
(search-forward ".")
|
||
(buffer-substring (point-min) (1- (point))))))
|
||
;; If there is a specific tutorial for the current language
|
||
;; environment and it is not English, append its title.
|
||
(if (string= en tut)
|
||
""
|
||
(concat " (" title ")"))))
|
||
"\n"
|
||
:link ("Emacs Guided Tour"
|
||
,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/software/emacs/tour/")))
|
||
"Browse https://www.gnu.org/software/emacs/tour/")
|
||
"\tOverview of Emacs features at gnu.org\n"
|
||
:link ("View Emacs Manual" ,(lambda (_button) (info-emacs-manual)))
|
||
"\tView the Emacs manual using Info\n"
|
||
:link ("Absence of Warranty" ,(lambda (_button) (describe-no-warranty)))
|
||
"\tGNU Emacs comes with "
|
||
:face (variable-pitch (:slant oblique))
|
||
"ABSOLUTELY NO WARRANTY\n"
|
||
:face variable-pitch
|
||
:link ("Copying Conditions" ,(lambda (_button) (describe-copying)))
|
||
"\tConditions for redistributing and changing Emacs\n"
|
||
:link ("Ordering Manuals" ,(lambda (_button) (view-order-manuals)))
|
||
"\tPurchasing printed copies of manuals\n"
|
||
"\n"))
|
||
"A list of texts to show in the middle part of splash screens.
|
||
Each element in the list should be a list of strings or pairs
|
||
`:KEYWORD VALUE', like what `fancy-splash-insert' accepts.")
|
||
|
||
(defconst fancy-about-text
|
||
`((:face (variable-pitch font-lock-comment-face)
|
||
"This is "
|
||
:link ("GNU Emacs"
|
||
,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/software/emacs/")))
|
||
"Browse https://www.gnu.org/software/emacs/")
|
||
", a text editor and more.\nIt's a component of the "
|
||
:link
|
||
,(lambda ()
|
||
(if (eq system-type 'gnu/linux)
|
||
`("GNU/Linux"
|
||
,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/gnu/linux-and-gnu.html")))
|
||
"Browse https://www.gnu.org/gnu/linux-and-gnu.html")
|
||
`("GNU" ,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(describe-gnu-project)))
|
||
"Display info on the GNU project.")))
|
||
" operating system.\n"
|
||
:face (variable-pitch font-lock-builtin-face)
|
||
"\n"
|
||
,(lambda ()
|
||
(with-temp-buffer
|
||
(insert (emacs-version))
|
||
(fill-region (point-min) (point-max))
|
||
(buffer-string)))
|
||
"\n"
|
||
:face (variable-pitch (:height 0.8))
|
||
,(lambda () emacs-copyright)
|
||
"\n\n"
|
||
:face variable-pitch
|
||
:link ("Authors"
|
||
,(lambda (_button)
|
||
(view-file (expand-file-name "AUTHORS" data-directory))
|
||
(goto-char (point-min))))
|
||
"\tMany people have contributed code included in GNU Emacs\n"
|
||
:link ("Contributing"
|
||
,(lambda (_button) (info "(emacs)Contributing")))
|
||
"\tHow to report bugs and contribute improvements to Emacs\n"
|
||
"\n"
|
||
:link ("GNU and Freedom" ,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(describe-gnu-project))))
|
||
"\tWhy we developed GNU Emacs, and the GNU operating system\n"
|
||
:link ("Absence of Warranty" ,(lambda (_button) (describe-no-warranty)))
|
||
"\tGNU Emacs comes with "
|
||
:face (variable-pitch (:slant oblique))
|
||
"ABSOLUTELY NO WARRANTY\n"
|
||
:face variable-pitch
|
||
:link ("Copying Conditions" ,(lambda (_button) (describe-copying)))
|
||
"\tConditions for redistributing and changing Emacs\n"
|
||
:link ("Getting New Versions" ,(lambda (_button) (describe-distribution)))
|
||
"\tHow to obtain the latest version of Emacs\n"
|
||
:link ("Ordering Manuals" ,(lambda (_button) (view-order-manuals)))
|
||
"\tBuying printed manuals from the FSF\n"
|
||
"\n"
|
||
:link ("Emacs Tutorial" ,(lambda (_button) (help-with-tutorial)))
|
||
"\tLearn basic Emacs keystroke commands"
|
||
,(lambda ()
|
||
(let* ((en "TUTORIAL")
|
||
(tut (or (get-language-info current-language-environment
|
||
'tutorial)
|
||
en))
|
||
(title (with-temp-buffer
|
||
(insert-file-contents
|
||
(expand-file-name tut tutorial-directory)
|
||
;; Read the entire file, to make sure any
|
||
;; coding cookies and other local variables
|
||
;; get acted upon.
|
||
nil)
|
||
(search-forward ".")
|
||
(buffer-substring (point-min) (1- (point))))))
|
||
;; If there is a specific tutorial for the current language
|
||
;; environment and it is not English, append its title.
|
||
(if (string= en tut)
|
||
""
|
||
(concat " (" title ")"))))
|
||
"\n"
|
||
:link ("Emacs Guided Tour"
|
||
,(lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/software/emacs/tour/")))
|
||
"Browse https://www.gnu.org/software/emacs/tour/")
|
||
"\tSee an overview of Emacs features at gnu.org\n"
|
||
:link ("Emacs Manual" ,(lambda (_button) (info-emacs-manual)))
|
||
"\tDisplay the Emacs manual in Info mode"))
|
||
"A list of texts to show in the middle part of the About screen.
|
||
Each element in the list should be a list of strings or pairs
|
||
`:KEYWORD VALUE', like what `fancy-splash-insert' accepts.")
|
||
|
||
|
||
(defgroup fancy-splash-screen ()
|
||
;; FIXME: Do we really need this group with a single custom var?
|
||
"Fancy splash screen when Emacs starts."
|
||
:version "21.1"
|
||
:group 'initialization)
|
||
|
||
(defcustom fancy-splash-image nil
|
||
"The image to show in the splash screens, or nil for defaults."
|
||
:type '(choice (const :tag "Default" nil)
|
||
(file :tag "File")))
|
||
|
||
|
||
(defvar splash-screen-keymap
|
||
(let ((map (make-sparse-keymap)))
|
||
(suppress-keymap map)
|
||
(set-keymap-parent map button-buffer-map)
|
||
(define-key map "\C-?" #'scroll-down-command)
|
||
(define-key map [?\S-\ ] #'scroll-down-command)
|
||
(define-key map " " #'scroll-up-command)
|
||
(define-key map "q" #'exit-splash-screen)
|
||
map)
|
||
"Keymap for splash screen buffer.")
|
||
|
||
;; These are temporary storage areas for the splash screen display.
|
||
|
||
(defun fancy-splash-insert (&rest args)
|
||
"Insert text into the current buffer, with faces.
|
||
Arguments from ARGS should be either strings; functions called
|
||
with no args that return a string; pairs `:face FACE', where FACE
|
||
is a face specification usable with `put-text-property'; or pairs
|
||
`:link LINK' where LINK is a list of arguments to pass to
|
||
`insert-button', of the form (LABEL ACTION [HELP-ECHO]), which
|
||
specifies the button's label, `action' property and help-echo string.
|
||
FACE and LINK can also be functions, which are evaluated to obtain
|
||
a face or button specification."
|
||
(let ((current-face nil))
|
||
(while args
|
||
(cond ((eq (car args) :face)
|
||
(setq args (cdr args) current-face (car args))
|
||
(if (functionp current-face)
|
||
(setq current-face (funcall current-face))))
|
||
((eq (car args) :link)
|
||
(setq args (cdr args))
|
||
(let ((spec (car args)))
|
||
(if (functionp spec)
|
||
(setq spec (funcall spec)))
|
||
(insert-button (car spec)
|
||
'face (list 'link current-face)
|
||
'action (cadr spec)
|
||
'help-echo (concat "mouse-2, RET: "
|
||
(or (nth 2 spec)
|
||
"Follow this link"))
|
||
'follow-link t)))
|
||
(t (insert (propertize (let ((it (car args)))
|
||
(if (functionp it)
|
||
(funcall it)
|
||
it))
|
||
'face current-face
|
||
'help-echo (startup-echo-area-message)))))
|
||
(setq args (cdr args)))))
|
||
|
||
(declare-function image-size "image.c" (spec &optional pixels frame))
|
||
|
||
(defun fancy-splash-image-file ()
|
||
(cond ((stringp fancy-splash-image) fancy-splash-image)
|
||
((display-color-p)
|
||
(cond ((<= (display-planes) 8)
|
||
(if (image-type-available-p 'xpm)
|
||
"splash.xpm"
|
||
"splash.pbm"))
|
||
((or (image-type-available-p 'svg)
|
||
(image-type-available-p 'imagemagick))
|
||
"splash.svg")
|
||
((image-type-available-p 'png)
|
||
"splash.png")
|
||
((image-type-available-p 'xpm)
|
||
"splash.xpm")
|
||
(t "splash.pbm")))
|
||
(t "splash.pbm")))
|
||
|
||
(defun fancy-splash-head ()
|
||
"Insert the head part of the splash screen into the current buffer."
|
||
(let* ((image-file (fancy-splash-image-file))
|
||
(img (create-image image-file))
|
||
(image-width (and img (car (image-size img))))
|
||
(window-width (window-width)))
|
||
(when img
|
||
(when (> window-width image-width)
|
||
;; Center the image above text.
|
||
;; NB. The logo used to be centered in the window, which made
|
||
;; it align poorly with the non-centered text on large
|
||
;; displays. Arguably it would be better to center both
|
||
;; text and image, but this will do for now. -- SK
|
||
(let ((text-width 80)
|
||
;; The below value chosen to avoid splash screen being
|
||
;; visually unbalanced. This needs to be eye-balled.
|
||
(adjust-left 3))
|
||
(insert (propertize " " 'display
|
||
`(space :align-to (+ ,(- (/ text-width 2)
|
||
adjust-left)
|
||
(-0.5 . ,img))))))
|
||
|
||
;; Change the color of the XPM version of the splash image
|
||
;; so that it is visible with a dark frame background.
|
||
(when (and (memq 'xpm img)
|
||
(eq (frame-parameter nil 'background-mode) 'dark))
|
||
(setq img (append img '(:color-symbols (("#000000" . "gray30"))))))
|
||
|
||
;; Insert the image with a help-echo and a link.
|
||
(make-button (prog1 (point) (insert-image img)) (point)
|
||
'face 'default
|
||
'help-echo "mouse-2, RET: Browse https://www.gnu.org/"
|
||
'action (lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(browse-url "https://www.gnu.org/")))
|
||
'follow-link t)
|
||
(insert "\n\n")))))
|
||
|
||
(defun fancy-startup-tail (&optional concise)
|
||
"Insert the tail part of the splash screen into the current buffer."
|
||
(unless concise
|
||
(fancy-splash-insert
|
||
:face 'variable-pitch
|
||
"\nTo start...\t"
|
||
:link `("Open a File"
|
||
,(lambda (_button) (call-interactively 'find-file))
|
||
"Specify a new file's name, to edit the file")
|
||
"\t\t"
|
||
:link `("Open Home Directory"
|
||
,(lambda (_button) (dired "~"))
|
||
"Open your home directory, to operate on its files")
|
||
"\n\t"
|
||
:link `("Customize Startup"
|
||
,(lambda (_button) (customize-group 'initialization))
|
||
"Change initialization settings including this screen")
|
||
"\t"
|
||
:link `("Explore Packages"
|
||
,(lambda (_button) (call-interactively 'package-list-packages))
|
||
"Explore, install and remove Emacs packages (requires Internet connection)")
|
||
"\n"))
|
||
(fancy-splash-insert
|
||
:face 'variable-pitch "To quit a partially entered command, type "
|
||
:face 'default "Control-g"
|
||
:face 'variable-pitch ".\n")
|
||
(save-restriction
|
||
(narrow-to-region (point) (point))
|
||
(fancy-splash-insert :face '(variable-pitch font-lock-builtin-face)
|
||
"\nThis is "
|
||
(emacs-version)
|
||
"\n")
|
||
(fill-region (point-min) (point-max)))
|
||
(fancy-splash-insert :face '(variable-pitch (:height 0.8))
|
||
emacs-copyright
|
||
"\n")
|
||
(when auto-save-list-file-prefix
|
||
(let ((dir (file-name-directory auto-save-list-file-prefix))
|
||
(name (file-name-nondirectory auto-save-list-file-prefix))
|
||
files)
|
||
;; Don't warn if the directory for auto-save-list files does not
|
||
;; yet exist.
|
||
(and (file-directory-p dir)
|
||
(setq files (directory-files dir nil (concat "\\`" name) t))
|
||
(fancy-splash-insert :face '(variable-pitch font-lock-comment-face)
|
||
(if (= (length files) 1)
|
||
"\nAn auto-save file list was found. "
|
||
"\nAuto-save file lists were found. ")
|
||
"If an Emacs session crashed recently,\ntype "
|
||
:link `("M-x recover-session RET"
|
||
,(lambda (_button)
|
||
(call-interactively
|
||
'recover-session)))
|
||
" to recover the files you were editing."))))
|
||
(when concise
|
||
(fancy-splash-insert
|
||
:face 'variable-pitch "\n"
|
||
:link `("Dismiss this startup screen"
|
||
,(lambda (_button)
|
||
(when startup-screen-inhibit-startup-screen
|
||
(customize-set-variable 'inhibit-startup-screen t)
|
||
(customize-mark-to-save 'inhibit-startup-screen)
|
||
(custom-save-all))
|
||
(quit-windows-on "*GNU Emacs*" t)))
|
||
" ")
|
||
(when (or user-init-file custom-file)
|
||
(let ((checked (create-image "checked.xpm"
|
||
nil nil :ascent 'center))
|
||
(unchecked (create-image "unchecked.xpm"
|
||
nil nil :ascent 'center)))
|
||
(insert-button
|
||
" "
|
||
:on-glyph checked
|
||
:off-glyph unchecked
|
||
'checked nil 'display unchecked 'follow-link t
|
||
'action (lambda (button)
|
||
(if (overlay-get button 'checked)
|
||
(progn (overlay-put button 'checked nil)
|
||
(overlay-put button 'display
|
||
(overlay-get button :off-glyph))
|
||
(setq startup-screen-inhibit-startup-screen
|
||
nil))
|
||
(overlay-put button 'checked t)
|
||
(overlay-put button 'display
|
||
(overlay-get button :on-glyph))
|
||
(setq startup-screen-inhibit-startup-screen t)))))
|
||
(fancy-splash-insert :face '(variable-pitch (:height 0.9))
|
||
" Never show it again."))))
|
||
|
||
(defun exit-splash-screen ()
|
||
"Stop displaying the splash screen buffer."
|
||
(interactive)
|
||
(quit-window t))
|
||
|
||
(defun fancy-startup-screen (&optional concise)
|
||
"Display fancy startup screen.
|
||
If CONCISE is non-nil, display a concise version of the
|
||
splash screen in another window."
|
||
(let ((splash-buffer (get-buffer-create "*GNU Emacs*")))
|
||
(with-current-buffer splash-buffer
|
||
(let ((inhibit-read-only t))
|
||
(erase-buffer)
|
||
(setq default-directory command-line-default-directory)
|
||
(make-local-variable 'startup-screen-inhibit-startup-screen)
|
||
(if pure-space-overflow
|
||
(insert pure-space-overflow-message))
|
||
;; Insert the permissions notice if the user has yet to grant Emacs
|
||
;; storage permissions.
|
||
(when (fboundp 'android-before-splash-screen)
|
||
(funcall 'android-before-splash-screen t))
|
||
(unless concise
|
||
(fancy-splash-head))
|
||
(dolist (text fancy-startup-text)
|
||
(apply #'fancy-splash-insert text)
|
||
(insert "\n"))
|
||
(skip-chars-backward "\n")
|
||
(delete-region (point) (point-max))
|
||
(insert "\n")
|
||
(fancy-startup-tail concise))
|
||
(use-local-map splash-screen-keymap)
|
||
(setq tab-width 22
|
||
buffer-read-only t)
|
||
(set-buffer-modified-p nil)
|
||
(if (and view-read-only (not view-mode))
|
||
(view-mode-enter nil 'kill-buffer))
|
||
(goto-char (point-min))
|
||
(forward-line (if concise 2 4)))
|
||
(if concise
|
||
(progn
|
||
(display-buffer splash-buffer)
|
||
;; If the splash screen is in a split window, fit it.
|
||
(let ((window (get-buffer-window splash-buffer t)))
|
||
(or (null window)
|
||
(eq window (selected-window))
|
||
(eq window (next-window window))
|
||
(fit-window-to-buffer window))))
|
||
(switch-to-buffer splash-buffer))))
|
||
|
||
(defun fancy-about-screen ()
|
||
"Display fancy About screen."
|
||
(let ((frame (fancy-splash-frame)))
|
||
(save-selected-window
|
||
(select-frame frame)
|
||
(switch-to-buffer "*About GNU Emacs*")
|
||
(setq buffer-undo-list t)
|
||
(let ((inhibit-read-only t))
|
||
(erase-buffer)
|
||
(if pure-space-overflow
|
||
(insert pure-space-overflow-message))
|
||
(fancy-splash-head)
|
||
(dolist (text fancy-about-text)
|
||
(apply #'fancy-splash-insert text)
|
||
(insert "\n"))
|
||
(set-buffer-modified-p nil)
|
||
(goto-char (point-min))
|
||
(force-mode-line-update))
|
||
(use-local-map splash-screen-keymap)
|
||
(setq tab-width 22)
|
||
(setq buffer-read-only t)
|
||
;; Place point somewhere it doesn't cover a character.
|
||
(goto-char (point-min))
|
||
(re-search-forward "\n$" nil nil 2))))
|
||
|
||
(defun fancy-splash-frame ()
|
||
"Return the frame to use for the fancy splash screen.
|
||
Returning non-nil does not mean we should necessarily
|
||
use the fancy splash screen, but if we do use it,
|
||
we put it on this frame."
|
||
(let (chosen-frame)
|
||
;; MS-Windows needs this to have a chance to make the initial
|
||
;; frame visible.
|
||
(if (eq (window-system) 'w32)
|
||
(sit-for 0 t))
|
||
(if (eq (window-system) 'pgtk)
|
||
(sit-for 0.1 t))
|
||
(dolist (frame (append (frame-list) (list (selected-frame))))
|
||
(if (and (frame-visible-p frame)
|
||
(not (window-minibuffer-p (frame-selected-window frame))))
|
||
(setq chosen-frame frame)))
|
||
;; If there are no visible frames yet, try the selected one.
|
||
(or chosen-frame (selected-frame))))
|
||
|
||
(defun use-fancy-splash-screens-p ()
|
||
"Return t if fancy splash screens should be used."
|
||
(when (and (display-graphic-p)
|
||
(or (and (display-color-p)
|
||
(image-type-available-p 'xpm))
|
||
(image-type-available-p 'pbm)))
|
||
(let ((frame (fancy-splash-frame)))
|
||
(when frame
|
||
(let ((img (create-image (fancy-splash-image-file))))
|
||
(when img
|
||
(let ((image-height (cdr (image-size img nil frame)))
|
||
;; We test frame-height and not window-height so that,
|
||
;; if the frame is split by displaying a warning, that
|
||
;; doesn't cause the normal splash screen to be used.
|
||
;; We subtract 2 from frame-height to account for the
|
||
;; echo area and the mode line.
|
||
(frame-height (- (frame-height frame) 2)))
|
||
(> frame-height (+ image-height 19)))))))))
|
||
|
||
(defun normal-splash-screen (&optional startup concise)
|
||
"Display non-graphic splash screen.
|
||
If optional argument STARTUP is non-nil, display the startup screen
|
||
after Emacs starts. If STARTUP is nil, display the About screen.
|
||
If CONCISE is non-nil, display a concise version of the
|
||
splash screen in another window."
|
||
(let ((splash-buffer (get-buffer-create "*About GNU Emacs*")))
|
||
(with-current-buffer splash-buffer
|
||
(setq buffer-read-only nil)
|
||
(erase-buffer)
|
||
(setq default-directory command-line-default-directory)
|
||
(setq-local tab-width 8)
|
||
|
||
(if pure-space-overflow
|
||
(insert pure-space-overflow-message))
|
||
;; Insert the permissions notice if the user has yet to grant
|
||
;; Emacs storage permissions.
|
||
(when (fboundp 'android-before-splash-screen)
|
||
(funcall 'android-before-splash-screen nil))
|
||
;; The convention for this piece of code is that
|
||
;; each piece of output starts with one or two newlines
|
||
;; and does not end with any newlines.
|
||
(insert (if startup "Welcome to GNU Emacs" "This is GNU Emacs"))
|
||
(insert
|
||
(if (eq system-type 'gnu/linux)
|
||
", one component of the GNU/Linux operating system.\n"
|
||
", a part of the GNU operating system.\n"))
|
||
|
||
(if startup
|
||
(if (display-mouse-p)
|
||
;; The user can use the mouse to activate menus
|
||
;; so give help in terms of menu items.
|
||
(normal-mouse-startup-screen)
|
||
|
||
;; No mouse menus, so give help using kbd commands.
|
||
(normal-no-mouse-startup-screen))
|
||
|
||
(normal-about-screen))
|
||
|
||
;; The rest of the startup screen is the same on all
|
||
;; kinds of terminals.
|
||
|
||
;; Give information on recovering, if there was a crash.
|
||
(and startup
|
||
auto-save-list-file-prefix
|
||
;; Don't signal an error if the
|
||
;; directory for auto-save-list files
|
||
;; does not yet exist.
|
||
(file-directory-p (file-name-directory
|
||
auto-save-list-file-prefix))
|
||
(directory-files
|
||
(file-name-directory auto-save-list-file-prefix)
|
||
nil
|
||
(concat "\\`"
|
||
(regexp-quote (file-name-nondirectory
|
||
auto-save-list-file-prefix)))
|
||
t)
|
||
(insert "\n\nIf an Emacs session crashed recently, "
|
||
"type M-x recover-session RET\nto recover"
|
||
" the files you were editing.\n"))
|
||
(use-local-map splash-screen-keymap)
|
||
|
||
;; Display the input that we set up in the buffer.
|
||
(set-buffer-modified-p nil)
|
||
(setq buffer-read-only t)
|
||
(if (and view-read-only (not view-mode))
|
||
(view-mode-enter nil 'kill-buffer))
|
||
(if startup (rename-buffer "*GNU Emacs*" t))
|
||
(goto-char (point-min)))
|
||
(if concise
|
||
(display-buffer splash-buffer)
|
||
(switch-to-buffer splash-buffer))))
|
||
|
||
(defun normal-mouse-startup-screen ()
|
||
;; The user can use the mouse to activate menus
|
||
;; so give help in terms of menu items.
|
||
(insert "\
|
||
To follow a link, click Mouse-1 on it, or move to it and type RET.
|
||
To quit a partially entered command, type Control-g.\n")
|
||
|
||
(insert "\nImportant Help menu items:\n")
|
||
(insert-button "Emacs Tutorial"
|
||
'action (lambda (_button) (help-with-tutorial))
|
||
'follow-link t)
|
||
(insert "\t\tLearn basic Emacs keystroke commands\n")
|
||
(insert-button "Read the Emacs Manual"
|
||
'action (lambda (_button) (info-emacs-manual))
|
||
'follow-link t)
|
||
(insert "\tView the Emacs manual using Info\n")
|
||
(insert-button "(Non)Warranty"
|
||
'action (lambda (_button) (describe-no-warranty))
|
||
'follow-link t)
|
||
(insert "\t\tGNU Emacs comes with ABSOLUTELY NO WARRANTY\n")
|
||
(insert-button "Copying Conditions"
|
||
'action (lambda (_button) (describe-copying))
|
||
'follow-link t)
|
||
(insert "\tConditions for redistributing and changing Emacs\n")
|
||
(insert-button "More Manuals / Ordering Manuals"
|
||
'action (lambda (_button) (view-order-manuals))
|
||
'follow-link t)
|
||
(insert " How to order printed manuals from the FSF\n")
|
||
|
||
(insert "\nUseful tasks:\n")
|
||
(insert-button "Visit New File"
|
||
'action (lambda (_button) (call-interactively 'find-file))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys
|
||
"\t\tSpecify a new file's name, to edit the file\n"))
|
||
(insert-button "Open Home Directory"
|
||
'action (lambda (_button) (dired "~"))
|
||
'follow-link t)
|
||
(insert "\tOpen your home directory, to operate on its files\n")
|
||
(insert-button "Customize Startup"
|
||
'action (lambda (_button) (customize-group 'initialization))
|
||
'follow-link t)
|
||
(insert "\tChange initialization settings including this screen\n")
|
||
|
||
(save-restriction
|
||
(narrow-to-region (point) (point))
|
||
(insert "\n" (emacs-version) "\n")
|
||
(fill-region (point-min) (point-max)))
|
||
(insert emacs-copyright))
|
||
|
||
(defun normal-no-mouse-startup-screen ()
|
||
"Show a splash screen suitable for displays without mouse support."
|
||
(let* ((c-h-accessible
|
||
;; If normal-erase-is-backspace is used on a tty, there's
|
||
;; no way to invoke C-h and you have to use F1 instead.
|
||
(or (not (char-table-p keyboard-translate-table))
|
||
(eq (aref keyboard-translate-table ?\C-h) ?\C-h)))
|
||
(minor-mode-overriding-map-alist
|
||
(cons (cons (not c-h-accessible)
|
||
;; If C-h can't be invoked, temporarily disable its
|
||
;; binding, so where-is uses alternative bindings.
|
||
(let ((map (make-sparse-keymap)))
|
||
(define-key map [?\C-h] #'undefined)
|
||
map))
|
||
minor-mode-overriding-map-alist)))
|
||
|
||
(insert (format "\nGet help\t %s\n"
|
||
(let ((where (where-is-internal 'help-command nil t)))
|
||
(cond
|
||
((equal where [?\C-h])
|
||
"C-h (Hold down CTRL and press h)")
|
||
(where (key-description where))
|
||
(t "M-x help")))))
|
||
(insert-button "Emacs manual"
|
||
'action (lambda (_button) (info-emacs-manual))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys"\t \\[info-emacs-manual]\t"))
|
||
(insert-button "Browse manuals"
|
||
'action (lambda (_button) (Info-directory))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys "\t \\[info]\n"))
|
||
(insert-button "Emacs tutorial"
|
||
'action (lambda (_button) (help-with-tutorial))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys
|
||
"\t \\[help-with-tutorial]\tUndo changes\t \\[undo]\n"))
|
||
(insert-button "Buy manuals"
|
||
'action (lambda (_button) (view-order-manuals))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys
|
||
"\t \\[view-order-manuals]\tExit Emacs\t \\[save-buffers-kill-terminal]")))
|
||
|
||
;; Say how to use the menu bar with the keyboard.
|
||
(insert "\n")
|
||
(insert-button "Activate menubar"
|
||
'action (lambda (_button) (tmm-menubar))
|
||
'follow-link t)
|
||
(if (and (eq (key-binding "\M-`") 'tmm-menubar)
|
||
(eq (key-binding [f10]) 'tmm-menubar))
|
||
(insert " F10 or ESC ` or M-`")
|
||
(insert (substitute-command-keys " \\[tmm-menubar]")))
|
||
|
||
;; Many users seem to have problems with these.
|
||
(insert (substitute-command-keys "
|
||
\(`C-' means use the CTRL key. `M-' means use the Meta (or Alt) key.
|
||
If you have no Meta key, you may instead type ESC followed by the character.)"))
|
||
|
||
;; Insert links to useful tasks
|
||
(insert "\nUseful tasks:\n")
|
||
|
||
(insert-button "Visit New File"
|
||
'action (lambda (_button) (call-interactively 'find-file))
|
||
'follow-link t)
|
||
(insert "\t\t\t")
|
||
(insert-button "Open Home Directory"
|
||
'action (lambda (_button) (dired "~"))
|
||
'follow-link t)
|
||
(insert "\n")
|
||
|
||
(insert-button "Customize Startup"
|
||
'action (lambda (_button) (customize-group 'initialization))
|
||
'follow-link t)
|
||
(insert "\t\t")
|
||
(insert-button "Open *scratch* buffer"
|
||
'action (lambda (_button) (switch-to-buffer
|
||
(get-scratch-buffer-create)))
|
||
'follow-link t)
|
||
(insert "\n")
|
||
(save-restriction
|
||
(narrow-to-region (point) (point))
|
||
(insert "\n" (emacs-version) "\n")
|
||
(fill-region (point-min) (point-max)))
|
||
(insert emacs-copyright "\n")
|
||
(insert (substitute-command-keys
|
||
"
|
||
GNU Emacs comes with ABSOLUTELY NO WARRANTY; type \\[describe-no-warranty] for "))
|
||
(insert-button "full details"
|
||
'action (lambda (_button) (describe-no-warranty))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys ".
|
||
Emacs is Free Software--Free as in Freedom--so you can redistribute copies
|
||
of Emacs and modify it; type \\[describe-copying] to see "))
|
||
(insert-button "the conditions"
|
||
'action (lambda (_button) (describe-copying))
|
||
'follow-link t)
|
||
(insert (substitute-command-keys".
|
||
Type \\[describe-distribution] for information on "))
|
||
(insert-button "getting the latest version"
|
||
'action (lambda (_button) (describe-distribution))
|
||
'follow-link t)
|
||
(insert "."))
|
||
|
||
(defun normal-about-screen ()
|
||
(insert "\n" (emacs-version) "\n" emacs-copyright "\n\n")
|
||
|
||
(insert "To follow a link, click Mouse-1 on it, or move to it and type RET.\n\n")
|
||
|
||
(insert-button "Authors"
|
||
'action
|
||
(lambda (_button)
|
||
(view-file (expand-file-name "AUTHORS" data-directory))
|
||
(goto-char (point-min)))
|
||
'follow-link t)
|
||
(insert "\t\tMany people have contributed code included in GNU Emacs\n")
|
||
|
||
(insert-button "Contributing"
|
||
'action
|
||
(lambda (_button) (info "(emacs)Contributing"))
|
||
'follow-link t)
|
||
(insert "\tHow to report bugs and contribute improvements to Emacs\n\n")
|
||
|
||
(insert-button "GNU and Freedom"
|
||
'action (lambda (_button)
|
||
(let ((browse-url-browser-function 'eww-browse-url))
|
||
(describe-gnu-project)))
|
||
'follow-link t)
|
||
(insert "\t\tWhy we developed GNU Emacs and the GNU system\n")
|
||
|
||
(insert-button "Absence of Warranty"
|
||
'action (lambda (_button) (describe-no-warranty))
|
||
'follow-link t)
|
||
(insert "\tGNU Emacs comes with ABSOLUTELY NO WARRANTY\n")
|
||
|
||
(insert-button "Copying Conditions"
|
||
'action (lambda (_button) (describe-copying))
|
||
'follow-link t)
|
||
(insert "\tConditions for redistributing and changing Emacs\n")
|
||
|
||
(insert-button "Getting New Versions"
|
||
'action (lambda (_button) (describe-distribution))
|
||
'follow-link t)
|
||
(insert "\tHow to get the latest version of GNU Emacs\n")
|
||
|
||
(insert-button "More Manuals / Ordering Manuals"
|
||
'action (lambda (_button) (view-order-manuals))
|
||
'follow-link t)
|
||
(insert "\tBuying printed manuals from the FSF\n"))
|
||
|
||
(defun startup-echo-area-message ()
|
||
(if (daemonp)
|
||
"Starting Emacs daemon."
|
||
(substitute-command-keys
|
||
"For information about GNU Emacs and the GNU system, type \
|
||
\\[about-emacs].")))
|
||
|
||
(defun display-startup-echo-area-message ()
|
||
(let ((resize-mini-windows t))
|
||
(or noninteractive ;(input-pending-p) init-file-had-error
|
||
;; t if the init file says to inhibit the echo area startup message.
|
||
(and inhibit-startup-echo-area-message
|
||
user-init-file
|
||
(or (and (get 'inhibit-startup-echo-area-message 'saved-value)
|
||
(equal inhibit-startup-echo-area-message
|
||
(if (equal init-file-user "")
|
||
(user-login-name)
|
||
init-file-user)))
|
||
;; Wasn't set with custom; see if .emacs has a setq.
|
||
(condition-case nil
|
||
(with-temp-buffer
|
||
(insert-file-contents user-init-file)
|
||
(re-search-forward
|
||
(concat
|
||
"([ \t\n]*setq[ \t\n]+"
|
||
"inhibit-startup-echo-area-message[ \t\n]+"
|
||
(regexp-quote
|
||
(prin1-to-string
|
||
(if (equal init-file-user "")
|
||
(user-login-name)
|
||
init-file-user)))
|
||
"[ \t\n]*)")
|
||
nil t))
|
||
(error nil))))
|
||
(message "%s" (startup-echo-area-message)))))
|
||
|
||
(defun display-startup-screen (&optional concise)
|
||
"Display startup screen according to display.
|
||
A fancy display is used on graphic displays, normal otherwise.
|
||
|
||
If CONCISE is non-nil, display a concise version of the startup
|
||
screen."
|
||
;; Prevent recursive calls from server-process-filter.
|
||
(if (not (get-buffer "*GNU Emacs*"))
|
||
(if (use-fancy-splash-screens-p)
|
||
(fancy-startup-screen concise)
|
||
(normal-splash-screen t concise))))
|
||
|
||
(defun display-about-screen ()
|
||
"Display the *About GNU Emacs* buffer.
|
||
A fancy display is used on graphic displays, normal otherwise."
|
||
(interactive)
|
||
(if (use-fancy-splash-screens-p)
|
||
(fancy-about-screen)
|
||
(normal-splash-screen nil)))
|
||
|
||
(defalias 'about-emacs #'display-about-screen)
|
||
(defalias 'display-splash-screen #'display-startup-screen)
|
||
|
||
;; This avoids byte-compiler warning in the unexec build.
|
||
(declare-function pdumper-stats "pdumper.c" ())
|
||
|
||
(defun command-line-1 (args-left)
|
||
"A subroutine of `command-line'."
|
||
(display-startup-echo-area-message)
|
||
(when (and pure-space-overflow
|
||
(not noninteractive)
|
||
;; If we were dumped with pdumper, we don't care about
|
||
;; pure-space overflow.
|
||
(or (not (fboundp 'pdumper-stats))
|
||
(null (pdumper-stats))))
|
||
(display-warning
|
||
'initialization
|
||
"Building Emacs overflowed pure space.\
|
||
(See the node Pure Storage in the Lisp manual for details.)"
|
||
:warning))
|
||
|
||
;; `displayable-buffers' is a list of buffers that may be displayed,
|
||
;; which includes files parsed from the command line arguments and
|
||
;; `initial-buffer-choice'. All of the display logic happens at the
|
||
;; end of this `let'. As files as processed from the command line
|
||
;; arguments, their buffers are prepended to `displayable-buffers'.
|
||
;; In order for options like "--eval" to work with the "--file" arg,
|
||
;; the file buffers are set as the current buffer as they are seen
|
||
;; on the command line (so "emacs --batch --file a --file b
|
||
;; --eval='(message "%s" (buffer-name))'" will print "b"), but this
|
||
;; does not affect the final displayed state of the buffers.
|
||
(let ((displayable-buffers nil))
|
||
;; This `let' processes the command line arguments.
|
||
(let ((command-line-args-left args-left))
|
||
(when command-line-args-left
|
||
;; We have command args; process them.
|
||
(let* ((dir command-line-default-directory)
|
||
tem
|
||
;; This approach loses for "-batch -L DIR --eval "(require foo)",
|
||
;; if foo is intended to be found in DIR.
|
||
;;
|
||
;; The directories listed in --directory/-L options will *appear*
|
||
;; at the front of `load-path' in the order they appear on the
|
||
;; command-line. We cannot do this by *placing* them at the front
|
||
;; in the order they appear, so we need this variable to hold them,
|
||
;; temporarily.
|
||
;;
|
||
;; To DTRT we keep track of the splice point and modify `load-path'
|
||
;; straight away upon any --directory/-L option.
|
||
splice
|
||
just-files ;; t if this follows the magic -- option.
|
||
;; This includes our standard options' long versions
|
||
;; and long versions of what's on command-switch-alist.
|
||
(longopts
|
||
(append '("--funcall" "--load" "--insert" "--kill"
|
||
"--dump-file" "--seccomp"
|
||
"--directory" "--eval" "--execute" "--no-splash"
|
||
"--find-file" "--visit" "--file" "--no-desktop")
|
||
(mapcar (lambda (elt) (concat "-" (car elt)))
|
||
command-switch-alist)))
|
||
(line 0)
|
||
(column 0)
|
||
;; `process-file-arg' opens a file buffer for `name',
|
||
;; sets that buffer as the current buffer without
|
||
;; displaying it, adds the buffer to
|
||
;; `displayable-buffers', and puts the point at
|
||
;; `line':`column'. `line' and `column' are both reset
|
||
;; to zero when `process-file-arg' returns.
|
||
(process-file-arg
|
||
(lambda (name)
|
||
;; This can only happen if PWD is deleted.
|
||
(if (not (or dir (file-name-absolute-p name)))
|
||
(message "Ignoring relative file name (%s) due to \
|
||
nil default-directory" name)
|
||
(let* ((file (expand-file-name
|
||
(command-line-normalize-file-name name)
|
||
dir))
|
||
(buf (find-file-noselect file)))
|
||
(file-name-history--add file)
|
||
(setq displayable-buffers (cons buf displayable-buffers))
|
||
;; Set the file buffer to the current buffer so
|
||
;; that it will be used with "--eval" and
|
||
;; similar options.
|
||
(set-buffer buf)
|
||
;; Put the point at `line':`column' in the file
|
||
;; buffer, and reset `line' and `column' to 0.
|
||
(unless (zerop line)
|
||
(goto-char (point-min))
|
||
(forward-line (1- line)))
|
||
(setq line 0)
|
||
(unless (< column 1)
|
||
(move-to-column (1- column)))
|
||
(setq column 0))))))
|
||
|
||
;; Add the long X options to longopts.
|
||
(dolist (tem command-line-x-option-alist)
|
||
(if (string-match "^--" (car tem))
|
||
(push (car tem) longopts)))
|
||
|
||
;; Add the long NS options to longopts.
|
||
(dolist (tem command-line-ns-option-alist)
|
||
(if (string-match "^--" (car tem))
|
||
(push (list (car tem)) longopts)))
|
||
|
||
;; Loop, processing options.
|
||
(while command-line-args-left
|
||
(let* ((argi (car command-line-args-left))
|
||
(orig-argi argi)
|
||
argval completion)
|
||
(setq command-line-args-left (cdr command-line-args-left))
|
||
|
||
;; Do preliminary decoding of the option.
|
||
(if just-files
|
||
;; After --, don't look for options; treat all args as files.
|
||
(setq argi "")
|
||
;; Convert long options to ordinary options
|
||
;; and separate out an attached option argument into argval.
|
||
(when (string-match "\\`\\(--[^=]*\\)=" argi)
|
||
(setq argval (substring argi (match-end 0))
|
||
argi (match-string 1 argi)))
|
||
(when (string-match "\\`--?[^-]" orig-argi)
|
||
(setq completion (try-completion argi longopts))
|
||
(if (eq completion t)
|
||
(setq argi (substring argi 1))
|
||
(if (stringp completion)
|
||
(let ((elt (member completion longopts)))
|
||
(or elt
|
||
(error "Option `%s' is ambiguous" argi))
|
||
(setq argi (substring (car elt) 1)))
|
||
(setq argval nil
|
||
argi orig-argi)))))
|
||
|
||
;; Execute the option.
|
||
(cond ((setq tem (assoc argi command-switch-alist))
|
||
(if argval
|
||
(let ((command-line-args-left
|
||
(cons argval command-line-args-left)))
|
||
(funcall (cdr tem) argi))
|
||
(funcall (cdr tem) argi)))
|
||
|
||
((equal argi "-no-splash")
|
||
(setq inhibit-startup-screen t))
|
||
|
||
((member argi '("-f" ; what the manual claims
|
||
"-funcall"
|
||
"-e")) ; what the source used to say
|
||
(setq inhibit-startup-screen t)
|
||
(setq tem (intern (or argval (pop command-line-args-left))))
|
||
(if (commandp tem)
|
||
(command-execute tem)
|
||
(funcall tem)))
|
||
|
||
((member argi '("-eval" "-execute"))
|
||
(setq inhibit-startup-screen t)
|
||
(let* ((str-expr (or argval (pop command-line-args-left)))
|
||
(read-data (read-from-string str-expr))
|
||
(expr (car read-data))
|
||
(end (cdr read-data)))
|
||
;; Allow same trailing chars as minibuf.c's
|
||
;; `string_to_object'.
|
||
(unless (string-match-p "[\s\t\n]*\\'" str-expr end)
|
||
(error "Trailing garbage following expression: %s"
|
||
(substring str-expr end)))
|
||
(eval expr t)))
|
||
|
||
((member argi '("-L" "-directory"))
|
||
;; -L :/foo adds /foo to the _end_ of load-path.
|
||
(let (append)
|
||
(if (string-match-p
|
||
(format "\\`%s" path-separator)
|
||
(setq tem (or argval (pop command-line-args-left))))
|
||
(setq tem (substring tem 1)
|
||
append t))
|
||
(setq tem (expand-file-name
|
||
(command-line-normalize-file-name tem)))
|
||
(cond (append (setq load-path
|
||
(append load-path (list tem)))
|
||
(if splice (setq splice load-path)))
|
||
(splice (setcdr splice (cons tem (cdr splice)))
|
||
(setq splice (cdr splice)))
|
||
(t (setq load-path (cons tem load-path)
|
||
splice load-path)))))
|
||
|
||
((member argi '("-l" "-load"))
|
||
(let* ((file (command-line-normalize-file-name
|
||
(or argval (pop command-line-args-left))))
|
||
;; Take file from default dir if it exists there;
|
||
;; otherwise let `load' search for it.
|
||
(file-ex (file-truename (expand-file-name file))))
|
||
(when (file-regular-p file-ex)
|
||
(setq file file-ex))
|
||
(load file nil t)))
|
||
|
||
;; This is used to handle -script. It's not clear
|
||
;; we need to document it (it is totally internal).
|
||
((member argi '("-scriptload" "-scripteval"))
|
||
(let* ((file (command-line-normalize-file-name
|
||
(or argval (pop command-line-args-left))))
|
||
;; Take file from default dir.
|
||
(file-ex (expand-file-name file))
|
||
(truename (file-truename file-ex)))
|
||
;; We want to use the truename here if we can,
|
||
;; because that makes `eval-after-load' work
|
||
;; more reliably. But if the file is, for
|
||
;; instance, /dev/stdin, the truename doesn't
|
||
;; actually exist on some systems.
|
||
(when (file-exists-p truename)
|
||
(setq file-ex truename))
|
||
(if (equal argi "-scripteval")
|
||
;; This will kill Emacs.
|
||
(command-line--eval-script file-ex)
|
||
(command-line--load-script file-ex))))
|
||
|
||
((equal argi "-insert")
|
||
(setq inhibit-startup-screen t)
|
||
(setq tem (or argval (pop command-line-args-left)))
|
||
(or (stringp tem)
|
||
(error "File name omitted from `-insert' option"))
|
||
(insert-file-contents (command-line-normalize-file-name tem)))
|
||
|
||
((or (equal argi "-dump-file")
|
||
(equal argi "-seccomp"))
|
||
;; This was processed in C.
|
||
(or argval (pop command-line-args-left)))
|
||
|
||
((equal argi "-kill")
|
||
(kill-emacs t))
|
||
|
||
;; This is for when they use --no-desktop with -q, or
|
||
;; don't load Desktop in their .emacs. If desktop.el
|
||
;; _is_ loaded, it will handle this switch, and we
|
||
;; won't see it by the time we get here.
|
||
((equal argi "-no-desktop")
|
||
(message "\"--no-desktop\" ignored because the Desktop package is not loaded"))
|
||
|
||
((string-match "^\\+[0-9]+\\'" argi)
|
||
(setq line (string-to-number argi)))
|
||
|
||
((string-match "^\\+\\([0-9]+\\):\\([0-9]+\\)\\'" argi)
|
||
(setq line (string-to-number (match-string 1 argi))
|
||
column (string-to-number (match-string 2 argi))))
|
||
|
||
((setq tem (assoc orig-argi command-line-x-option-alist))
|
||
;; Ignore X-windows options and their args if not using X.
|
||
(setq command-line-args-left
|
||
(nthcdr (nth 1 tem) command-line-args-left)))
|
||
|
||
((setq tem (assoc orig-argi command-line-ns-option-alist))
|
||
;; Ignore NS-windows options and their args if not using NS.
|
||
(setq command-line-args-left
|
||
(nthcdr (nth 1 tem) command-line-args-left)))
|
||
|
||
((member argi '("-find-file" "-file" "-visit"))
|
||
(setq inhibit-startup-screen t)
|
||
;; An explicit option to specify visiting a file.
|
||
(setq tem (or argval (pop command-line-args-left)))
|
||
(unless (stringp tem)
|
||
(error "File name omitted from `%s' option" argi))
|
||
(funcall process-file-arg tem))
|
||
|
||
;; These command lines now have no effect.
|
||
((string-match "\\`--?\\(no-\\)?\\(uni\\|multi\\)byte$" argi)
|
||
(display-warning 'initialization
|
||
(format "Ignoring obsolete arg %s" argi)))
|
||
|
||
((equal argi "--")
|
||
(setq just-files t))
|
||
(t
|
||
;; We have almost exhausted our options. See if the
|
||
;; user has made any other command-line options available
|
||
(let ((hooks command-line-functions)
|
||
(did-hook nil))
|
||
(while (and hooks
|
||
(not (setq did-hook (funcall (car hooks)))))
|
||
(setq hooks (cdr hooks)))
|
||
(unless did-hook
|
||
;; Presume that the argument is a file name.
|
||
(if (string-match "\\`-" argi)
|
||
(error "Unknown option `%s'" argi))
|
||
;; FIXME: Why do we only inhibit the startup
|
||
;; screen for -nw?
|
||
(unless initial-window-system
|
||
(setq inhibit-startup-screen t))
|
||
(funcall process-file-arg orig-argi)))))
|
||
|
||
;; In unusual circumstances, the execution of Lisp code due
|
||
;; to command-line options can cause the last visible frame
|
||
;; to be deleted. In this case, kill emacs to avoid an
|
||
;; abort later.
|
||
(unless (frame-live-p (selected-frame)) (kill-emacs nil)))))))
|
||
|
||
(when (eq initial-buffer-choice t)
|
||
;; When `initial-buffer-choice' equals t make sure that *scratch*
|
||
;; exists.
|
||
(get-scratch-buffer-create))
|
||
|
||
;; If *scratch* exists and is empty, insert initial-scratch-message.
|
||
;; Do this before switching to *scratch* below to handle bug#9605.
|
||
(and initial-scratch-message
|
||
(get-buffer "*scratch*")
|
||
(with-current-buffer "*scratch*"
|
||
(when (zerop (buffer-size))
|
||
(insert (substitute-command-keys initial-scratch-message))
|
||
(set-buffer-modified-p nil))))
|
||
|
||
;; Prepend `initial-buffer-choice' to `displayable-buffers'. If
|
||
;; the buffer is already a member of that list then shift the
|
||
;; buffer to the head of the list. The shift behavior is intended
|
||
;; to prevent the same buffer being displayed in two windows when
|
||
;; an `initial-buffer-choice' function happens to return the head
|
||
;; of `displayable-buffers'.
|
||
(when initial-buffer-choice
|
||
(let ((buf
|
||
(cond ((stringp initial-buffer-choice)
|
||
(find-file-noselect initial-buffer-choice))
|
||
((functionp initial-buffer-choice)
|
||
(funcall initial-buffer-choice))
|
||
((eq initial-buffer-choice t)
|
||
(get-scratch-buffer-create))
|
||
(t
|
||
(error "`initial-buffer-choice' must be a string, a function, or t")))))
|
||
(unless (buffer-live-p buf)
|
||
(error "Value returned by `initial-buffer-choice' is not a live buffer: %S" buf))
|
||
(setq displayable-buffers (cons buf (delq buf displayable-buffers)))))
|
||
|
||
;; Display the first two buffers in `displayable-buffers'. If
|
||
;; `initial-buffer-choice' is non-nil, its buffer will be the
|
||
;; first buffer in `displayable-buffers'. The first buffer will
|
||
;; be focused.
|
||
(let ((displayable-buffers-len (length displayable-buffers))
|
||
;; `nondisplayed-buffers-p' is true if there exist buffers
|
||
;; in `displayable-buffers' that were not displayed to the
|
||
;; user.
|
||
(nondisplayed-buffers-p nil)
|
||
(old-face-font-rescale-alist face-font-rescale-alist))
|
||
(when (> displayable-buffers-len 0)
|
||
(switch-to-buffer (car displayable-buffers)))
|
||
(cond
|
||
;; Two buffers; display them both.
|
||
((= displayable-buffers-len 2)
|
||
(switch-to-buffer-other-window (cadr displayable-buffers))
|
||
;; Focus on the first buffer.
|
||
(other-window -1))
|
||
;; More than two buffers: Ensure that the buffer display order
|
||
;; reflects the order they were given on the command line.
|
||
;; (This will end up with a `next-buffer' order that's in
|
||
;; reverse order -- the final file is the focused one, and then
|
||
;; the rest are in `next-buffer' in descending order.
|
||
((> displayable-buffers-len 2)
|
||
(let ((bufs (reverse (cdr displayable-buffers))))
|
||
(switch-to-buffer-other-window (pop bufs))
|
||
(dolist (buf bufs)
|
||
(switch-to-buffer buf nil t))
|
||
;; Focus on the first buffer.
|
||
(other-window -1))))
|
||
(when (> displayable-buffers-len 2)
|
||
(setq nondisplayed-buffers-p t))
|
||
|
||
(if (or inhibit-startup-screen
|
||
initial-buffer-choice
|
||
noninteractive
|
||
(daemonp)
|
||
inhibit-x-resources)
|
||
|
||
;; Not displaying a startup screen. Display *Buffer List* if
|
||
;; there exist buffers that were not displayed.
|
||
(when (and nondisplayed-buffers-p
|
||
(not noninteractive)
|
||
(not inhibit-startup-buffer-menu))
|
||
(list-buffers))
|
||
|
||
;; Display a startup screen, after some preparations.
|
||
|
||
;; If there are no switches to process, we might as well
|
||
;; run this hook now, and there may be some need to do it
|
||
;; before doing any output.
|
||
(run-hooks 'emacs-startup-hook 'term-setup-hook)
|
||
|
||
;; See the commentary in `normal-top-level' for why we do
|
||
;; this.
|
||
(when (and (display-multi-font-p)
|
||
(not (eq face-font-rescale-alist
|
||
old-face-font-rescale-alist))
|
||
(assoc (font-xlfd-name (face-attribute 'default :font))
|
||
face-font-rescale-alist #'string-match-p))
|
||
(set-face-attribute 'default nil :font (font-spec)))
|
||
|
||
;; It's important to notice the user settings before we
|
||
;; display the startup message; otherwise, the settings
|
||
;; won't take effect until the user gives the first
|
||
;; keystroke, and that's distracting.
|
||
(when (fboundp 'frame-notice-user-settings)
|
||
(frame-notice-user-settings))
|
||
|
||
;; If there are no switches to process, we might as well
|
||
;; run this hook now, and there may be some need to do it
|
||
;; before doing any output.
|
||
(run-hooks 'window-setup-hook)
|
||
|
||
(setq inhibit-startup-hooks t)
|
||
|
||
;; ;; Do this now to avoid an annoying delay if the user
|
||
;; ;; clicks the menu bar during the sit-for.
|
||
;; (when (display-popup-menus-p)
|
||
;; (precompute-menubar-bindings))
|
||
;; (with-no-warnings
|
||
;; (setq menubar-bindings-done t))
|
||
|
||
(display-startup-screen (> displayable-buffers-len 0))))))
|
||
|
||
(defun command-line--load-script (file)
|
||
(load-with-code-conversion
|
||
file file nil t
|
||
(lambda (buffer file)
|
||
(with-current-buffer buffer
|
||
(goto-char (point-min))
|
||
;; Removing the #! and then calling `eval-buffer' will make the
|
||
;; reader not signal an error if it then turns out that the
|
||
;; buffer is empty.
|
||
(when (looking-at "#!")
|
||
(delete-line))
|
||
(eval-buffer buffer nil file nil t)))))
|
||
|
||
(defun command-line--eval-script (file)
|
||
(load-with-code-conversion
|
||
file file nil t
|
||
(lambda (buffer _)
|
||
(with-current-buffer buffer
|
||
(goto-char (point-min))
|
||
(when (looking-at "#!")
|
||
(forward-line))
|
||
(let (value form)
|
||
(while (ignore-error end-of-file
|
||
(setq form (read (current-buffer))))
|
||
(setq value (eval form t)))
|
||
(kill-emacs (if (numberp value)
|
||
value
|
||
0)))))))
|
||
|
||
(defun command-line-normalize-file-name (file)
|
||
"Collapse multiple slashes to one, to handle non-Emacs file names."
|
||
(save-match-data
|
||
;; Use arg 1 so that we don't collapse // at the start of the file name.
|
||
;; That is significant on some systems.
|
||
;; However, /// at the beginning is supposed to mean just /, not //.
|
||
(if (string-match
|
||
(if (memq system-type '(ms-dos windows-nt))
|
||
"^\\([\\/][\\/][\\/]\\)+"
|
||
"^///+")
|
||
file)
|
||
(setq file (replace-match "/" t t file)))
|
||
(if (memq system-type '(ms-dos windows-nt))
|
||
(while (string-match "\\([\\/][\\/]\\)+" file 1)
|
||
(setq file (replace-match "/" t t file)))
|
||
(while (string-match "//+" file 1)
|
||
(setq file (replace-match "/" t t file))))
|
||
file))
|
||
|
||
;;; startup.el ends here
|