Commit 64059d31 authored by Jonas Bernoulli's avatar Jonas Bernoulli

magit-dwim-selection: new option

`magit-invoke-popup-action' is adjusted to set `this-command' to the
invoked command before calling instead of after doing so.  Without
this change `this-command's value would be wrong when consulting it
in `magit-completing-read' when the command was invoked form a popup.

Also deprecate the option `magit-no-confirm-default', which will be
removed in v2.13.0.

Re #2916.

squash! magit-dwim-selection: new option
parent 9c2a362c
Magit v2.12.0 Release Notes (unreleased)
========================================
Upcoming breaking changes
-------------------------
* The option `magit-no-confirm-default' has been demoted to a variable
and will be removed in v2.13.0. Please migrate your customizations
to the new option `magit-dwim-selection'. #3232
Changes since v2.11.0
---------------------
......@@ -148,6 +155,11 @@ Changes since v2.11.0
and the hunk-internal region were significantly extended. It might
be worth reading that.
* Added new option `magit-dwim-selection', which allows configuring
commands that would otherwise ask the user to select among possible
candidates to use the default instead, with or without confirmation.
#3232
Fixes since v2.11.0
-------------------
......
......@@ -7,7 +7,7 @@
#+TEXINFO_DIR_CATEGORY: Emacs
#+TEXINFO_DIR_TITLE: Magit: (magit).
#+TEXINFO_DIR_DESC: Using Git from Emacs with Magit.
#+SUBTITLE: for version 2.11.0 (2.11.0-225-g9b96aeb04+1)
#+SUBTITLE: for version 2.11.0 (2.11.0-226-g9c2a362cf+1)
#+BIND: ox-texinfo+-before-export-hook ox-texinfo+-update-version-strings
#+TEXINFO_DEFFN: t
......@@ -22,7 +22,7 @@ directly from within Emacs. While many fine Git clients exist, only
Magit and Git itself deserve to be called porcelains.
#+BEGIN_QUOTE
This manual is for Magit version 2.11.0 (2.11.0-225-g9b96aeb04+1).
This manual is for Magit version 2.11.0 (2.11.0-226-g9c2a362cf+1).
Copyright (C) 2015-2017 Jonas Bernoulli <jonas@bernoul.li>
......@@ -1323,7 +1323,9 @@ the target by moving to it.
However you might find that for some commands you always want to use
the default target, if any, or even that you want the command to act
on the default without requiring any confirmation at all.
on the default without requiring any confirmation at all. The option
~magit-dwim-selection~ can be used to configure certain commands to that
effect.
Note that when the region is active then many commands act on the
things that are selected using a mechanism based on the region, in
......@@ -1337,6 +1339,30 @@ Also note that Magit asks for confirmation of certain actions that are
not coupled with completion (or the selection). Such dialogs are also
not affected by this option and are described in the previous section.
- User Option: magit-dwim-selection
This option can be used to tell certain commands to use the thing
at point instead of asking the user to select a candidate to act
on, with or without confirmation.
The value has the form ~((COMMAND nil|PROMPT DEFAULT)...)~.
- COMMAND is the command that should not prompt for a choice.
To have an effect, the command has to use the function
~magit-completing-read~ or a utility function which in turn uses
that function.
- If the command uses ~magit-completing-read~ multiple times, then
PROMPT can be used to only affect one of these uses. PROMPT, if
non-nil, is a regular expression that is used to match against
the PROMPT argument passed to ~magit-completing-read~.
- DEFAULT specifies how to use the default. If it is ~t~, then
the DEFAULT argument passed to ~magit-completing-read~ is used
without confirmation. If it is ~ask~, then the user is given
a chance to abort. DEFAULT can also be ~nil~, in which case the
entry has no effect.
*** The Selection
If the region is active, then many Magit commands act on the things
......
......@@ -30,7 +30,7 @@ General Public License for more details.
@finalout
@titlepage
@title Magit User Manual
@subtitle for version 2.11.0 (2.11.0-225-g9b96aeb04+1)
@subtitle for version 2.11.0 (2.11.0-226-g9c2a362cf+1)
@author Jonas Bernoulli
@page
@vskip 0pt plus 1filll
......@@ -52,7 +52,7 @@ directly from within Emacs. While many fine Git clients exist, only
Magit and Git itself deserve to be called porcelains.
@quotation
This manual is for Magit version 2.11.0 (2.11.0-225-g9b96aeb04+1).
This manual is for Magit version 2.11.0 (2.11.0-226-g9c2a362cf+1).
Copyright (C) 2015-2017 Jonas Bernoulli <jonas@@bernoul.li>
......@@ -1865,7 +1865,9 @@ the target by moving to it.
However you might find that for some commands you always want to use
the default target, if any, or even that you want the command to act
on the default without requiring any confirmation at all.
on the default without requiring any confirmation at all. The option
@code{magit-dwim-selection} can be used to configure certain commands to that
effect.
Note that when the region is active then many commands act on the
things that are selected using a mechanism based on the region, in
......@@ -1879,6 +1881,38 @@ Also note that Magit asks for confirmation of certain actions that are
not coupled with completion (or the selection). Such dialogs are also
not affected by this option and are described in the previous section.
@defopt magit-dwim-selection
@end defopt
This option can be used to tell certain commands to use the thing
at point instead of asking the user to select a candidate to act
on, with or without confirmation.
The value has the form @code{((COMMAND nil|PROMPT DEFAULT)...)}.
@itemize
@item
COMMAND is the command that should not prompt for a choice.
To have an effect, the command has to use the function
@code{magit-completing-read} or a utility function which in turn uses
that function.
@item
If the command uses @code{magit-completing-read} multiple times, then
PROMPT can be used to only affect one of these uses. PROMPT, if
non-nil, is a regular expression that is used to match against
the PROMPT argument passed to @code{magit-completing-read}.
@item
DEFAULT specifies how to use the default. If it is @code{t}, then
the DEFAULT argument passed to @code{magit-completing-read} is used
without confirmation. If it is @code{ask}, then the user is given
a chance to abort. DEFAULT can also be @code{nil}, in which case the
entry has no effect.
@end itemize
@node The Selection
@subsection The Selection
......
......@@ -332,15 +332,11 @@ when using `magit-branch-and-checkout'."
(defun magit-branch-read-args (prompt)
(let ((args (magit-branch-arguments)))
(if magit-branch-read-upstream-first
(let* ((default (and (memq this-command
(with-no-warnings magit-no-confirm-default))
(magit--default-starting-point)))
(choice (or default
(magit-read-starting-point prompt))))
(let ((choice (magit-read-starting-point prompt)))
(if (magit-rev-verify choice)
(list (magit-read-string-ns
(if default
(format "%s (starting at %s)" prompt choice)
(if magit-completing-read--silent-default
(format "%s (starting at `%s')" prompt choice)
"Name for new branch")
(let ((def (mapconcat #'identity
(cdr (split-string choice "/"))
......@@ -353,7 +349,10 @@ when using `magit-branch-and-checkout'."
(list choice (magit-read-starting-point prompt choice) args)
(user-error "Not a valid starting-point: %s" choice))))
(let ((branch (magit-read-string-ns (concat prompt " named"))))
(list branch (magit-read-starting-point prompt branch) args)))))
(list branch
(with-no-warnings
(let ((magit-no-confirm-default nil))
(magit-read-starting-point prompt branch) args)))))))
;;;###autoload
(defun magit-branch-spinoff (branch &optional from &rest args)
......@@ -565,11 +564,7 @@ defaulting to the branch at point."
With prefix, forces the rename even if NEW already exists.
\n(git branch -m|-M OLD NEW)."
(interactive
(let ((branch (or (and (memq 'magit-branch-rename
(with-no-warnings magit-no-confirm-default))
(or (magit-local-branch-at-point)
(magit-get-current-branch)))
(magit-read-local-branch "Rename branch"))))
(let ((branch (magit-read-local-branch "Rename branch")))
(list branch
(magit-read-string-ns (format "Rename branch '%s' to" branch)
nil 'magit-revision-history)
......
......@@ -134,5 +134,8 @@ use `magit-pre-refresh-hook', `magit-post-refresh-hook',
(define-obsolete-function-alias 'magit-insert-unpulled-from-upstream-or-recent
'magit-insert-unpulled-from-upstream "Magit 2.12.0")
(make-obsolete-variable 'magit-no-confirm-default
'magit-dwim-selection "Magit 2.12.0")
(provide 'magit-obsolete)
;;; magit-obsolete.el ends here
......@@ -848,9 +848,8 @@ TYPE is one of `:action', `:sequence-action', `:switch', or
(magit-current-popup-action command))
(when action
(magit-popup-quit))
(setq this-command command)
(call-interactively command)
(when (eq this-command 'magit-invoke-popup-action)
(setq this-command command))
(unless action
(magit-refresh-popup-buffer))))
((eq event ?q)
......
......@@ -74,7 +74,7 @@ or `helm--completing-read-default'."
(function-item helm--completing-read-default)
(function :tag "Other function")))
(defcustom magit-no-confirm-default nil
(defvar magit-no-confirm-default nil
"A list of commands which should just use the default choice.
Many commands let the user choose the target they act on offering
......@@ -82,8 +82,7 @@ a sensible default as default choice. If you think that that
default is so sensible that it should always be used without even
offering other choices, then add that command here.
Commands have to explicitly support this option. Currently only
these commands do:
Only the following commands support this option:
`magit-branch'
`magit-branch-and-checkout'
`magit-branch-orphan'
......@@ -91,16 +90,43 @@ these commands do:
For these four commands `magit-branch-read-upstream-first'
must be non-nil, or adding them here has no effect.
`magit-branch-rename'
`magit-tag'"
:package-version '(magit . "2.9.0")
`magit-tag'")
(defcustom magit-dwim-selection nil
"When not to offer alternatives and ask for confirmation.
Many commands by default ask the user to select from a list of
possible candidates. They do so even when there is a thing at
point that they can act on, which is then offered as the default.
This option can be used to tell certain commands to use the thing
at point instead of asking the user to select a candidate to act
on, with or without confirmation.
The value has the form ((COMMAND nil|PROMPT DEFAULT)...).
- COMMAND is the command that should not prompt for a choice.
To have an effect, the command has to use the function
`magit-completing-read' or a utility function which in turn uses
that function.
- If the command uses `magit-completing-read' multiple times, then
PROMPT can be used to only affect one of these uses. PROMPT, if
non-nil, is a regular expression that is used to match against
the PROMPT argument passed to `magit-completing-read'.
- DEFAULT specifies how to use the default. If it is t, then
the DEFAULT argument passed to `magit-completing-read' is used
without confirmation. If it is `ask', then the user is given
a chance to abort. DEFAULT can also be nil, in which case the
entry has no effect."
:package-version '(magit . "2.12.0")
:group 'magit-commands
:type '(list :convert-widget custom-hook-convert-widget)
:options '(magit-branch
magit-branch-and-checkout
magit-branch-orphan
magit-branch-rename
magit-worktree-branch
magit-tag))
:type '(repeat (list command
(regexp :tag "Prompt regexp")
(choice (const "Offer other choices" nil)
(const "Require confirmation" ask)
(const "Use default without confirmation" t)))))
(defconst magit--confirm-actions
'((const reverse) (const discard)
......@@ -300,45 +326,71 @@ and delay of your graphical environment or operating system."
;;; User Input
(defvar magit-completing-read--silent-default nil)
(defun magit-completing-read
(prompt collection &optional predicate require-match initial-input hist def)
"Magit wrapper around `completing-read' or an alternative function.
"Read a choice in the minibuffer, or use the default choice.
This is the function that Magit commands use when they need the
user to select a single thing to act on. The arguments have the
same meaning as for `completing-read', except for FALLBACK, which
is unique to this function and is described below.
Instead of asking the user to choose from a list of possible
candidates, this function may instead just return the default
specified by DEF, with or without requiring user confirmation.
Whether that is the case depends on PROMPT, `this-command' and
`magit-dwim-selection'. See the documentation of the latter for
more information.
Option `magit-completing-read-function' can be used to wrap
around another `completing-read'-like function. Unless it
doesn't have the exact same signature, an additional wrapper is
required. Even if it has the same signature it might be a good
idea to wrap it, so that `magit-prompt-with-default' can be used.
If it does use the default without the user even having to
confirm that, then `magit-completing-read--silent-default' is set
to t, otherwise nil.
See `completing-read' for the meanings of the arguments, but note
that this wrapper makes the following changes:
If it does read a value in the minibuffer, then this function
acts similarly to `completing-read', except for the following:
- If REQUIRE-MATCH is nil and the user exits without a choice,
then return nil instead of an empty string.
then nil is returned instead of an empty string.
- If REQUIRE-MATCH is non-nil and the users exits without a
choice, then raise an user-error.
choice, an user-error is raised.
- \": \" is appended to PROMPT.
- If a `magit-completing-read-function' is used which in turn
uses `magit-prompt-with-completion' and DEF is non-nil, then
PROMPT is modified to end with \" (default DEF): \".
The use of another completing function and/or wrapper obviously
results in additional differences."
(let ((reply (funcall magit-completing-read-function
(concat prompt ": ")
(if (and def (not (member def collection)))
(cons def collection)
collection)
predicate
require-match initial-input hist def)))
(if (string= reply "")
(if require-match
(user-error "Nothing selected")
nil)
reply)))
- PROMPT is modified to end with \" (default DEF|FALLBACK): \"
provided that DEF or FALLBACK is non-nil, that neither
`ivy-mode' nor `helm-mode' is enabled, and that
`magit-completing-read-function' is set to its default value of
`magit-builtin-completing-read'."
(setq magit-completing-read--silent-default nil)
(-if-let (dwim (and def
(or (nth 2 (-first (pcase-lambda (`(,cmd ,re ,_))
(and (eq this-command cmd)
(or (not re)
(string-match-p re prompt))))
magit-dwim-selection))
(memq this-command
(with-no-warnings magit-no-confirm-default)))))
(if (eq dwim 'ask)
(if (y-or-n-p (format "%s %s? " prompt def))
def
(user-error "Abort"))
(setq magit-completing-read--silent-default t)
def)
(let ((reply (funcall magit-completing-read-function
(concat prompt ": ")
(if (and def (not (member def collection)))
(cons def collection)
collection)
predicate
require-match initial-input hist def)))
(if (string= reply "")
(if require-match
(user-error "Nothing selected")
nil)
reply))))
(defun magit--completion-table (collection)
(lambda (string pred action)
......
......@@ -441,10 +441,7 @@ With a prefix argument also reset the working tree.
With a prefix argument annotate the tag.
\n(git tag [--annotate] NAME REV)"
(interactive (list (magit-read-tag "Tag name")
(or (and (memq 'magit-tag magit-no-confirm-default)
(or (magit-branch-or-commit-at-point)
(magit-get-current-branch)))
(magit-read-branch-or-commit "Place tag on"))
(magit-read-branch-or-commit "Place tag on")
(let ((args (magit-tag-arguments)))
(when current-prefix-arg
(cl-pushnew "--annotate" args))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment