unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#47215: 28.0.50; Let M-x switch between M-x and M-X
@ 2021-03-17 17:56 Felician Nemeth
  2021-03-18  5:08 ` Lars Ingebrigtsen
  0 siblings, 1 reply; 7+ messages in thread
From: Felician Nemeth @ 2021-03-17 17:56 UTC (permalink / raw)
  To: 47215


I wish there was a convenient way to switch back and forth between
execute-extended-command and execute-extended-command-for-buffer.  I
think M-x would be an ideal binding for this as it is easy to press and
more useful than the current "Command attempted to use minibuffer while
in minibuffer".

I'd imagine this feature being somewhat analogous to how ido-find-file
falls back to find-file after C-f.

Thank you.





^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#47215: 28.0.50; Let M-x switch between M-x and M-X
  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
  0 siblings, 1 reply; 7+ messages in thread
From: Lars Ingebrigtsen @ 2021-03-18  5:08 UTC (permalink / raw)
  To: Felician Nemeth; +Cc: 47215

Felician Nemeth <felician.nemeth@gmail.com> writes:

> I wish there was a convenient way to switch back and forth between
> execute-extended-command and execute-extended-command-for-buffer.  I
> think M-x would be an ideal binding for this as it is easy to press and
> more useful than the current "Command attempted to use minibuffer while
> in minibuffer".
>
> I'd imagine this feature being somewhat analogous to how ido-find-file
> falls back to find-file after C-f.

Yes, being able to move from `execute-extended-command-for-buffer' to
`execute-extended-command' makes sense, but I'm not sure the other
direction is as useful.  And while there's only two of these commands
today, I think it's likely that (in the future) that we'll grow more of
these.

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?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#47215: 28.0.50; Let M-x switch between M-x and M-X
  2021-03-18  5:08 ` Lars Ingebrigtsen
@ 2021-04-04 17:51   ` Felician Nemeth
  2021-04-04 19:52     ` Lars Ingebrigtsen
  0 siblings, 1 reply; 7+ messages in thread
From: Felician Nemeth @ 2021-04-04 17:51 UTC (permalink / raw)
  To: 47215; +Cc: Lars Ingebrigtsen

>> I wish there was a convenient way to switch back and forth between
>> execute-extended-command and execute-extended-command-for-buffer.  I
>> think M-x would be an ideal binding for this as it is easy to press and
>> more useful than the current "Command attempted to use minibuffer while
>> in minibuffer".
>>
>> I'd imagine this feature being somewhat analogous to how ido-find-file
>> falls back to find-file after C-f.
>
> Yes, being able to move from `execute-extended-command-for-buffer' to
> `execute-extended-command' makes sense, but I'm not sure the other
> direction is as useful.  And while there's only two of these commands
> today, I think it's likely that (in the future) that we'll grow more of
> these.

I think cycling makes even more sense when there are more than two of
these execute-extended-commands.  Currently, going from
`execute-extended-command' to `execute-extended-command-for-buffer'
would be useful for me because I can type M-x M-x more easily than type
M-X.

> 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.


(defun my-exit ()
  (interactive)
  (throw 'cycle (cons 'cycle (minibuffer-contents))))

(let ((minibuffer-local-completion-map minibuffer-local-completion-map)
      ret)
  (define-key minibuffer-local-completion-map (kbd "M-x") 'my-exit)
  (setq ret (catch 'cycle
	      (execute-extended-command nil)))
  (if (eq 'cycle (car ret))
      (message "Should switch to M-X with %s" (cdr ret))
    ret))


Thanks.





^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#47215: 28.0.50; Let M-x switch between M-x and M-X
  2021-04-04 17:51   ` Felician Nemeth
@ 2021-04-04 19:52     ` Lars Ingebrigtsen
  2021-04-10 17:56       ` Felician Nemeth
  0 siblings, 1 reply; 7+ messages in thread
From: Lars Ingebrigtsen @ 2021-04-04 19:52 UTC (permalink / raw)
  To: Felician Nemeth; +Cc: 47215

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... 

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#47215: 28.0.50; Let M-x switch between M-x and M-X
  2021-04-04 19:52     ` Lars Ingebrigtsen
@ 2021-04-10 17:56       ` Felician Nemeth
  2021-04-11 17:36         ` Lars Ingebrigtsen
  0 siblings, 1 reply; 7+ messages in thread
From: Felician Nemeth @ 2021-04-10 17:56 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 47215

[-- 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)))

