GNU bug report logs -
#61221
30.0.50; [PATCH] Support completion of quoted variable refs in Eshell
Previous Next
Reported by: Jim Porter <jporterbugs <at> gmail.com>
Date: Thu, 2 Feb 2023 02:29:01 UTC
Severity: normal
Tags: patch
Found in version 30.0.50
Done: Jim Porter <jporterbugs <at> gmail.com>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 61221 in the body.
You can then email your comments to 61221 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org
:
bug#61221
; Package
emacs
.
(Thu, 02 Feb 2023 02:29:01 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Jim Porter <jporterbugs <at> gmail.com>
:
New bug report received and forwarded. Copy sent to
monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org
.
(Thu, 02 Feb 2023 02:29:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
X-Debbugs-Cc: monnier <at> iro.umontreal.ca
Eshell lets you put quotes around variable names so that the parser can
tell where the name ends, sort of like ${var} in other shells:
~ $ echo $'user-login-name'-suffix
user-suffix
~ $ echo $"user-login-name"-suffix
user-suffix
However, you can't tab-complete variable names when you do this. Here's
a fix. I also fixed a couple small issues with completing directory
names where it would sometimes complete to "whatever/ ". That extra
trailing space isn't helpful, since you'd have to delete it before
typing in a subdir.
Probably the most controversial part of this patch is in #0002, where I
added another dynamic variable 'pcomplete-exit-function' that Pcomplete
handlers can set to tell Pcomplete what to do after exiting a
completion. Maybe it would be better to have handlers throw some special
value for 'pcomplete-completions' that contains this info (sort of like
the value that a 'completion-at-point-function' returns). I'm not sure
what the best (and most-compatible) way to do this would be...
[0001-Throw-strings-as-the-values-for-eshell-incomplete.patch (text/plain, attachment)]
[0002-Add-support-for-completing-quoted-variables-in-Eshel.patch (text/plain, attachment)]
[0003-Don-t-add-a-space-after-the-trailing-slash-when-comp.patch (text/plain, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61221
; Package
emacs
.
(Sun, 05 Feb 2023 15:34:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 61221 <at> debbugs.gnu.org (full text, mbox):
> Probably the most controversial part of this patch is in #0002, where
> I added another dynamic variable 'pcomplete-exit-function' that Pcomplete
> handlers can set to tell Pcomplete what to do after exiting
> a completion. Maybe it would be better to have handlers throw some special
> value for 'pcomplete-completions' that contains this info (sort of like the
> value that a 'completion-at-point-function' returns). I'm not sure what the
> best (and most-compatible) way to do this would be...
BTW, a low-tech way to get similar results is to change your completion
table. Instead of having entries like
user-login-name
make it contains entries like:
user-login-name"
or
user-login-name'
or even
'user-login-name'
[ assuming you change the `pcomplete-stub` so that it also contains the
leading ' of course. ]
Regarding `pcomplete-exit-function`:
- It's ugly and I don't like it, but given the general design of the
current Pcomplete API, I think it's OK.
- Please add a good docstring to that variable (the fact that the other
vars nearby don't have any is no excuse, instead it's a(nother)
problem that should be fixed).
- Maybe `pcomplete-exit-function` should override the default exit
function (i.e. the handing of `pcomplete-termination-string`) rather
than being added to it?
E.g. we could start with `pcomplete-exit-function` bound to the
default (the one that handles `pcomplete-termination-string`) and let
the rest of the code modify it either with `setq` (to completely
override) or `add-function`.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61221
; Package
emacs
.
(Thu, 23 Feb 2023 06:43:01 GMT)
Full text and
rfc822 format available.
Message #11 received at 61221 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 2/5/2023 7:33 AM, Stefan Monnier via Bug reports for GNU Emacs, the
Swiss army knife of text editors wrote:
> BTW, a low-tech way to get similar results is to change your completion
> table. Instead of having entries like
>
> user-login-name
>
> make it contains entries like:
>
> user-login-name" ...
I'd thought about this, but it gets a little uglier for more-complex
cases like bug#53371, which wants to complete things like the "foo" in
"#<buffer foo>".
> Regarding `pcomplete-exit-function`:
> - It's ugly and I don't like it, but given the general design of the
> current Pcomplete API, I think it's OK.
Yeah, I'd rather do it by returning some structured object, but that
would probably require some significant incompatible changes to pcomplete...
> - Please add a good docstring to that variable (the fact that the other
> vars nearby don't have any is no excuse, instead it's a(nother)
> problem that should be fixed).
Done.
> - Maybe `pcomplete-exit-function` should override the default exit
> function (i.e. the handing of `pcomplete-termination-string`) rather
> than being added to it?
> E.g. we could start with `pcomplete-exit-function` bound to the
> default (the one that handles `pcomplete-termination-string`) and let
> the rest of the code modify it either with `setq` (to completely
> override) or `add-function`.
I like this a lot better than my previous solution. Done.
I also changed the last patch to return a programmed completion function
that mimics "~user" completion in 'completion-file-name-table'. That
seems like a more-consistent way to handle that case, since now Eshell
"~user" completion works the same as completing any file name.
[0001-Throw-strings-as-the-values-for-eshell-incomplete.patch (text/plain, attachment)]
[0002-Add-support-for-completing-quoted-variables-in-Eshel.patch (text/plain, attachment)]
[0003-Don-t-add-a-space-after-the-trailing-slash-when-comp.patch (text/plain, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61221
; Package
emacs
.
(Thu, 23 Feb 2023 18:13:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 61221 <at> debbugs.gnu.org (full text, mbox):
The patches look good, feel free to push, AFAIC.
Some minor comments below.
Stefan
> diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
> index a5bfbf4254d..e8e8cfb39b4 100644
> --- a/lisp/eshell/esh-var.el
> +++ b/lisp/eshell/esh-var.el
> @@ -434,9 +434,15 @@ eshell-insert-envvar
>
> (defun eshell-envvar-names (&optional environment)
> "Return a list of currently visible environment variable names."
> - (mapcar (lambda (x)
> - (substring x 0 (string-search "=" x)))
> - (or environment process-environment)))
> + (delete-dups
> + (append
> + ;; Real environment variables
> + (mapcar (lambda (x)
> + (substring x 0 (string-search "=" x)))
> + (or environment process-environment))
> + ;; Eshell variable aliases
> + (mapcar (lambda (x) (car x))
Aka (mapcar #'car
> @@ -817,36 +823,43 @@ eshell-index-value
>
> (defun eshell-complete-variable-reference ()
> "If there is a variable reference, complete it."
> - (let ((arg (pcomplete-actual-arg)))
> + (let ((arg (pcomplete-actual-arg))
> + delimiter)
> (when (string-match
> (rx "$" (? (or "#" "@"))
> - (? (group (regexp eshell-variable-name-regexp)))
> - string-end)
> + (? (or (group-n 1 (regexp eshell-variable-name-regexp)
> + string-end)
> + (seq (group-n 2 (or "'" "\""))
> + (group-n 1 (+ anychar))))))
> arg)
> - (setq pcomplete-stub (substring arg (match-beginning 1)))
> + (setq pcomplete-stub (substring arg (match-beginning 1))
> + delimiter (match-string 2 arg))
You could let-bind `delimiter` here instead of let-binding it earlier
and then `setq`ing it here. Better for karma and marginally more
efficient (avoids the creation of a `cons` cell to contain the value of
the var).
> + (append (eshell-envvar-names)
> + (all-completions argname obarray 'boundp))
> + #'string-lessp)))
Since you use #' for `string-lessp`, it would make sense to use #' for
`boundp` as well :-)
> + ('lambda ; test-completion
> + (let ((result (test-completion string names pred)))
> + (if (eq result t) string result)))
Hmm... why not just always return `result`?
Stefan
Reply sent
to
Jim Porter <jporterbugs <at> gmail.com>
:
You have taken responsibility.
(Thu, 23 Feb 2023 22:13:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Jim Porter <jporterbugs <at> gmail.com>
:
bug acknowledged by developer.
(Thu, 23 Feb 2023 22:13:02 GMT)
Full text and
rfc822 format available.
Message #19 received at 61221-done <at> debbugs.gnu.org (full text, mbox):
On 2/23/2023 10:02 AM, Stefan Monnier via Bug reports for GNU Emacs, the
Swiss army knife of text editors wrote:
> The patches look good, feel free to push, AFAIC.
Thanks, merged as 9d48c9844b.
>> + (mapcar (lambda (x) (car x))
>
> Aka (mapcar #'car
Fixed.
>> + (setq pcomplete-stub (substring arg (match-beginning 1))
>> + delimiter (match-string 2 arg))
>
> You could let-bind `delimiter` here instead of let-binding it earlier
> and then `setq`ing it here. Better for karma and marginally more
> efficient (avoids the creation of a `cons` cell to contain the value of
> the var).
Done.
>> + (append (eshell-envvar-names)
>> + (all-completions argname obarray 'boundp))
>> + #'string-lessp)))
>
> Since you use #' for `string-lessp`, it would make sense to use #' for
> `boundp` as well :-)
Fixed.
>> + ('lambda ; test-completion
>> + (let ((result (test-completion string names pred)))
>> + (if (eq result t) string result)))
>
> Hmm... why not just always return `result`?
As I understand it, returning 't' means "there is just one matching
completion, and the match is exact"[1], but in this case, that's not
really true: after completing "~user/" there are still more matching
completions (the contents of the user's home directory).
This is really just trying to match what happens when calling
'completion-file-name-table':
(completion-file-name-table "~user/" nil nil)
=> "~user/"
(try-completion "~user/" '("~user/") nil)
=> t
So if we get 't' from 'try-completion', we "downgrade" that to the
original string.
[1]
https://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Completion.html
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61221
; Package
emacs
.
(Thu, 23 Feb 2023 22:40:02 GMT)
Full text and
rfc822 format available.
Message #22 received at 61221-done <at> debbugs.gnu.org (full text, mbox):
>>> + ('lambda ; test-completion
>>> + (let ((result (test-completion string names pred)))
>>> + (if (eq result t) string result)))
>> Hmm... why not just always return `result`?
>
> As I understand it, returning 't' means "there is just one matching
> completion, and the match is exact"[1], but in this case, that's not really
> true: after completing "~user/" there are still more matching completions
> (the contents of the user's home directory).
What you describe is for `try-completion`, not `test-completion`.
> This is really just trying to match what happens when calling
> 'completion-file-name-table':
>
> (completion-file-name-table "~user/" nil nil)
> => "~user/"
>
> (try-completion "~user/" '("~user/") nil)
> => t
The `action` arg is not `lambda` is these examples.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61221
; Package
emacs
.
(Thu, 23 Feb 2023 23:18:02 GMT)
Full text and
rfc822 format available.
Message #25 received at 61221-done <at> debbugs.gnu.org (full text, mbox):
On 2/23/2023 2:39 PM, Stefan Monnier via Bug reports for GNU Emacs, the
Swiss army knife of text editors wrote:
>> As I understand it, returning 't' means "there is just one matching
>> completion, and the match is exact"[1], but in this case, that's not really
>> true: after completing "~user/" there are still more matching completions
>> (the contents of the user's home directory).
>
> What you describe is for `try-completion`, not `test-completion`.
>
>> This is really just trying to match what happens when calling
>> 'completion-file-name-table':
>>
>> (completion-file-name-table "~user/" nil nil)
>> => "~user/"
>>
>> (try-completion "~user/" '("~user/") nil)
>> => t
>
> The `action` arg is not `lambda` is these examples.
Ohhh. I totally missed that part. Pushed a fix as 0a361fd91a. Thanks
again for finding my mistakes.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Fri, 24 Mar 2023 11:24:07 GMT)
Full text and
rfc822 format available.
This bug report was last modified 2 years and 50 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.