From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Samer Masterson Newsgroups: gmane.emacs.devel Subject: Re: [PATCH] switch to file buffer from command line args regardless of `initial-buffer-choice' Date: Fri, 15 May 2015 20:11:03 -0700 Message-ID: <87oall2p4o.fsf@f-box.i-did-not-set--mail-host-address--so-tickle-me> References: <1425283676.2563.0@mail.samertm.com> <87fv7ge61j.fsf@f-box.i-did-not-set--mail-host-address--so-tickle-me> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1431745901 26400 80.91.229.3 (16 May 2015 03:11:41 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 16 May 2015 03:11:41 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat May 16 05:11:33 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1YtSVg-0007aJ-Ib for ged-emacs-devel@m.gmane.org; Sat, 16 May 2015 05:11:32 +0200 Original-Received: from localhost ([::1]:33516 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtSVf-0005IY-Tm for ged-emacs-devel@m.gmane.org; Fri, 15 May 2015 23:11:31 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:33952) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtSVO-0005II-NK for emacs-devel@gnu.org; Fri, 15 May 2015 23:11:18 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YtSVL-0002zx-2P for emacs-devel@gnu.org; Fri, 15 May 2015 23:11:14 -0400 Original-Received: from mx1.mailbox.org ([80.241.60.212]:42158) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtSVK-0002zn-L3 for emacs-devel@gnu.org; Fri, 15 May 2015 23:11:10 -0400 Original-Received: from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.mailbox.org (Postfix) with ESMTPS id EAC4640008; Sat, 16 May 2015 05:11:09 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de Original-Received: from smtp1.mailbox.org ([80.241.60.240]) by gerste.heinlein-support.de (gerste.heinlein-support.de [91.198.250.173]) (amavisd-new, port 10030) with ESMTP id JftvLSdg5A-L; Sat, 16 May 2015 05:11:07 +0200 (CEST) In-Reply-To: <87fv7ge61j.fsf@f-box.i-did-not-set--mail-host-address--so-tickle-me> User-Agent: Notmuch/0.19 (http://notmuchmail.org) Emacs/25.0.50.1 (x86_64-unknown-linux-gnu) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 80.241.60.212 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:186523 Archived-At: Ping. Don't worry if you haven't gotten to this yet. -s Samer Masterson writes: > Stefan Monnier writes: > >> IIUC the problem you're trying to fix is specific to >> initial-buffer-choice and does not happen to the default *scratch*. >> Right? > > Correct. > >> >>> - (switch-to-buffer >>> - (if (buffer-live-p buf) buf (get-buffer-create "*scratch*")) >>> - 'norecord))) >>> + (unless (> file-count 0) >>> + (switch-to-buffer >>> + (if (buffer-live-p buf) buf (get-buffer-create "*scratch*")) >>> + 'norecord)))) >> >> So I don't understand why this patch applies to a part of the code that >> handles initial-buffer-choice and *scratch* in a similar way. > > That section of the code is confusing. `initial-buffer-choice' opens > *scratch* when its value is t, and that's what this line does: > > (if (buffer-live-p buf) buf (get-buffer-create "*scratch*")) > > It's unrelated to how *scratch* is (usually) the initial buffer when > `inhibit-startup-screen' is t and `initial-buffer-choice' is nil. > > The function `command-line-1' relies on a bunch of implicit state to set > up Emacs and is kind of hairy, so I refactored it a bit. This is how > `command-line-1' works without my patch applied: > > Before `command-line-1' has been called, *scratch* is already open > (unless the user put '(kill-buffer "*scratch*")' in their init, then > *Messages* will be open, and so on). > > Then `command-line-1' goes through all the args and opens files as it > processes them (and whether the file is opened in the current window or > the other window depends on whether `inhibit-startup-screen' is > non-nil). > > After it's finished processing the command line args, it switches to the > buffer `initial-buffer-choice'. It does not open the startup screen if > `initial-buffer-choice' is non-nil, and it does not switch to any files. > It will open *Buffers List* if three or more files are given to it. > > The behavior with my patch: If Emacs is given one file arg, it's opened > alongside `initial-buffer-choice'. If Emacs is given two or more file > args, then it will display `initial-buffer-choice' and *Buffer List*, > which is consistent with the current behavior when > `initial-buffer-choice' is nil and Emacs is given more files than it can > display. > > I've separated the command line processing logic for files from the > buffer switching logic. This makes it much more clear what the final > state of the windows will be. Also, whether the buffer list gets displayed is > based on how many buffers are shown, not how many file args there are. > > Thanks in advance for the review! > > Best, > Samer > > Patch below: > > From a8e7ec07cffa17719b88bf6022a463b7f812db24 Mon Sep 17 00:00:00 2001 > From: Samer Masterson > Date: Fri, 1 May 2015 06:51:14 -0700 > Subject: [PATCH] Show files when `initial-buffer-choice' is non-nil > > * startup.el (command-line-1): When Emacs is given a file as an > argument and `initial-buffer-choice' is non-nil, display both the file > and `initial-buffer-choice'. For more than one file, show > `initial-buffer-choice' and *Buffer List*. Refactor display-changing > commands out of the command line arg parser. > (initial-buffer-choice): Clarify docstring. > --- > etc/NEWS | 7 + > lisp/startup.el | 581 +++++++++++++++++++++++++++++--------------------------- > 2 files changed, 310 insertions(+), 278 deletions(-) > > diff --git a/etc/NEWS b/etc/NEWS > index e2b6b11..1193055 100644 > --- a/etc/NEWS > +++ b/etc/NEWS > @@ -70,6 +70,13 @@ so if you want to use it, you can always take a copy from an older Emacs. > > * Startup Changes in Emacs 25.1 > > +** When Emacs is given a file as a command line argument and > +`initial-buffer-choice' is non-nil, display both the file and > +`initial-buffer-choice'. When Emacs is given more than one file and > +`initial-buffer-choice' is non-nil, show `initial-buffer-choice' > +and *Buffer List*. This makes Emacs convenient to use from the > +command line when `initial-buffer-choice' is non-nil. > + > > * Changes in Emacs 25.1 > > diff --git a/lisp/startup.el b/lisp/startup.el > index cb8a6a9..b189f84 100644 > --- a/lisp/startup.el > +++ b/lisp/startup.el > @@ -47,6 +47,9 @@ 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 > @@ -2145,238 +2148,238 @@ A fancy display is used on graphic displays, normal otherwise." > (See the node Pure Storage in the Lisp manual for details.)" > :warning)) > > - (let ((file-count 0) > - (command-line-args-left args-left) > - first-file-buffer) > - (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" > - "--directory" "--eval" "--execute" "--no-splash" > - "--find-file" "--visit" "--file" "--no-desktop") > - (mapcar (lambda (elt) (concat "-" (car elt))) > - command-switch-alist))) > - (line 0) > - (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) > - (eval (read (or argval (pop command-line-args-left))))) > - > - ((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 (expand-file-name file))) > - (when (file-exists-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")) > - (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))) > - (load file-ex nil t t))) > - > - ((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))) > - > - ((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)) > - (setq file-count (1+ file-count)) > - (let ((file (expand-file-name > - (command-line-normalize-file-name tem) > - dir))) > - (if (= file-count 1) > - (setq first-file-buffer (find-file file)) > - (find-file-other-window file))) > - (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)) > - > - ;; 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))) > - (if (not did-hook) > - ;; Presume that the argument is a file name. > - (progn > - (if (string-match "\\`-" argi) > - (error "Unknown option `%s'" argi)) > - (unless initial-window-system > - (setq inhibit-startup-screen t)) > - (setq file-count (1+ file-count)) > - (let ((file > - (expand-file-name > - (command-line-normalize-file-name orig-argi) > - dir))) > - (cond ((= file-count 1) > - (setq first-file-buffer (find-file file))) > - (inhibit-startup-screen > - (find-file-other-window file)) > - (t (find-file file)))) > - (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)))))) > - ;; 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)))))) > + ;; `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' > + ;; but they are not displayed until command line parsing has > + ;; finished. > + (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" > + "--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' > + ;; without switching to the buffer, 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) > + (let* ((file (expand-file-name > + (command-line-normalize-file-name name) > + dir)) > + (buf (find-file-noselect file))) > + (setq displayable-buffers (cons buf displayable-buffers)) > + (with-current-buffer buf > + (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) > + (eval (read (or argval (pop command-line-args-left))))) > + > + ((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 (expand-file-name file))) > + (when (file-exists-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")) > + (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))) > + (load file-ex nil t t))) > + > + ((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))) > + > + ((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* > + ;; When `initial-buffer-choice' equals t make sure that *scratch* > ;; exists. > (get-buffer-create "*scratch*")) > > @@ -2389,59 +2392,81 @@ A fancy display is used on graphic displays, normal otherwise." > (insert initial-scratch-message) > (set-buffer-modified-p nil)))) > > + ;; Prepend `initial-buffer-choice' to `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))))) > - (switch-to-buffer > - (if (buffer-live-p buf) buf (get-buffer-create "*scratch*")) > - 'norecord))) > - > - (if (or inhibit-startup-screen > - initial-buffer-choice > - noninteractive > - (daemonp) > - inhibit-x-resources) > - > - ;; Not displaying a startup screen. If 3 or more files > - ;; visited, and not all visible, show user what they all are. > - (and (> file-count 2) > - (not noninteractive) > - (not inhibit-startup-buffer-menu) > - (or (get-buffer-window first-file-buffer) > - (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) > - > - ;; 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 (> file-count 0))))) > + (funcall initial-buffer-choice)) > + ((eq initial-buffer-choice t) > + (get-buffer-create "*scratch*")) > + (t > + (error "initial-buffer-choice must be a string, a function, or t."))))) > + (unless (buffer-live-p buf) > + (error "initial-buffer-choice is not a live buffer.")) > + (setq displayable-buffers (cons 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)) > + (when (> displayable-buffers-len 0) > + (switch-to-buffer (car displayable-buffers))) > + (when (> displayable-buffers-len 1) > + (switch-to-buffer-other-window (car (cdr displayable-buffers))) > + ;; 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) > + > + ;; 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-normalize-file-name (file) > "Collapse multiple slashes to one, to handle non-Emacs file names."