^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#47215: 28.0.50; Let M-x switch between M-x and M-X
  2021-04-10 17:56       ` Felician Nemeth
@ 2021-04-11 17:36         ` Lars Ingebrigtsen
  2021-04-11 18:29           ` bug#47215: [External] : " Drew Adams
  0 siblings, 1 reply; 7+ messages in thread
From: Lars Ingebrigtsen @ 2021-04-11 17:36 UTC (permalink / raw)
  To: Felician Nemeth; +Cc: 47215

Felician Nemeth <felician.nemeth@gmail.com> writes:

> 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.

Nice; your patch works very smoothly -- using `M-x' to switch here feels
very natural.

> However, the patch creates code duplication.

I think that can be fixed by refactoring out most of the interactive
spec of `execute-extended-command-for-buffer' and then reusing it.

> 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.

A lot of people have `enable-recursive-minibuffers' bound, though, which
is an argument against using `M-x' as the keystroke to switch between
modes.

> Finally, the docstring says initial-input is deprecated.

I think this use case demonstrates that perhaps we should slightly
un-deprecate initial-input -- instead of deprecating it, we could
instead just discourage the usage.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#47215: [External] : bug#47215: 28.0.50; Let M-x switch between M-x and M-X
  2021-04-11 17:36         ` Lars Ingebrigtsen
@ 2021-04-11 18:29           ` Drew Adams
  0 siblings, 0 replies; 7+ messages in thread
From: Drew Adams @ 2021-04-11 18:29 UTC (permalink / raw)
  To: Lars Ingebrigtsen, Felician Nemeth; +Cc: 47215

> > Finally, the docstring says initial-input is deprecated.
> 
> I think this use case demonstrates that perhaps we should slightly
> un-deprecate initial-input -- instead of deprecating it, we could
> instead just discourage the usage.

It never should have been deprecated - quite unwise.
Arguments against deprecation went unheeded/ignored.
___

The Icicles doc for `completing-read' has always said:

 If INITIAL-INPUT is non-nil, insert it in the minibuffer initially,
 with point positioned at the end.  If it is (STRING . POSITION), the
 initial input is STRING, but point is placed at zero-indexed position
 POSITION in STRING.  (This is different from `read-from-minibuffer'
 and related functions, which use one-indexing for POSITION.)

 INITIAL-INPUT is considered deprecated by vanilla Emacs, but not by
 Icicles.  If INITIAL-INPUT is nil and DEF is non-nil, the user can use
 `next-history-element' to yank DEF into the minibuffer.
___

As for your `M-x' changes and the addition of `M-X':
they too aren't positive, IMO, but I'll leave it to
time and others for that to be realized.  (I already
mentioned better approaches in the "Smarter M-x"
thread.)





^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-04-11 18:29 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
2021-04-11 17:36         ` Lars Ingebrigtsen
2021-04-11 18:29           ` bug#47215: [External] : " Drew Adams

unofficial mirror of bug-gnu-emacs@gnu.org 

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://yhetil.org/emacs-bugs/0 emacs-bugs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 emacs-bugs emacs-bugs/ https://yhetil.org/emacs-bugs \
		bug-gnu-emacs@gnu.org
	public-inbox-index emacs-bugs

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.yhetil.org/yhetil.emacs.bugs
	nntp://news.gmane.io/gmane.emacs.bugs


code repositories for project(s) associated with this inbox:

	https://git.savannah.gnu.org/cgit/emacs.git

AGPL code for this site: git clone http://ou63pmih66umazou.onion/public-inbox.git