From: Felician Nemeth <felician.nemeth@gmail.com>
To: Lars Ingebrigtsen <larsi@gnus.org>
Cc: 47215@debbugs.gnu.org
Subject: bug#47215: 28.0.50; Let M-x switch between M-x and M-X
Date: Sat, 10 Apr 2021 19:56:49 +0200 [thread overview]
Message-ID: <87r1ji3twe.fsf@betli.tmit.bme.hu> (raw)
In-Reply-To: <87czv9g74a.fsf@gnus.org> (Lars Ingebrigtsen's message of "Sun, 04 Apr 2021 21:52:21 +0200")
[-- Attachment #1: Type: text/plain, Size: 1842 bytes --]
Lars Ingebrigtsen <larsi@gnus.org> writes:
> Felician Nemeth <felician.nemeth@gmail.com> writes:
>
>>> I'm not quite sure how to implement this, though -- we basically end up
>>> in `completing-read', and `execute-extended-command-for-buffer' would
>>> have to define an `M-x' binding there, I guess... and then somehow call
>>> `read-extended-command' with the text already in the minibuffer.
>>>
>>> Anybody got an idea as to how to implement this without rewriting
>>> `read-extended-command' completely?
>>
>> The execute-extended-commands have two undocumented optional arguments
>> (command-name and typed). What are they used for?
>>
>> Anyway, following the fallback logic of `ido-find-file', I was able to
>> rebind `M-x' and save the content of the minibuffer with a non-standard
>> exit from `execute-extended-command'. Maybe the ugly code below can
>> give ideas to someone more knowledgeable.
>
> Thanks -- I was wondering more about the situation where you've typed
>
> M-X foo|bar
>
> (| for point)
>
> and then hit `M-x' because you want to switch to the other mode.
> Ideally, `M-x' should do that, and also preserve the text the user has
> typed, and the cursor position. I don't see an obvious simple way to do
> that...
I've discovered that the initial-input argument of `completing-read` can
be written as (STRING . POSITION). The attached patch makes use of it
and shows a simple implementation of my original wish.
However, the patch creates code duplication. Also, I don't know how it
copes with recursive editing: maybe it's not a good idea to rebind M-x
when `enable-recursive-minibuffers' is t. Finally, the docstring says
initial-input is deprecated.
I'm happy to work on the patch if you guide me to the right direction,
but this time I'd rather receive a fish instead of being taught how to
fish :)
[-- Attachment #2: m-x.patch --]
[-- Type: #("text/x-diff" 0 11 (face iswitchb-current-match)), Size: 4324 bytes --]
diff --git a/lisp/simple.el b/lisp/simple.el
index c48e644345..1bd8ba5993 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1949,7 +1949,46 @@ read-extended-command-predicate
command-completion-default-include-p)
(function :tag "Other function")))
-(defun read-extended-command ()
+(defun execute-extended-command--cycle ()
+ (interactive)
+ (throw 'cycle
+ (cons 'cycle (cons (minibuffer-contents)
+ (- (point) (minibuffer-prompt-end))))))
+
+(defun read-extended-command (&optional prompt)
+ (let ((minibuffer-local-must-match-map minibuffer-local-must-match-map)
+ (read-extended-command-predicate read-extended-command-predicate)
+ initial-input ret)
+ (define-key minibuffer-local-must-match-map
+ (kbd "M-x") #'execute-extended-command--cycle)
+ (while (not ret)
+ (setq ret (catch 'cycle
+ (read-extended-command-1 prompt initial-input)))
+ (when (and (consp ret) (eq 'cycle (car ret)))
+ ;; Cycle to the next setting. There's only two, so it's easy to do.
+ (if read-extended-command-predicate
+ (setq prompt "M-x "
+ read-extended-command-predicate nil)
+ (let ((keymaps
+ ;; The major mode's keymap and any active minor modes.
+ (cons
+ (current-local-map)
+ (mapcar
+ #'cdr
+ (seq-filter
+ (lambda (elem)
+ (symbol-value (car elem)))
+ minor-mode-map-alist)))))
+ (setq prompt "M-X ")
+ (setq read-extended-command-predicate
+ (lambda (symbol buffer)
+ (or (command-completion-using-modes-p symbol buffer)
+ (where-is-internal symbol keymaps))))))
+ (setq initial-input (cdr ret))
+ (setq ret nil)))
+ ret))
+
+(defun read-extended-command-1 (prompt initial-input)
"Read command name to invoke in `execute-extended-command'.
This function uses the `read-extended-command-predicate' user option."
(let ((buffer (current-buffer)))
@@ -1976,8 +2015,8 @@ read-extended-command
(cons def (delete def all))
all)))))
;; Read a string, completing from and restricting to the set of
- ;; all defined commands. Don't provide any initial input.
- ;; Save the command read on the extended-command history list.
+ ;; all defined commands. Save the command read on the
+ ;; extended-command history list.
(completing-read
(concat (cond
((eq current-prefix-arg '-) "- ")
@@ -1994,9 +2033,7 @@ read-extended-command
;; but actually a prompt other than "M-x" would be confusing,
;; because "M-x" is a well-known prompt to read a command
;; and it serves as a shorthand for "Extended command: ".
- (if (memq 'shift (event-modifiers last-command-event))
- "M-X "
- "M-x "))
+ (or prompt "M-x "))
(lambda (string pred action)
(if (and suggest-key-bindings (eq action 'metadata))
'(metadata
@@ -2013,7 +2050,7 @@ read-extended-command
(funcall read-extended-command-predicate sym buffer)
(error (message "read-extended-command-predicate: %s: %s"
sym (error-message-string err))))))))
- t nil 'extended-command-history))))
+ t initial-input 'extended-command-history))))
(defun command-completion-using-modes-p (symbol buffer)
"Say whether SYMBOL has been marked as a mode-specific command in BUFFER."
@@ -2241,7 +2278,7 @@ execute-extended-command-for-buffer
(or (command-completion-using-modes-p symbol buffer)
(where-is-internal symbol keymaps)))))
(list current-prefix-arg
- (read-extended-command)
+ (read-extended-command "M-X ")
execute-extended-command--last-typed)))
(with-suppressed-warnings ((interactive-only execute-extended-command))
(execute-extended-command prefixarg command-name typed)))
next prev parent reply other threads:[~2021-04-10 17:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-17 17:56 bug#47215: 28.0.50; Let M-x switch between M-x and M-X Felician Nemeth
2021-03-18 5:08 ` Lars Ingebrigtsen
2021-04-04 17:51 ` Felician Nemeth
2021-04-04 19:52 ` Lars Ingebrigtsen
2021-04-10 17:56 ` Felician Nemeth [this message]
2021-04-11 17:36 ` Lars Ingebrigtsen
2021-04-11 18:29 ` bug#47215: [External] : " Drew Adams
2022-06-24 18:18 ` Lars Ingebrigtsen
2022-06-24 18:55 ` Juri Linkov
2022-06-24 19:00 ` Lars Ingebrigtsen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87r1ji3twe.fsf@betli.tmit.bme.hu \
--to=felician.nemeth@gmail.com \
--cc=47215@debbugs.gnu.org \
--cc=larsi@gnus.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).