[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user")
From: |
Michal Nazarewicz |
Subject: |
Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user") |
Date: |
Tue, 03 Mar 2015 18:48:24 +0100 |
User-agent: |
Notmuch/0.19+53~g2e63a09 (http://notmuchmail.org) Emacs/25.0.50.1 (x86_64-unknown-linux-gnu) |
On Tue, Mar 03 2015, Eli Zaretskii <address@hidden> wrote:
>> From: Michal Nazarewicz <address@hidden>
>> Cc: address@hidden, address@hidden
>> Date: Mon, 02 Mar 2015 21:37:56 +0100
>>
>> >> Looking at that code, it appears it’s inconsistent on Windows when it
>> >> comes to handling ~/.emacs.d/init.el. If I understand it correctly,
>> >> here’s how Emacs behave on Windows:
>> >>
>> >> * emacs -> load ~/.emacs, ~/_emacs or ~/.emacs.d/init.el
>> >> * emacs -u foo -> load ~/.emacs or ~/_emacs
>> >
>> > I'm not bothered about the inconsistency, since the "-u foo"
>> > "handling" is a kludge for a situation that shouldn't happen. I
>> > wouldn't object to emitting an error in that case.
>>
>> Doesn’t this basically mean doing this:
>>
>> - (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
>> + (unless (file-directory-p (expand-file-name
>> + (concat "~" init-file-user)))
>> + (display-warning 'initialization
>>
>> and then using ~user/… for every system including windows-nt?
>
> Not exactly. First, we had what you suggest before 1df1e49eb, so
> going back to that code means re-introducing the problem it solved.
1df1e49eb actually makes sense to me (since windows-nt ignores
`init-file-user' when looking for .emacs) but 5463218ce doesn’t since
ms-dos uses `init-file-user' when looking for _emacs.
> Second, it's not really nice to have init-file-user have the value of,
> say, "~bob/.emacs", when Emacs was invoked with "-u bob", whereas in
> fact we loaded "C:/fred's-home/.emacs".
That does not happen. If an init file has been loaded, `user-itni-file'
variable *will* point to it.
However, if ‘bob’ is not a valid user, and fred runs Emacs with ‘-u
bob’, `init-file-user' will be "bob" while `user-init-file' will be:
* on Windows: "C:/fred's-home/.emacs" (if that file exists) or
"~/.emacs" (if it does not);
* on DOS: "D:/current/dir/~bob/_emacs" (if that file exists) or
"~bob/_emacs" (if it does not); and
* on POSIX: "/current/dir/~bob/.emacs" (if that file exists) or
"~bob/.emacs" (if it does not).
If ‘bob’ is a valid user with a home directory though, `user-init-file'
will be:
* on Windows: "C:/fred's-home/.emacs" (if that file exists) or
"~/.emacs" (if it does not);
* on DOS: "C:/bob's-home/_emacs" (if that file exists) or
"~bob/_emacs" (if it does not); and
* on POSIX: "/home/bob/.emacs" (if that file exists) or
"~bob/.emacs" (if it does not).
Furthermore:
* DOS port will check "C:/fred's-home" directory even though it will try
to load "C:/fred's-home/~bob/_emacs" or "C:/bob's-home/_emacs" file; and
* Windows port will load "C:/fred's-home/.emacs" even if
"C:/bob's-home/.emacs" or "C:/fred's-home/~bob/.emacs" exists.
> It's a lie, and one that's tricky to untangle: you need to know that
> to get a _real_ file name, you need to run it through
> expand-file-name. If you don't, things will subtly fail, e.g., if you
> compare this with some other file name.
This is already a problem on *all* systems and it happens if user init
file is not found. If you run ‘emacs -u foo’ on GNU/Linux, you’ll end
up with `user-init-file" equal to "~foo/.emacs".
> So I'd rather we either errored out with such invocation, or fixed the
> value to not lie, as we do now.
>
>> If I understand correctly, ~user/… expansion depends on getpwnam and a)
>> on MS-DOS DJGPP provides it (by having a single pw entry for user ==
>> current user), b) on W32 src/w32.c provides it (with the same
>> implementation) and on POSIX we have it properly implemented.
> Another important piece of the puzzle is that if USER is not
> recognized as a valid user by the getpwnam emulation on
> MS-Windows/MS-DOS, you get this:
>
> (expand-file-name "~USER") => /current/directory/~USER
>
> And it is possible to have a literal "~USER" directory, in which case
> the warning will be incorrectly skipped.
This also happens on UNIX-like systems. Like I’ve said above, if you
run ‘emacs -u foo’ on GNU/Linux, you end up with "~foo/.emacs"
`user-init-file'. You also end up with ‘User foo has no home directory’
warning.
Based on all that, I think the most consistent option is to:
1) always check if ~USER/ directory exists for the ‘User foo has no home
directory’ warning;
2) user ~USER/.emacs and ~USER/_emacs on MS-Windows; and
3) use `expand-file-name' when setting `user-init-file' if init file has
not been loaded.
The below untested patch does that plus stops Emacs from attempting to
load init file if `init-file-user' is ‘invalid’, i.e. contains ~, /, :
or \n.
>From d96e4d6e4f9ed3919351f81bdb50412f9a1ea178 Mon Sep 17 00:00:00 2001
From: Michal Nazarewicz <address@hidden>
Date: Tue, 3 Mar 2015 18:44:27 +0100
Subject: [PATCH] startup.el: Harmonise initialisation file loading across
systems
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* lisp/startup.el (command-line): Change how initialisation file is
loaded on various systems in the effort to harmonise it and get rid
of various inconsistencies.
1. If init file has not been loaded, the `user-file-user' will now
be an absolute path rather than "~/.emacs" (or "~/_emacs" on DOS).
2. With ‘-u’ argument, MS-Windows version of Emacs will now try to
load ~USER/.emacs, ~USER/_emacs and finally ~USER/.emacs.d/init
files (in that order) rather than ~/.emacs, ~/_emacs and
~USER/.emacs.d/init.
NB: If `-u’ argument specifies an unknown user, expansion of
"~USER/…" yields "/current/working/directory/~USER/…" This is
nothing new and it’s how *NIX and DOS ports behaved already.
3. With ‘-u’ argument, MS-DOS and MS-Windows versions will check if
"~USER/" directory exists before issuing a ‘user has no home’
warning. This is consistent with the fact that both those ports
will attempt to read files inside of "~USER/". (For MS-DOS port,
the latter has already been the case, but it checked "~/"
nonetheless).
---
lisp/startup.el | 159 ++++++++++++++++++++++----------------------------------
1 file changed, 63 insertions(+), 96 deletions(-)
diff --git a/lisp/startup.el b/lisp/startup.el
index 999e53e..0bfb5f0 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1043,108 +1043,75 @@ (defun command-line ()
(setq inhibit-startup-screen nil)
;; Warn for invalid user name.
- (when init-file-user
- (if (string-match "[~/:\n]" init-file-user)
- (display-warning 'initialization
- (format "Invalid user name %s"
- init-file-user)
- :error)
- (if (file-directory-p (expand-file-name
- ;; We don't support ~USER on MS-Windows
- ;; and MS-DOS except for the current
- ;; user, and always load .emacs from
- ;; the current user's home directory
- ;; (see below). So always check "~",
- ;; even if invoked with "-u USER", or
- ;; if $USER or $LOGNAME are set to
- ;; something different.
- (if (memq system-type '(windows-nt ms-dos))
- "~"
- (concat "~" init-file-user))))
- nil
- (display-warning 'initialization
- (format "User %s has no home directory"
- (if (equal init-file-user "")
- (user-real-login-name)
- init-file-user))
- :error))))
-
;; Load that user's init file, or the default one, or none.
(let (debug-on-error-from-init-file
debug-on-error-should-be-set
(debug-on-error-initial
(if (eq init-file-debug t) 'startup init-file-debug))
- (orig-enable-multibyte (default-value 'enable-multibyte-characters)))
+ (orig-enable-multibyte (default-value 'enable-multibyte-characters))
+ home-dir)
+
+ (when init-file-user
+ (if (string-match "[~/:\n]" init-file-user)
+ (display-warning 'initialization
+ (format "Invalid user name %s" init-file-user)
+ :error)
+ (setq home-dir (file-name-as-directory
+ (expand-file-name (concat "~" init-file-user))))
+ (unless (file-directory-p home-dir)
+ (display-warning 'initialization
+ (format "User %s has no home directory"
+ (if (equal init-file-user "")
+ (user-real-login-name)
+ init-file-user))
+ :error))))
+
(let ((debug-on-error debug-on-error-initial)
- ;; This function actually reads the init files.
- (inner
- (function
- (lambda ()
- (if init-file-user
- (let ((user-init-file-1
- (cond
- ((eq system-type 'ms-dos)
- (concat "~" init-file-user "/_emacs"))
- ((not (eq system-type 'windows-nt))
- (concat "~" init-file-user "/.emacs"))
- ;; Else deal with the Windows situation
- ((directory-files "~" nil
"^\\.emacs\\(\\.elc?\\)?$")
- ;; Prefer .emacs on Windows.
- "~/.emacs")
- ((directory-files "~" nil "^_emacs\\(\\.elc?\\)?$")
- ;; Also support _emacs for compatibility, but
warn about it.
- (push '(initialization
- "`_emacs' init file is deprecated, please
use `.emacs'")
- delayed-warnings-list)
- "~/_emacs")
- (t ;; But default to .emacs if _emacs does not
exist.
- "~/.emacs"))))
- ;; This tells `load' to store the file name found
- ;; into user-init-file.
- (setq user-init-file t)
- (load user-init-file-1 t t)
-
- (when (eq user-init-file t)
- ;; If we did not find ~/.emacs, try
- ;; ~/.emacs.d/init.el.
- (let ((otherfile
- (expand-file-name
- "init"
- (file-name-as-directory
- (concat "~" init-file-user "/.emacs.d")))))
- (load otherfile t t)
-
- ;; If we did not find the user's init file,
- ;; set user-init-file conclusively.
- ;; Don't let it be set from default.el.
- (when (eq user-init-file t)
- (setq user-init-file user-init-file-1))))
-
- ;; If we loaded a compiled file, set
- ;; `user-init-file' to the source version if that
- ;; exists.
- (when (and user-init-file
- (equal (file-name-extension user-init-file)
- "elc"))
- (let* ((source (file-name-sans-extension
user-init-file))
- (alt (concat source ".el")))
- (setq source (cond ((file-exists-p alt) alt)
- ((file-exists-p source) source)
- (t nil)))
- (when source
- (when (file-newer-than-file-p source user-init-file)
- (message "Warning: %s is newer than %s"
- source user-init-file)
- (sit-for 1))
- (setq user-init-file source))))
-
- (unless inhibit-default-init
- (let ((inhibit-startup-screen nil))
- ;; Users are supposed to be told their rights.
- ;; (Plus how to get help and how to undo.)
- ;; Don't you dare turn this off for anyone
- ;; except yourself.
- (load "default" t t)))))))))
+ ;; This function actually reads the init files.
+ (inner
+ (function
+ (lambda ()
+ (when home-dir
+ ;; This tells `load' to store the file name found
+ ;; into user-init-file.
+ (setq user-init-file t)
+ ;; On MS-DOS, try ~USER/_emacs. On MS-Windows try
+ ;; ~USER/.emacs, ~USER/_emacs and ~/emacs.d/init. On all
+ ;; other systems, try ~USER/.emacs and ~/emacs.d/init.
+ (if (or (and (not (eq system-type 'ms-dos))
+ (load (concat home-dir ".emacs") t t))
+ (and (memq system-type '(ms-dos windows-nt))
+ (load (concat home-dir "_emacs") t t))
+ (and (not (eq system-type 'ms-dos))
+ (load (concat home-dir ".emacs.d/init") t t)))
+ ;; If we loaded a compiled file, set `user-init-file' to
+ ;; the source version if that exists.
+ (when (equal (file-name-extension user-init-file) "elc")
+ (let* ((src (file-name-sans-extension user-init-file))
+ (alt (concat src ".el")))
+ (setq src (cond ((file-exists-p alt) alt)
+ ((file-exists-p src) src)
+ (t nil)))
+ (when source
+ (when (file-newer-than-file-p src user-init-file)
+ (message "Warning: %s is newer than %s"
+ src user-init-file)
+ (sit-for 1))
+ (setq user-init-file src))))
+ ;; If we failed to load the init file, set `user-init-file'
+ ;; to the default location for it. On MS-DOS that’s
+ ;; ~USER/_emacs and on all other systems it’s ~USER/.emacs
+ (setq user-init-file (if (eq system-type 'ms-dos)
+ (concat home-dir "_emacs")
+ (concat home-dir ".emacs")))
+
+ (unless inhibit-default-init
+ (let ((inhibit-startup-screen nil))
+ ;; Users are supposed to be told their rights. (Plus
+ ;; how to get help and how to undo.) Don't you dare
+ ;; turn this off for anyone except yourself.
+ (load "default" t t)))))))))
+
(if init-file-debug
;; Do this without a condition-case if the user wants to debug.
(funcall inner)
--
Best regards, _ _
.o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michał “mina86” Nazarewicz (o o)
ooo +--<address@hidden>--<xmpp:address@hidden>--ooO--(_)--Ooo--
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Michal Nazarewicz, 2015/03/02
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Eli Zaretskii, 2015/03/02
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Michal Nazarewicz, 2015/03/02
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Eli Zaretskii, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"),
Michal Nazarewicz <=
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Eli Zaretskii, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Eli Zaretskii, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Pete Williamson, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Eli Zaretskii, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Pete Williamson, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Michal Nazarewicz, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Michal Nazarewicz, 2015/03/03
- Re: [PATCH] for review - Allow expansion of "~" (as opposed to "~user"), Eli Zaretskii, 2015/03/04