Giter VIP home page Giter VIP logo

transient's Introduction

A Git Porcelain inside Emacs

homepage | manual | faq | wiki | mastodon


Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.


Keeping its users this excited is a lot of work . If Magit makes you
more productive too, then please consider making a donation.
Thank you! — Jonas Bernoulli

Sponsor my work using Github Sponsors    Sponsor my work using Liberapay
Sponsor my work using Opencollective    Sponsor my work using PayPal

Some alternative donation methods are available.

Getting Started

If you are new to Magit, then either one of the following two articles should help understanding how it differs from other Git clients.

If you are completely new to Magit, then this article is a good visual introduction.

Almost everything that you see in Magit can be acted on by pressing some key, but that's not obvious from just seeing how Magit looks. The screenshots and accompanying text of this article explain how to perform a variety of actions on Magit's output.

Magit differs significantly from other Git interfaces, and its advantages are not immediately obvious simply from looking at a few screenshots as presented in the preceding article.

This article discusses Magit's properties in somewhat more abstract terms.

Video introductions

If you prefer video introductions, head over to that page, where find a collection of such introductions and other videos about Magit, by various creators.


Support and Contributing

Magit has many users and very few maintainers, so we kindly ask to read the appropriate guidelines before getting in contact. — Thanks!

TL;DR We now use discussions for feature requests (not issues) and prefer if you ask the community for support instead of the overworked maintainers.

Please also consider to contribute by supporting other users or by making a monetary donation. — Thanks!


Acknowledgments

Magit was started by Marius Vollmer, and is now maintained by Jonas Bernoulli and Kyle Meyer. Former maintainers are Nicolas Dudebout, Noam Postavsky, Peter J. Weisberg, Phil Jackson, Rémi Vanicat and Yann Hodique. Many more people have contributed code, suggested features or made monetary contributions.

Thanks to all of you, may (the history of) the source be with you!


Compile Test Manual NonGNU ELPA Melpa Melpa Stable

transient's People

Contributors

alezost avatar basil-conto avatar borkitall avatar cireu avatar clemera avatar conao3 avatar damiencassou avatar guiltydolphin avatar hokomo avatar jdtsmith avatar juergenhoetzel avatar kivikakk avatar kyleam avatar larsmagne avatar mattiase avatar monnier avatar psionic-k avatar schalkwijk avatar stepnem avatar stevemolitor avatar tarsius avatar thblt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

transient's Issues

Emacs 27 tabs

Emacs has new builtin tab feature which appear in transient buffer and make it not display fully:

image

I think that transient should set tab-line-format to nil for Emacs 27+

setting levels from elisp code

hi,

first of all, thanks for working on this fancy library!

that said, i'm wondering what the right way to set custom levels for some transient commands from elisp code, in particular from my init.el file.

i see there's a transient-levels variable which looks like this:

((magit-log
  (transient:magit-log:--first-parent . 1)
  (transient:magit-log:--no-merges . 1)))

but i'm not sure how to modify it.

i see transient uses an additional config file that is used when levels are changed interactively, but i very much prefer to keep all my configuration in one place instead.

i tried to find this in the manual and even in the source code, but couldn't find the answer, hence this issue.

thanks in advance!

Popup gets stuck after setting branch upstream

Steps to reproduce:

  • Open the branch popup
  • Press u to set the upstream branch
  • Select the branch in the prompt
  • The branch popup stops responding to C-g after the upstream branch is set

Expected behaviour:

Branch popup should close

In fact, Emacs stops responding to all keys except ? which displays the help text. I get the Unbound suffix messages for all the other keys.

Arrow keys don't work to navigate magit popup

I'm having trouble since recently updating magit - I can no longer use arrow keys to navigate inside magit's popups. When I do, I get errors like Unbound suffix: ‘<down>’ (Use ‘C-g’ to abort, ‘?’ for help). I've tried magit-emacs-Q-command and even then it doesn't work. Any tips on how to reenable arrow key navigation?

The q-command has the versions of my dependencies:

/usr/local/Cellar/emacs-plus/26.1/Emacs.app/Contents/MacOS/Emacs -Q --eval \(setq\ debug-on-error\ t\) -L $HOME/.emacs.d/elpa/dash-20190413.1058/ -L $HOME/elpa/transient-20190419.2124/ -L $HOME/.emacs.d/elpa/with-editor-20190224.931/ -L $HOME/.emacs.d/elpa/magit-20190420.1907/ -L $HOME/.emacs.d/elpa/git-commit-20190413.1201/ -l $HOME/.emacs.d/elpa/magit-20190420.1907/magit`

empty-string spacer in magit-merge transient definition breaks modifying the transient after the fact

Please explain
(1) what behavior you expected

I would expect to be able to add stuff to the magit-merge menu with transient-append-suffix.

(2) what behavior you observed

I upgraded my packages and started getting a backtrace.

(3) and how we can reproduce the issue.

Any call to transient-append-suffix; in my case, this one:

       (transient-append-suffix
         'magit-merge "a"
         '("u"
           "Catch Up To Upstream"
           glyph-setup-merge-catch-up-to-upstream))

The backtrace looks like this:

Debugger entered--Lisp error: (wrong-type-argument listp "")
  #f(compiled-function (suffix) #<bytecode 0x4476d0dd>)("")
  cl-member(nil ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into))) :if #f(compiled-function (suffix) #<bytecode 0x4476d0dd>))
  apply(cl-member nil ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into))) :if #f(compiled-function (suffix) #<bytecode 0x4476d0dd>) nil)
  cl-member-if(#f(compiled-function (suffix) #<bytecode 0x4476d0dd>) ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into))))
  transient--group-member("u" [1 transient-column nil ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into)))])
  transient--layout-member-1("u" [1 transient-column nil ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into)))] remove)
  transient--layout-member-1("u" [1 transient-columns (:description "Actions" :if-not magit-merge-in-progress-p) ([1 transient-column nil ((1 transient-suffix (:key "m" :description "Merge" :command magit-merge-plain)) (1 transient-suffix (:key "e" :description "Merge and edit message" :command magit-merge-editmsg)) (1 transient-suffix (:key "n" :description "Merge but don't commit" :command magit-merge-nocommit)) (1 transient-suffix (:key "a" :description "Absorb" :command magit-merge-absorb)))] [1 transient-column nil ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into)))])] remove)
  transient--layout-member-1("u" ([1 transient-column (:description "Arguments" :if-not magit-merge-in-progress-p) ((1 transient-switch (:key "-f" :description "Fast-forward only" :argument "--ff-only" :command transient:magit-merge:--ff-only)) (1 transient-switch (:key "-n" :description "No fast-forward" :argument "--no-ff" :command transient:magit-merge:--no-ff)) (1 transient-suffix (:command magit-merge:--strategy)) (5 transient-suffix (:command magit:--gpg-sign)))] [1 transient-columns (:description "Actions" :if-not magit-merge-in-progress-p) ([1 transient-column nil ((1 transient-suffix (:key "m" :description "Merge" :command magit-merge-plain)) (1 transient-suffix (:key "e" :description "Merge and edit message" :command magit-merge-editmsg)) (1 transient-suffix (:key "n" :description "Merge but don't commit" :command magit-merge-nocommit)) (1 transient-suffix (:key "a" :description "Absorb" :command magit-merge-absorb)))] [1 transient-column nil ((1 transient-suffix (:key "p" :description "Preview merge" :command magit-merge-preview)) "" (1 transient-suffix (:key "s" :description "Squash merge" :command magit-merge-squash)) (1 transient-suffix (:key "i" :description "Merge into" :command magit-merge-into)))])] [1 transient-column (:description "Actions" :if magit-merge-in-progress-p) ((1 transient-suffix (:key "m" :description "Commit merge" :command magit-commit-create)) (1 transient-suffix (:key "a" :description "Abort merge" :command magit-merge-abort)))]) remove)
  transient--layout-member("u" magit-merge remove)
  transient-remove-suffix(magit-merge "u")
  transient--insert-suffix(magit-merge "a" ("u" "Catch Up To Upstream" glyph-setup-merge-catch-up-to-upstream) append)
  transient-append-suffix(magit-merge "a" ("u" "Catch Up To Upstream" glyph-setup-merge-catch-up-to-upstream))
  eval((transient-append-suffix (quote magit-merge) "a" (quote ("u" "Catch Up To Upstream" glyph-setup-merge-catch-up-to-upstream))) nil)
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)

Also post the output of:

M-x magit-version RET
Magit 20190525.1118, Git 2.21.0, Emacs 26.2, darwin

Also, since it's likely to be implicated, transient version 20190524.907.

The culprit appears to be the middle of these lines in define-transient-command magit-merge

   [("p" "Preview merge"          magit-merge-preview)
    ""
    ("s" "Squash merge"           magit-merge-squash)

Possibly the bug is in transient not maintaining its own internal data structures correctly.

Conflict between Magit transient commands and popwin

Thank you for Magit!!!

I used it for several years without any problem. I have not used it for the past 3 months and cannot get it to work anymore. I suspect the problem is the change from magit-popup to transient commands and it may have to do with the fact that I use EXWM.


My problem: when I try to commit (pressing c), what used to be a popup window now is a window without command line. Pressing c again gets me to the magit commit message buffer as it should, but with the error message:

Error in pre-command-hook (transient--pre-command): (error "Attempt to delete minibuffer or sole ordinary window")

In the magit commit message buffer, some letters work fine, but others (for instance e) call functions instead of typing text.

From there on, everything is total havoc which is why I am not providing a debug log or other information: cancelling the commit and killing all the magit buffers does not restore things and keys don't work or do unexpected actions in any Emacs buffer, making it really hard to collect information about what has gone wrong. Everything in Emacs at that point is pretty much dysfunctional and the only way out I have found is to restart Emacs.

I use EXWM and I wonder whether there could be something going on there (some window issue during the transient mode which breaks the normal functioning of Magit).

I would appreciate any help or advice on this. Providing more information might be difficult as I explained, but I will try to answer questions as best I can.

Thank you!!!


System info:

Magit: magit-20190325.1516 (latest from Melpa)
Magit-popup: magit-popup-20190223.2234 (latest from Melpa)
All dependencies: latest from Melpa
Emacs: 26.1-3
OS: 5.0.4-arch1-1-ARCH

popup navigation in no window mode

Hi,

When launching emacs in emacs -nw with the popup navigation option introduced in #42, I cannot navigate with key arrows. In normal mode (with a window) it's working as expected.

Am I the only one to face the issue ?

Feature request: Support Edebug

[I'm submitting this feature request further to the discussion in magit/magit#3761.]

Transients started during an Edebug session (e.g. when stepping through a define-transient-command) currently override all Edebug key bindings, making it nearly impossible to either continue edebugging or to quit either Edebug or Transient.

The only way I can currently recover from such a scenario is via M-:(error "")RET.

It would be nice if Transient were less intrusive and supported Edebug, given the feature's importance.

Thanks!

Empty transient

I recently had the problem that my magit log transient was completely empty. The reason was that I had set the transient level to 0 while playing with transient for the first time.

Now, after a week or two of working with another computer, I completely forgot and wondered why the logarithmic transient seemed dysfunctional.

With ? doesn't help, because I don't have a man under Windows (even the first `` doesn't seem to do anything).

I couldn't remember the level set command either.

So it would probably be a good idea to have it:

  • and an indication that the level is 0 and how to change the level if there is nothing in the transient.
  • Do you have a quick help (or is it supposed to show something?)?

Transient commands change define-key's contract

Hi. I have advised function define-key and would expect key argument to follow documentation which says:

KEY is a string or a vector of symbols and characters, representing a
sequence of keystrokes and events. Non-ASCII characters with codes
above 127 (such as ISO Latin-1) can be represented by vectors.
Two types of vector have special meanings:
[remap COMMAND] remaps any key binding for COMMAND.
[t] creates a default definition, which applies to any event with no
other definition in KEYMAP.

Opening any popup broke my advice since key gets value of:
[(lambda nil (interactive) (let ((obj (transient-suffix-object))) (transient-infix-set obj (transient-infix-read obj))) (transient--show))] which isn't a sequence of keystrokes or events. I currently work around this by adding a (functionp (aref key 0)) check.

I can live with this, but am reporting it since it may affect others.

Magit 20190326.2143, Git 2.21.0, Emacs 27.0.50, gnu/linux

Ugly entries in command history

Hello,

since some time, I've entries in my 'command-history' that look like

(magit-format-patch:--output-directory #s(#22=#s(eieio--class
transient-option #23="Class used for command-line argument that can
take a value." (#20=#s(eieio--class transient-argument #21="Abstract
superclass for infix arguments." (#17=#s(eieio--class transient-infix
#19="Transient infix command." (#14=#s(eieio--class transient-suffix
#16="Superclass for suffix command." (#2=#s(eieio--class
transient-child #3="Abstract superclass for group and and suffix
classes.

It is undefined what happens if more than one `if*' predicate slot is
non-nil." nil [#s(cl-slot-descriptor level 1 t ((:documentation
. #4="Enable if level of prefix is equal or greater.")))
#s(cl-slot-descriptor if nil t ((:documentation . #5="Enable if
predicate returns non-nil."))) #s(cl-slot-descriptor if-not nil t
((:documentation . #6="Enable if predicate returns nil.")))
#s(cl-slot-descriptor if-non-nil nil t ((:documentation . #7="Enable
if variable's value is non-nil."))) #s(cl-slot-descriptor if-nil nil t
((:documentation . #8="Enable if variable's value is nil.")))
#s(cl-slot-descriptor if-mode nil t ((:documentation . #9="Enable if
major-mode matches value."))) #s(cl-slot-descriptor if-not-mode nil t
((:documentation . #10="Enable if major-mode does not match value.")))
#s(cl-slot-descriptor if-derived nil t ((:documentation . #11="Enable
if major-mode derives from value."))) #s(cl-slot-descriptor
if-not-derived nil t ((:documentation . #12="Enable if major-mode does
not derive from value.")))] #s(hash-table size 65 test eq rehash-size
1.5 rehash-threshold 0.8125 data (level 0 if 1 if-not 2 if-non-nil 3
if-nil 4 if-mode 5 if-not-mode 6 if-derived 7 if-not-derived 8))
(transient-group transient-suffix) ((:level . level) (:if . if)
(:if-not . if-not) (:if-non-nil . if-non-nil) (:if-nil . if-nil)
(:if-mode . if-mode) (:if-not-mode . if-not-mode) (:if-derived
. if-derived) (:if-not-derived . if-not-derived)) #1=[] #1# #s(#2# 1
nil nil nil nil nil nil nil nil) (:custom-groups nil :documentation
#3# :abstract t))) [#s(cl-slot-descriptor level 1 t ((:documentation
. #4#))) #s(cl-slot-descriptor if nil t ((:documentation . #5#)))
#s(cl-slot-descriptor if-not nil t ((:documentation . #6#)))
#s(cl-slot-descriptor if-non-nil nil t ((:documentation . #7#)))
#s(cl-slot-descriptor if-nil nil t ((:documentation . #8#)))
#s(cl-slot-descriptor if-mode nil t ((:documentation . #9#)))
#s(cl-slot-descriptor if-not-mode nil t ((:documentation . #10#)))
#s(cl-slot-descriptor if-derived nil t ((:documentation . #11#)))
#s(cl-slot-descriptor if-not-derived nil t ((:documentation . #12#)))
#s(cl-slot-descriptor key #13=#:unbound t nil) #s(cl-slot-descriptor
command #13# t nil) #s(cl-slot-descriptor transient #13# t nil)
#s(cl-slot-descriptor format #15=" %k %d" t nil) #s(cl-slot-descriptor
description nil t nil)] #s(hash-table size 65 test eq rehash-size 1.5
rehash-threshold 0.8125 data (level 0 if 1 if-not 2 if-non-nil 3
if-nil 4 if-mode 5 if-not-mode 6 if-derived 7 if-not-derived 8 key 9
command 10 transient 11 format 12 description 13))
(magit--git-submodule-suffix transient-infix) ((:level . level) (:if
. if) (:if-not . if-not) (:if-non-nil . if-non-nil) (:if-nil . if-nil)
(:if-mode . if-mode) (:if-not-mode . if-not-mode) (:if-derived
. if-derived) (:if-not-derived . if-not-derived) (:key . key)
(:command . command) (:transient . transient) (:format . format)
(:description . description)) #1# #1# #s(#14# 1 nil nil nil nil nil
nil nil nil #13# #13# #13# #15# nil) (:custom-groups nil
:documentation #16#))) [#s(cl-slot-descriptor level 1 t
((:documentation . #4#))) #s(cl-slot-descriptor if nil t
((:documentation . #5#))) #s(cl-slot-descriptor if-not nil t
((:documentation . #6#))) #s(cl-slot-descriptor if-non-nil nil t
((:documentation . #7#))) #s(cl-slot-descriptor if-nil nil t
((:documentation . #8#))) #s(cl-slot-descriptor if-mode nil t
((:documentation . #9#))) #s(cl-slot-descriptor if-not-mode nil t
((:documentation . #10#))) #s(cl-slot-descriptor if-derived nil t
((:documentation . #11#))) #s(cl-slot-descriptor if-not-derived nil t
((:documentation . #12#))) #s(cl-slot-descriptor key #13# t nil)
#s(cl-slot-descriptor command #13# t nil) #s(cl-slot-descriptor
transient t t nil) #s(cl-slot-descriptor format #18=" %k %d (%v)" t
nil) #s(cl-slot-descriptor description nil t nil)
#s(cl-slot-descriptor argument #13# t nil) #s(cl-slot-descriptor
shortarg #13# t nil) #s(cl-slot-descriptor value nil t nil)
#s(cl-slot-descriptor multi-value nil t nil) #s(cl-slot-descriptor
allow-empty nil t nil) #s(cl-slot-descriptor history-key nil t nil)
#s(cl-slot-descriptor reader nil t nil) #s(cl-slot-descriptor prompt
nil t nil) #s(cl-slot-descriptor choices nil t nil)] #s(hash-table
size 65 test eq rehash-size 1.5 rehash-threshold 0.8125 data (level 0
if 1 if-not 2 if-non-nil 3 if-nil 4 if-mode 5 if-not-mode 6 if-derived
7 if-not-derived 8 key 9 command 10 transient 11 format 12 description
13 argument 14 shortarg 15 value 16 multi-value 17 allow-empty 18
history-key 19 reader 20 prompt 21 choices 22)) (transient-files
transient-variable transient-argument) ((:level . level) (:if . if)
(:if-not . if-not) (:if-non-nil . if-non-nil) (:if-nil . if-nil)
(:if-mode . if-mode) (:if-not-mode . if-not-mode) (:if-derived
. if-derived) (:if-not-derived . if-not-derived) (:key . key)
(:command . command) (:transient . transient) (:format . format)
(:description . description) (:argument . argument) (:shortarg
. shortarg) (:multi-value . multi-value) (:allow-empty . allow-empty)
(:history-key . history-key) (:reader . reader) (:prompt . prompt)
(:choices . choices)) #1# #1# #s(#17# 1 nil nil nil nil nil nil nil
nil #13# #13# t #18# nil #13# #13# nil nil nil nil nil nil nil)
(:custom-groups nil :documentation #19# :abstract t)))
[#s(cl-slot-descriptor level 1 t ((:documentation . #4#)))
#s(cl-slot-descriptor if nil t ((:documentation . #5#)))
#s(cl-slot-descriptor if-not nil t ((:documentation . #6#)))
#s(cl-slot-descriptor if-non-nil nil t ((:documentation . #7#)))
#s(cl-slot-descriptor if-nil nil t ((:documentation . #8#)))
#s(cl-slot-descriptor if-mode nil t ((:documentation . #9#)))
#s(cl-slot-descriptor if-not-mode nil t ((:documentation . #10#)))
#s(cl-slot-descriptor if-derived nil t ((:documentation . #11#)))
#s(cl-slot-descriptor if-not-derived nil t ((:documentation . #12#)))
#s(cl-slot-descriptor key #13# t nil) #s(cl-slot-descriptor command
#13# t nil) #s(cl-slot-descriptor transient t t nil)
#s(cl-slot-descriptor format #18# t nil) #s(cl-slot-descriptor
description nil t nil) #s(cl-slot-descriptor argument #13# t nil)
#s(cl-slot-descriptor shortarg #13# t nil) #s(cl-slot-descriptor value
nil t nil) #s(cl-slot-descriptor multi-value nil t nil)
#s(cl-slot-descriptor allow-empty nil t nil) #s(cl-slot-descriptor
history-key nil t nil) #s(cl-slot-descriptor reader nil t nil)
#s(cl-slot-descriptor prompt nil t nil) #s(cl-slot-descriptor choices
nil t nil)] #s(hash-table size 65 test eq rehash-size 1.5
rehash-threshold 0.8125 data (level 0 if 1 if-not 2 if-non-nil 3
if-nil 4 if-mode 5 if-not-mode 6 if-derived 7 if-not-derived 8 key 9
command 10 transient 11 format 12 description 13 argument 14 shortarg
15 value 16 multi-value 17 allow-empty 18 history-key 19 reader 20
prompt 21 choices 22)) (transient-switches transient-option
transient-switch) ((:level . level) (:if . if) (:if-not . if-not)
(:if-non-nil . if-non-nil) (:if-nil . if-nil) (:if-mode . if-mode)
(:if-not-mode . if-not-mode) (:if-derived . if-derived)
(:if-not-derived . if-not-derived) (:key . key) (:command . command)
(:transient . transient) (:format . format) (:description
. description) (:argument . argument) (:shortarg . shortarg)
(:multi-value . multi-value) (:allow-empty . allow-empty)
(:history-key . history-key) (:reader . reader) (:prompt . prompt)
(:choices . choices)) #1# #1# #s(#20# 1 nil nil nil nil nil nil nil
nil #13# #13# t #18# nil #13# #13# nil nil nil nil nil nil nil)
(:custom-groups nil :documentation #21# :abstract t)))
[#s(cl-slot-descriptor level 1 t ((:documentation . #4#)))
#s(cl-slot-descriptor if nil t ((:documentation . #5#)))
#s(cl-slot-descriptor if-not nil t ((:documentation . #6#)))
#s(cl-slot-descriptor if-non-nil nil t ((:documentation . #7#)))
#s(cl-slot-descriptor if-nil nil t ((:documentation . #8#)))
#s(cl-slot-descriptor if-mode nil t ((:documentation . #9#)))
#s(cl-slot-descriptor if-not-mode nil t ((:documentation . #10#)))
#s(cl-slot-descriptor if-derived nil t ((:documentation . #11#)))
#s(cl-slot-descriptor if-not-derived nil t ((:documentation . #12#)))
#s(cl-slot-descriptor key #13# t nil) #s(cl-slot-descriptor command
#13# t nil) #s(cl-slot-descriptor transient t t nil)
#s(cl-slot-descriptor format #18# t nil) #s(cl-slot-descriptor
description nil t nil) #s(cl-slot-descriptor argument #13# t nil)
#s(cl-slot-descriptor shortarg #13# t nil) #s(cl-slot-descriptor value
nil t nil) #s(cl-slot-descriptor multi-value nil t nil)
#s(cl-slot-descriptor allow-empty nil t nil) #s(cl-slot-descriptor
history-key nil t nil) #s(cl-slot-descriptor reader nil t nil)
#s(cl-slot-descriptor prompt nil t nil) #s(cl-slot-descriptor choices
nil t nil)] #s(hash-table size 65 test eq rehash-size 1.5
rehash-threshold 0.8125 data (level 0 if 1 if-not 2 if-non-nil 3
if-nil 4 if-mode 5 if-not-mode 6 if-derived 7 if-not-derived 8 key 9
command 10 transient 11 format 12 description 13 argument 14 shortarg
15 value 16 multi-value 17 allow-empty 18 history-key 19 reader 20
prompt 21 choices 22)) nil ((:level . level) (:if . if) (:if-not
. if-not) (:if-non-nil . if-non-nil) (:if-nil . if-nil) (:if-mode
. if-mode) (:if-not-mode . if-not-mode) (:if-derived . if-derived)
(:if-not-derived . if-not-derived) (:key . key) (:command . command)
(:transient . transient) (:format . format) (:description
. description) (:argument . argument) (:shortarg . shortarg)
(:multi-value . multi-value) (:allow-empty . allow-empty)
(:history-key . history-key) (:reader . reader) (:prompt . prompt)
(:choices . choices)) #1# #1# #s(#22# 1 nil nil nil nil nil nil nil
nil #13# #13# t #18# nil #13# #13# nil nil nil nil nil nil nil)
(:custom-groups nil :documentation #23#)) 1 nil nil nil nil nil nil
nil nil "C-m o " magit-format-patch:--output-directory t #18# "Output
directory" "--output-directory=" "-o" #24="/home/micha/today/" nil nil
nil transient-read-existing-directory nil nil) #24#)

Yes, that's one entry. Such an entry is not useful to repeat a command because I can't say what is doing, it's just confusing. Maybe you want to change things so that something more useful ends in the command history.

Thanks, Michael.

Can't see help command in magit: traced to -reductions-from

When I try to show the help commands in magit, I see the following error:
Symbol’s function definition is void: -reductions-from

Using ag in my ~/.emacs.d/elpa folder I see the following:

transient-20190319.1928/transient.el
2388:         (cc (-reductions-from (apply-partially #'+ 3) 0 cw)))

dash-20190320.1406/dash.el
287:(defun -reductions-from (fn init list)
300:See also: `-reductions-from', `-reductions-r', `-reduce-r'"
301:  (and list (-reductions-from fn (car list) (cdr list))))
2741:                             "-reductions-from"

In transient it is this line:

(cc (-reductions-from (apply-partially #'+ 3) 0 cw)))

Is there a missing 'require'?

Defined prefix command failes

Version 0.1.0.

Given the following test:

(require 'transient)

(defun pc1-do ()
  "Do pc1."
  (message "pc1-do"))

(define-transient-command pc1 ()
  "Transient prefix command 1."
  ["Prefix Command 1"
   ("p" "pc1-do" pc1-do)])

(pc1)

I get this as backtrace:

Debugger entered--Lisp error: (error "cl-etypecase failed: [eieio-class-tag--transient-column 1 nil nil nil nil nil nil nil nil ([eieio-class-tag--transient-suffix 1 nil nil nil nil nil nil nil nil p pc1-do unbound  %k %d pc1-do]) nil Prefix Command 1], (integer string list transient-group transient-suffix)")
  signal(error ("cl-etypecase failed: [eieio-class-tag--transient-column 1 nil nil nil nil nil nil nil nil ([eieio-class-tag--transient-suffix 1 nil nil nil nil nil nil nil nil p pc1-do unbound  %k %d pc1-do]) nil Prefix Command 1], (integer string list transient-group transient-suffix)"))
  error("cl-etypecase failed: %s, %s" [eieio-class-tag--transient-column 1 nil nil nil nil nil nil nil nil ([eieio-class-tag--transient-suffix 1 nil nil nil nil nil nil nil nil "p" pc1-do unbound " %k %d" "pc1-do"]) nil "Prefix Command 1"] (integer string list transient-group transient-suffix))
  #[257 "\211\250\203�

Emacs:

In GNU Emacs 25.3.1 (x86_64-w64-mingw32)
 of 2017-09-26 built on LAPHROAIG
Windowing system distributor 'Microsoft Corp.', version 10.0.16299

(wrong-type-argument number-or-marker-p nil)

I'm hitting an issue where typing b in a magit status buffer triggers this:

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  transient--use-level-p(nil)
  transient--init-suffix(nil nil)
  transient--init-child(nil nil)
  #f(compiled-function (c) #<bytecode 0x41d47af9>)(nil)
  mapcan(#f(compiled-function (c) #<bytecode 0x41d47af9>) ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil))
  cl-mapcan(#f(compiled-function (c) #<bytecode 0x41d47af9>) ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil))
  transient--init-group(nil [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)])
  transient--init-child(nil [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)])
  #f(compiled-function (c) #<bytecode 0x41d47a11>)([1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)])
  mapcan(#f(compiled-function (c) #<bytecode 0x41d47a11>) ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))]))
  cl-mapcan(#f(compiled-function (c) #<bytecode 0x41d47a11>) ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))]))
  transient--init-group(nil [1 transient-columns nil ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))])])
  transient--init-child(nil [1 transient-columns nil ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))])])
  #f(compiled-function (c) #<bytecode 0x442a2939>)([1 transient-columns nil ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))])])
  mapcan(#f(compiled-function (c) #<bytecode 0x442a2939>) ([1 transient-column (:description "Variables" :if (lambda nil (and magit-branch-direct-configure (oref transient--prefix scope)))) ((1 transient-suffix (:key "d" :command magit-branch\.<branch>\.description)) (1 transient-suffix (:key "u" :command magit-branch\.<branch>\.merge/remote)) (1 transient-suffix (:key "r" :command magit-branch\.<branch>\.rebase)) (1 transient-suffix (:key "p" :command magit-branch\.<branch>\.pushRemote)))] [1 transient-columns nil ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))])] [1 transient-columns (:hide (lambda nil (and (not (memq ... transient--common-command-prefixes)) (not transient-show-common-commands)))) ([1 transient-column (:description "Value commands") ((1 transient-suffix (:key "C-x s  " :description "Set" :command transient-set)) (1 transient-suffix (:key "C-x C-s" :description "Save" :command transient-save)) (1 transient-suffix (:key "M-p    " :description "Previous value" :command transient-history-prev)) (1 transient-suffix (:key "M-n    " :description "Next value" :command transient-history-next)))] [1 transient-column (:description "Sticky commands") ((1 transient-suffix (:key "C-g" :description "Quit prefix or transient" :command transient-quit-one)) (1 transient-suffix (:key "C-q" :description "Quit transient stack" :command transient-quit-all)) (1 transient-suffix (:key "C-z" :description "Suspend transient stack" :command transient-suspend)))] [1 transient-column (:description "Customize") ((1 transient-suffix (:key "C-x t" :command transient-toggle-common :description ...)) (1 transient-suffix (:key "C-x l" :description "Show/hide suffixes" :command transient-set-level)))])]))
  cl-mapcan(#f(compiled-function (c) #<bytecode 0x442a2939>) ([1 transient-column (:description "Variables" :if (lambda nil (and magit-branch-direct-configure (oref transient--prefix scope)))) ((1 transient-suffix (:key "d" :command magit-branch\.<branch>\.description)) (1 transient-suffix (:key "u" :command magit-branch\.<branch>\.merge/remote)) (1 transient-suffix (:key "r" :command magit-branch\.<branch>\.rebase)) (1 transient-suffix (:key "p" :command magit-branch\.<branch>\.pushRemote)))] [1 transient-columns nil ([1 transient-column (:description "Checkout") ((1 transient-suffix (:key "l" :description "local branch" :command magit-branch-checkout)) (1 transient-suffix (:key "c" :description "new branch" :command magit-branch-and-checkout)) (5 transient-suffix (:key "w" :description "new worktree" :command magit-worktree-checkout)) (1 transient-suffix (:key "y" :description "pull-request" :command forge-checkout-pullreq)) (6 transient-suffix (:key "o" :description "new orphan" :command magit-branch-orphan)) (1 transient-suffix (:key "b" :description "dwim" :command magit-checkout)))] [1 transient-column (:description "Create") ((1 transient-suffix (:key "s" :description "new spin-off" :command magit-branch-spinoff)) (1 transient-suffix (:key "n" :description "new branch" :command magit-branch-create)) (5 transient-suffix (:key "W" :description "new worktree" :command magit-worktree-branch)) (1 transient-suffix (:key "Y" :description "from pull-request" :command forge-branch-pullreq)) nil)] [1 transient-column (:description "Do") ((1 transient-suffix (:key "C" :description "configure..." :command magit-branch-configure)) (1 transient-suffix (:key "m" :description "rename" :command magit-branch-rename)) (1 transient-suffix (:key "X" :description "reset" :command magit-branch-reset)) (1 transient-suffix (:key "x" :description "delete" :command magit-branch-delete)))])] [1 transient-columns (:hide (lambda nil (and (not (memq ... transient--common-command-prefixes)) (not transient-show-common-commands)))) ([1 transient-column (:description "Value commands") ((1 transient-suffix (:key "C-x s  " :description "Set" :command transient-set)) (1 transient-suffix (:key "C-x C-s" :description "Save" :command transient-save)) (1 transient-suffix (:key "M-p    " :description "Previous value" :command transient-history-prev)) (1 transient-suffix (:key "M-n    " :description "Next value" :command transient-history-next)))] [1 transient-column (:description "Sticky commands") ((1 transient-suffix (:key "C-g" :description "Quit prefix or transient" :command transient-quit-one)) (1 transient-suffix (:key "C-q" :description "Quit transient stack" :command transient-quit-all)) (1 transient-suffix (:key "C-z" :description "Suspend transient stack" :command transient-suspend)))] [1 transient-column (:description "Customize") ((1 transient-suffix (:key "C-x t" :command transient-toggle-common :description ...)) (1 transient-suffix (:key "C-x l" :description "Show/hide suffixes" :command transient-set-level)))])]))
  transient--init-objects(magit-branch nil (:scope "master"))
  transient-setup(magit-branch nil nil :scope "master")
  magit-branch("master")
  funcall-interactively(magit-branch "master")
  call-interactively(magit-branch nil nil)
  command-execute(magit-branch)

I'm aware this is very little information, but I'm not sure which other information would you require. Please let me know if I can provide anything else.

Magit: melpa 20190226.428
Emacs: [email protected] (spacemacs)

Completely stuck, Emacs stops accepting *all* input and says "Unbound suffix"

I ran into a pretty nasty bug in transient-mode. I'm just getting "Unbound suffix: '' (Use 'C-g' to abort, '?' for help)" no matter what I tried.

Not sure exactly what happened or how to reproduce it, but the symptom is that all keybindings were disabled. I believe I tried bringing up magit-dispatch and then pressed C-g or C-[ at an extremely inopportune time because something was temporarily lagging. (I'm investigating slowdowns in my configuration due to some unknown package which motivates this behaviour.)

Here are some things I tried: Clicking the mouse, right clicking, mouse wheel, dragging mouse, all that in other windows, pressing C-g, q, ?, and literally any other keybinding I could dream up, clicking the mode line and that didn't work either ( is unbound). tool-bar-mode and menu-bar-mode are disabled so I can't try that.

I'll see if I can attach GDB to the process and get a Lisp level backtrace for you tomorrow. Emacs is still running, so if you have anything you want me to try, post quick and I might be able to do it before I have to kill this Emacs process.

Anyways, it would be good if there was a fire escape for situations like this. Two suggestions:

  1. Transient mode should just go away and reset itself after X seconds of inactivity (by default high, say 120 seconds or something)?
  2. C-g and/or q should always work. Maybe they should and something just broke, but here we are.

This is on version 0.1.0 from melpa-stable, not sure if this would be fixed by just upgrading. If so, please release a new version of the package. (BTW, it would be good with a new release of magit too soon, for us poor schmucks using melpa-stable.)

PS. Thanks for all your good work on Magit. It's one of the killer apps of Emacs.

Argument defaults ?

I have not found a way to set a default value for a parameter, for example say i have --num parameter when the transient opens for the first time I would like to give it that value of 10 but still allow the user to override it and have a different value in the future.

For me I want to have a default and allow it to be overridden from dir local so when opening a project on a new machine the dialog will have required param pre filled.

I have asked in a few places and I don't seem to be the only one who would like this feature.

https://www.reddit.com/r/emacs/comments/ciyqib/how_to_set_transient_infix_params_default_values/

And in the comments of this gist.
https://gist.github.com/abrochard/dd610fc4673593b7cbce7a0176d897de

Is there an existing way to do this and if not could it be added or is this considered outside of the scope of transient ?

Allow scrolling transient popup

Would it be possible to have an option to scroll the transient "popup"? Currently, when the transient is long, the emacs frame is small or if one is using a large font (none of which is a rare situation), not all of the transient is visible (see attached image — the "log" and reflog" commands are all invisible). There appears to be no option to scroll the transient, to make the bottom section visible. Even dragging the scroll-bar has no effect. This is rather inconvenient, especially since the "action" (suffix?) commands are at the bottom.

Would it be possible to add a set of keybindings to make scrolling possible?

Some possibilities might be SPC and S-SPC, C-v and M-v, next and prior (i.e. PgDown and PgUp). Of these, C-v seems to be taken, so that pair is probably not a good idea, but the others appear to be free.

In addition, allowing scrolling with the mouse (<mouse-[45]>), if at all possible, would also be useful.

Thank you, for yet another, otherwise wonderful package!

magit_transient_with_small_emacs_frame

transient-insert-suffix replaces list-suffixes

I wanted to add --start-number to `magit-patch-create' using this code

(define-infix-argument my-magit-patch-create:--start-number ()
    :description "Start number"
    :class 'transient-option
    :argument "--start-number="
    :key "C-m n  "
    :reader 'transient-read-number-N+)
(transient-append-suffix 'magit-patch-create "C-m o" '(my-magit-patch-create:--start-number))

But that actually replaces the (magit-format-patch:--output-directory) entry in magit-patch-create when I expected it to be inserted after C-m o.

Placing --start-number after C-m l works, as that is defined as

   ("C-m l  " "Add cover letter" "--cover-letter")

I think there is some problem with the key lookup in `transient--insert-suffix',

(plist-get (nth 2 suf) :key)

wont work on (magit-format-patch:--output-directory) entries, which means action will be set to 'replace.

Popups no longer closeable with 'q'

In magit-status, pressing e.g. c then q would cancel the commit popup. This seems no longer possible with the version from MELPA ("Unbound suffix: 'q'").

The popup does mention C-g, but that's a bit harder to reach. Or was this change intentional (to free up q for more actions)? I didn't see anything in the changelog.

Magit 20190217.1905, Git 2.20.1, Emacs 26.1, gnu/linux

Ability for user to save settings

In the older magit-popup mode, the user's settings (e.g. =S gpg key signing) could be saved and automatically applied to all future uses of the popup via the C-c C-c operation.

I have not been able to discover a way to do this in the new transient-based implementation. I would be happy to contribute a documentation pull request someone could indicate whether this is supported in transient, and if so, how.

Access "parent" transient arguments

Hello,

I have transients like this:

(define-transient-command docker-compose-up ()
  "Popup for \"docker-compose up\"."
  :man-page "docker-compose up"
  ["Arguments"
   ("-b" "Build" "--build")
   ("-t" "Timeout" "--timeout " read-string)]
  ["Actions"
   ("U" "Up" docker-compose--one)
   ("A" "All services" docker-compose--all)])

(define-transient-command docker-compose ()
  "Popup for docker-compose."
  :man-page "docker-compose"
  ["Arguments"
   ("-a" "No ANSI" "--no-ansi")
   ("-h" "Host" "--host " read-string)
   ("-p" "Project name" "--project-name " read-string)
   ("-v" "Verbose" "--verbose")]
  ["Docker-compose"
   ("U" "Up"         docker-compose-up)
   ("W" "Down"       docker-compose-down)])

Basically, one transient can be configured with some arguments, then it calls another transient which does something.

In the second transient, how do I access the first transient arguments? I thought (transient-args 'docker-compose) would work but it always return nil (I can only access the second transient arguments).

Does that mean I have to write some docker-compose-save-arguments-then-call-docker-compose-up function or is there another way? If yes I'll just generate those using metaprogramming, but I thought I'd ask before complicating things :-)

Also, I can't define suffix as inline-lambdas correct? (it has to be a symbol of a function to call)

Automatic uppercase-to-lowercase coercion for sloppy chording

I have a custom command that I bind to C-c L m. Sometimes I hold down the shift key too long and type C-c L M by accident. With global-set-keybinding, Emacs is forgiving: since there is no command actually bound to C-c L M it automatically coerces it to C-c L m. Do you think that transient should have the same behavior, or should I handle it some other way? (I suppose I could also try to get better at precise inputs but that may be putting too many demands on the fallible flesh.)

display-buffer-in-child-frame for transient-display-buffer-action breaks

I tried setting transient-display-buffer-action to display-buffer-in-child-frame like so:

(setq transient-display-buffer-action '(display-buffer-in-child-frame)

With that form evaluated, transient will pop up in a child frame as expected, but doesn't accept any commands. The minibuffer is very confused and the child frame doesn't close down. (WARNING: This rendered my emacs session semi-broken and I had to quit it... with knowledge of transient internals, you may be able to repair the damage).

I'm not sure that I really want transients to appear in child frames, but I would expect them to not break emacs (:

transient-save-history: wrong-type-argument listp \.\.\.

Hi,

M-x magit-version:

Magit 20190223.2219, Git 2.20.1, Emacs 27.0.50, gnu/linux

I just tried to C-x C-c my Emacs and got this error. Backtrace looks like (edited):

car(\.\.\.)
(setq transient-history [...])
transient-save-history()
(progn (transient-save-history))
(if transient-save-history (progn (transient-save-history)))
transient-maybe-save-history()
kill-emacs()

`transient-history' is bound to:

((magit-branch nil)
 (magit-commit nil)
 (magit-ediff nil)
 (magit-format-patch:--output-directory)
 (magit-log
  ("-n512" #1="--graph" #2="--decorate")
  ("-n256" #1# #2#)
  ("-n25")
  ("-n25" "--grep=autoload"
   ("--" "lisp/emacs-lisp/autoload.el"))
  ("-n256" "--date-order" "--graph" "--decorate"))
 (magit-log:--grep "autoload")
 (magit-patch nil)
 (magit-patch-create
  ("--output-directory=/home/micha/today/")
  nil)
 (magit-pull nil)
 (magit-push nil)
 \.\.\.)

I dunno why there is a ... symbol at the end, but it seems to cause the problem. Oh, I see it has been read from my transient/history.el file. Hmm, I have adviced pp-to-string, which is used in transient-save-history, to use cl-print. I'm not sure if using pp to generate lisp reader readable output is a good idea. But I'm not even sure if that's the reason why the ellipsis ended in the history file. I'll deactivate the advice and wait if I'm getting the same error again.

Michael.

wrong-type-argument number-or-marker-p nil

I'm having the following issue preventing me from using quite a few commands within Magit:

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  transient--use-level-p(nil)
  transient--init-suffix(nil nil)
  transient--init-child(nil nil)
  #f(compiled-function (c) #<bytecode 0x3dba9f5>)(nil)
  mapcan(#f(compiled-function (c) #<bytecode 0x3dba9f5>) ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil))
  cl-mapcan(#f(compiled-function (c) #<bytecode 0x3dba9f5>) ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil))
  transient--init-group(nil [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])
  transient--init-child(nil [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])
  #f(compiled-function (c) #<bytecode 0x3dba621>)([1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])
  mapcan(#f(compiled-function (c) #<bytecode 0x3dba621>) ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)]))
  cl-mapcan(#f(compiled-function (c) #<bytecode 0x3dba621>) ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)]))
  transient--init-group(nil [1 transient-columns (:description "Transient and dwim commands") ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])])
  transient--init-child(nil [1 transient-columns (:description "Transient and dwim commands") ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])])
  #f(compiled-function (c) #<bytecode 0x3dba5ed>)([1 transient-columns (:description "Transient and dwim commands") ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])])
  mapcan(#f(compiled-function (c) #<bytecode 0x3dba5ed>) ([1 transient-columns (:description "Transient and dwim commands") ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])] [1 transient-columns (:description "Applying changes" :if-derived magit-mode) ([1 transient-column nil ((1 transient-suffix (:key "a" :description "Apply" :command magit-apply)) (1 transient-suffix (:key "-" :description "Reverse" :command magit-reverse)) (1 transient-suffix (:key "x" :description "Discard" :command magit-discard)))] [1 transient-column nil ((1 transient-suffix (:key "s" :description "Stage" :command magit-stage)) (1 transient-suffix (:key "u" :description "Unstage" :command magit-unstage)))] [1 transient-column nil ((1 transient-suffix (:key "S" :description "Stage all" :command magit-stage-modified)) (1 transient-suffix (:key "U" :description "Unstage all" :command magit-unstage-all)))])] [1 transient-column (:description "Essential commands" :if-derived magit-mode) ((1 transient-suffix (:key "g" :description "       refresh current buffer" :command magit-refresh)) (1 transient-suffix (:key "<tab>" :description "   toggle section at point" :command magit-section-toggle)) (1 transient-suffix (:key "<return>" :description "visit thing at point" :command magit-visit-thing)) (1 transient-suffix (:key "C-h m" :description "   show all key bindings" :command describe-mode)))] [1 transient-columns (:hide (lambda nil (and (not (memq (car transient--redisplay-key) transient--common-command-prefixes)) (not transient-show-common-commands)))) ([1 transient-column (:description "Value commands") ((1 transient-suffix (:key "C-x s  " :description "Set" :command transient-set)) (1 transient-suffix (:key "C-x C-s" :description "Save" :command transient-save)) (1 transient-suffix (:key "M-p    " :description "Previous value" :command transient-history-prev)) (1 transient-suffix (:key "M-n    " :description "Next value" :command transient-history-next)))] [1 transient-column (:description "Sticky commands") ((1 transient-suffix (:key "C-g" :description "Quit prefix or transient" :command transient-quit-one)) (1 transient-suffix (:key "C-q" :description "Quit transient stack" :command transient-quit-all)) (1 transient-suffix (:key "C-z" :description "Suspend transient stack" :command transient-suspend)))] [1 transient-column (:description "Customize") ((1 transient-suffix (:key "C-x t" :command transient-toggle-common :description (lambda nil (if transient-show-common-commands "Hide common commands" "Show common permanently")))) (1 transient-suffix (:key "C-x l" :description "Show/hide suffixes" :command transient-set-level)))])]))
  cl-mapcan(#f(compiled-function (c) #<bytecode 0x3dba5ed>) ([1 transient-columns (:description "Transient and dwim commands") ([1 transient-column nil ((1 transient-suffix (:key "A" :description "Apply" :command magit-cherry-pick)) (1 transient-suffix (:key "b" :description "Branch" :command magit-branch)) (1 transient-suffix (:key "B" :description "Bisect" :command magit-bisect)) (1 transient-suffix (:key "c" :description "Commit" :command magit-commit)) (1 transient-suffix (:key "d" :description "Diff" :command magit-diff)) (1 transient-suffix (:key "D" :description "Diff (change)" :command magit-diff-refresh)) (1 transient-suffix (:key "e" :description "Ediff (dwim)" :command magit-ediff-dwim)) (1 transient-suffix (:key "E" :description "Ediff" :command magit-ediff)))] [1 transient-column nil ((1 transient-suffix (:key "f" :description "Fetch" :command magit-fetch)) (1 transient-suffix (:key "F" :description "Pull" :command magit-pull)) (1 transient-suffix (:key "l" :description "Log" :command magit-log)) (1 transient-suffix (:key "L" :description "Log (change)" :command magit-log-refresh)) (1 transient-suffix (:key "m" :description "Merge" :command magit-merge)) (1 transient-suffix (:key "M" :description "Remote" :command magit-remote)) (1 transient-suffix (:key "'" :description "Submodule" :command magit-submodule)) (1 transient-suffix (:key "\"" :description "Subtree" :command magit-subtree)))] [1 transient-column nil ((1 transient-suffix (:key "P" :description "Push" :command magit-push)) (1 transient-suffix (:key "r" :description "Rebase" :command magit-rebase)) (1 transient-suffix (:key "t" :description "Tag" :command magit-tag)) (1 transient-suffix (:key "T" :description "Note" :command magit-notes)) (1 transient-suffix (:key "_" :description "Revert" :command magit-revert)) (1 transient-suffix (:key "w" :description "Apply patches" :command magit-am)) (1 transient-suffix (:key "W" :description "Format patches" :command magit-patch)) (1 transient-suffix (:key "O" :description "Reset" :command magit-reset)))] [1 transient-column nil ((1 transient-suffix (:key "y" :description "Show Refs" :command magit-show-refs)) (1 transient-suffix (:key "z" :description "Stash" :command magit-stash)) (1 transient-suffix (:key "!" :description "Run" :command magit-run)) (1 transient-suffix (:key "@" :description "Forge" :command forge-dispatch)) (1 transient-suffix (:key "%" :description "Worktree" :command magit-worktree)) nil)])] [1 transient-columns (:description "Applying changes" :if-derived magit-mode) ([1 transient-column nil ((1 transient-suffix (:key "a" :description "Apply" :command magit-apply)) (1 transient-suffix (:key "-" :description "Reverse" :command magit-reverse)) (1 transient-suffix (:key "x" :description "Discard" :command magit-discard)))] [1 transient-column nil ((1 transient-suffix (:key "s" :description "Stage" :command magit-stage)) (1 transient-suffix (:key "u" :description "Unstage" :command magit-unstage)))] [1 transient-column nil ((1 transient-suffix (:key "S" :description "Stage all" :command magit-stage-modified)) (1 transient-suffix (:key "U" :description "Unstage all" :command magit-unstage-all)))])] [1 transient-column (:description "Essential commands" :if-derived magit-mode) ((1 transient-suffix (:key "g" :description "       refresh current buffer" :command magit-refresh)) (1 transient-suffix (:key "<tab>" :description "   toggle section at point" :command magit-section-toggle)) (1 transient-suffix (:key "<return>" :description "visit thing at point" :command magit-visit-thing)) (1 transient-suffix (:key "C-h m" :description "   show all key bindings" :command describe-mode)))] [1 transient-columns (:hide (lambda nil (and (not (memq (car transient--redisplay-key) transient--common-command-prefixes)) (not transient-show-common-commands)))) ([1 transient-column (:description "Value commands") ((1 transient-suffix (:key "C-x s  " :description "Set" :command transient-set)) (1 transient-suffix (:key "C-x C-s" :description "Save" :command transient-save)) (1 transient-suffix (:key "M-p    " :description "Previous value" :command transient-history-prev)) (1 transient-suffix (:key "M-n    " :description "Next value" :command transient-history-next)))] [1 transient-column (:description "Sticky commands") ((1 transient-suffix (:key "C-g" :description "Quit prefix or transient" :command transient-quit-one)) (1 transient-suffix (:key "C-q" :description "Quit transient stack" :command transient-quit-all)) (1 transient-suffix (:key "C-z" :description "Suspend transient stack" :command transient-suspend)))] [1 transient-column (:description "Customize") ((1 transient-suffix (:key "C-x t" :command transient-toggle-common :description (lambda nil (if transient-show-common-commands "Hide common commands" "Show common permanently")))) (1 transient-suffix (:key "C-x l" :description "Show/hide suffixes" :command transient-set-level)))])]))
  transient--init-objects(magit-dispatch nil nil)
  transient-setup(magit-dispatch)
  magit-dispatch()
  funcall-interactively(magit-dispatch)
  call-interactively(magit-dispatch nil nil)
  command-execute(magit-dispatch)

In this particular instance, I opened a git repository, opened magit and then tried opening the help (?). Another key which doesn't work is b for the various branch operations, though some still work (such as l for log operations).

Using Spacemacs with the following packages:

  evil-magit         20190216.1721
  forge              20190218.1841
  magit              20190217.2150
  magit-gitflow      20170929.824
  magit-popup        20181204.2031

Let me know if you need further information.

Add some examples of basic transients and generally improve the documentation

Hi! First of all, thank you very much for your work on this package and Magit in general!

I have recently started working on a package which uses transient to provide a user interface to the rust cli utility called cargo. Transient is a pleasure to work with and the manual is very detailed but I think that it could benefit from some basic examples of Transient being used(defining infix command, creating a basic transient and so on...). If you are interested in adding something such as this, I have no problem contributing some code.

Looking around, it seems like it would be perfect to put this in the wiki for this package and perhaps link to it from the manual or maybe even just adding these pieces into the manual itself. Either way, if you are open to adding some examples, then please let me know and I will create some and contribute them. I have not worked with every feature that transient provides but whatever I can offer will hopefully be helpful to somebody else.

How to add a custom infix to existing transients

For example, I want to add --first-parent switch to magit-log transient.

Document explains how to modify existing transients, but this is limited to modifying suffix.

Version Info

Emacs => GNU Emacs 26.1 (build 1, x86_64-w64-mingw32)
transient.el => 20190215.1221
magit.el => 20190215.1359

Invoking transient commands with arguments

I'd like to invoke a transient command using specific arguments, skipping its popup. Is it possible?

For instance, I'd like to run something like (magit-blame "-w") to invoke magit blame with the ignore whitespace option.

Some notes about the initial version

This is pre-alpha software, but if you concluded that it doesn't work at all yet because some commands don't do anything (they have no body), then you would be wrong. These commands don't do anything themselves, but running them while a transient command is active causes things to happen in transient--pre-command and transient--post-command.

The code is pretty tense and you will have to understand pretty much all of it to understand what is going on. I tried to arrange the code so that you can start reading at the top and if you have understood everything you have read so far, then you should also be able to understand the rest.

At this point in time transient.el is mostly an alternative to prefix arguments and cannot replace magit-popup.el yet, though that is the goal. The implementation of the core functionality that is already present is heavily inspired by how prefix arguments are implemented, in that "infix arguments" set variables whose values are later used by other commands. Like the prefix argument functionality, transient uses set-transient-map (from Emacs) but the use of that functionality is more complex here, so you might want to first fully understand how prefix arguments are implemented before you do the same for infix arguments.


Note that I will be amending to the initial commit for a while.

Cannot `transient-append-suffix` on empty section

Hello,

I cannot call transient-append-suffix on an empty section. Using (transient-append-suffix 'docker-compose '(1 -1) suffix))) only works if the section already contains a suffix.

Here is my current workaround (adding a dummy one then removing it):

(define-transient-command docker-compose ()
  "Popup for docker-compose."
  :man-page "docker-compose"
  :value docker-compose-arguments
  ["Arguments"
   ("-a" "No ANSI" "--no-ansi")
   ("-c" "Compatibility" "--compatibility")
   ("-d" "Project directory" "--project-directory " docker-compose-read-directory)
   ("-f" "Compose file" "--file " docker-compose-read-compose-file)
   ("-h" "Host" "--host " read-string)
   ("-l" "Log level" "--log-level " docker-compose-read-log-level)
   ("-p" "Project name" "--project-name " read-string)
   ("-v" "Verbose" "--verbose")]
  ["Docker-compose"
   ("X" "DELME" "-x")])

(let ((params '(("B" "Build"      docker-compose-build)
                ("C" "Create"     docker-compose-create)
                ("D" "Remove"     docker-compose-rm)
                ("E" "Exec"       docker-compose-exec)
                ("F" "Pull"       docker-compose-pull)
                ("L" "Logs"       docker-compose-logs)
                ("O" "Stop"       docker-compose-stop)
                ("P" "Push"       docker-compose-push)
                ("R" "Run"        docker-compose-run)
                ("S" "Start"      docker-compose-start)
                ("T" "Restart"    docker-compose-restart)
                ("U" "Up"         docker-compose-up)
                ("V" "Config"     docker-compose-config)
                ("W" "Down"       docker-compose-down))))
  (--each params
    (let* ((method (-last-item it))
           (name (intern (format "%s-save" method)))
           (suffix (-replace-last method name it)))
      (defalias name
        (lambda ()
          (interactive)
          (setq docker-compose-arguments (transient-args 'docker-compose))
          (funcall method)))
      (transient-append-suffix 'docker-compose '(1 -1) suffix)))
  (transient-remove-suffix 'docker-compose '(1 0)))

For now that works but I guess there should be a better way.

Adding the whole section using (1) as LOC could work but I'd require me to use -each to generate the saver methods then use -map to produce the suffixes (instead of doing it in one go like above).

EDIT: discovered I can simply call (transient-set) instead of saving the current popup value to a variable, then later get the value with... hum... why isn't there something like (transient-get-value 'docker-compose)

EDIT2: okay, I guess I need to extract the first one from transient-history

transient and dimmer integration

Hi,

I'm sure if this is bug-report or a feature request, feel free to adapt.
I'm using dimmer to dim the non active buffers.
With previous magit version (using magit popup), the popups were dimmed when they hadn't the focus and had full bright when selected.

RIght now, I'm using Magit 20190225.418, Git 2.17.1, Emacs 26.1, gnu/linux and for what I understand, with this new transient mechanism, the popup is display only.
I have not been able to give it the focus (mouse click, windmove,C-x o, everything is unknown) thus it is always dimmed and it becomes hard to read.

Dimmer has a function to prevent some buffers from being dimmed if the buffer's name matches a regex (Dimmer Exclusion Regexp), but up to now, I haven't been able to make it work as I can't find the name of the popups.

Any help is appreciated !
Thanks.

David

Make some accommodation for column alignment

Following the resolution of magit/magit-popup#14 I've successfully changed the possible faces to inherit from fixed-pitch, but this does not resolve the problem.

As long as transient assumes that a fixed pitch is used for the default face and that (as a result) it can simply use spaces to achieve a columnar layout of the commands, this problem will persist.

image

It looks like package-menu-mode (mostly) fixes this by using the following bit:

	      ;; Insert a space that aligns the button properly.
	      (propertize " " 'display (list 'space :align-to column)
			  'face 'fixed-pitch)

image

Focus on the selected option while prompting for a value

For instance, in magit-log when prompting for the value for the -- option, it might look better if every other option was faded out, and -- Limit to Files was the same colour.

Instead, only the = option was faded out, and the 2nd - in -- Limit to Files was still in the transient-key face.

Modifying layout based on group

Thanks for this package.
I am implementing a transient frontend for my package rg.el and have the following scenario.

I want to define a transient for the package supported commands but would also like to support adding custom commands to the transient from a macro that defines these custom commands.

The problem I have is that all the transient-insert-suffix like commands needs a location in form of another suffix. That works fine if you know the layout (i.e. doing manual customizations in emacs init file) but makes it hard for my scenario where I essentially just want to append or prepend a suffix to a group without caring about the suffixes already there. The solutions I have come up with are either complex and sensitive to breakage, depending on transient internals or add unwanted complexity to the API:s I want to expose.

Is this possible to achive in some way with the current API:s that I have missed?

If not, would you consider adding/accepting prs for such API:s? I can also see that adding new groups could be a useful feature, if you for instance want to keep your own modifications to a transient separately under a "Custom" sub section.

Set level for existing keys

In the editing mode (C-x l) you can set the level for keys (commands). This is very convenient. However, if I need to scroll the transient to see all the commands that exist, I'm asked to set the level for the mwheel-scroll or mouse-drag-region commands.

I think the level should only be set for existing keys (if possible).

Can't `C-h k`

After a transient popup opens, I would like to press C-h k (or similar) and then a suffix key to find out what command will be executed.

transient interacts with frame-mode in a way that completely breaks emacs

frame-mode is by no means a widely used package, but it is does something that I imagine many users might do without a package, which is basically to set custom values for display-buffer-alist to almost completely disable windows in favor of frames.

As you can see here:

https://github.com/IvanMalison/frame-mode/blob/4551bf43bc087448ce0edcd67c36f68649e95274/frame-mode.el#L153
https://github.com/IvanMalison/frame-mode/blob/4551bf43bc087448ce0edcd67c36f68649e95274/frame-mode.el#L165

All that frame-does is set some rules to make it so that the default of popping up new windows is avoided in all but a few special cases.

This seems to cause the transient window to pop up in a new frame and also seems to make its keymap indefinitely active, making it basically impossible to regain control of emacs, since it is not possible to use something like C-g or M-x in this state as far as I can tell.

I'm not super intimately familiar with how display-buffer should be behaving when it is passed an action as it is from transient here:

(display-buffer buf transient-display-buffer-action)))

I'm going to take some time to look in to this, but its pretty scary that this is causing complete emacs breakage.

<ESC> <ESC> <ESC> is unbound

https://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html recommends that "Anything that acts like a temporary mode or state that the user can enter and leave should define <ESC> <ESC> or <ESC> <ESC> <ESC> as a way to escape." I find myself hammering either C-g or <ESC> (I have a mechanical keyboard so it makes appropriate sounds); would be nice if both worked to cancel a transient.

(Aside: I'm happy to see transients arrive! Starting to convert some of my own stuff to use them.)

Some nits about the new popup

I was trying to look for previous issues, apologies if I missed some.

magit-version: Magit 20190215.1903, Git 2.17.1, Emacs 25.2.2, gnu/linux

I upgraded today and saw that the popup buffer behaves differently (I guess with the switch to transient?). My small nit is that it takes ownership too much. Concretely it would be nice if it did not hijack all my usual emacs bindings, especially the C-x bindings, and the windmove shift-{left,up,right,down} keys to move between windows.

The other small nit: it was great being able to treat the popup as a normal buffer, where I could enter and do C-s to search quickly for a command instead of reading through all of them to find the one I need.

Finally, can you give me a quick pointer how to restore q as an alias for C-g to quit magit popups? At the moment, q still works for e.g. log, stash, revision buffers, but not the popups.

As always, thanks for all the great work!

Request: Defer package loading when calling transient

Hi!

I have a big transient I use that contains commands to various packages. When I start the transient for the first time, it seemingly runs?/requires? the packages the command is autoloaded in. For example,

(define-transient-command matcha-me-space ()
  "Space"
  [["Find"
    ("n" "Sidebar" dired-sidebar-toggle-sidebar)]]
  (interactive)
  (let ((transient-show-popup -.2))
    (transient-setup 'matcha-me-space)))

Loads/requires dired-sidebar which also loads its requires and so on causing a heavy initial delay when running the transient.

Thanks for reading!

Getting a return value from a transient

I know transients were invented to make it easier to use external commands, but I’d like to use them to grab some quick data from the user. But, I can’t get a transient to return anything. For instance:

(defun tinas-suffix ()
  (interactive)
  42)

(define-transient-command tinas-transient
  "An example transient"
  ["Tina’s transient"
   ("t" "Tina’s suffix" tinas-suffix)])

(setq test-var (tinas-transient))
test-var

test-var, at the end, is nil, not 42. I can even try something more elaborate:

(defvar rtn-var nil)

(defun tinas-suffix ()
  (interactive)
  (setq rtn-var 42))

(define-transient-command tinas-transient
  "An example transient"
  ["Tina’s transient"
   ("t" "Tina’s suffix" tinas-suffix)])

(defun tinas-transient-wrapper ()
  (interactive)
  (setq rtn-var nil)
  (tinas-transient)
  (prog1 rtn-var
    (setq rtn-var nil)))

(setq test-var (tinas-transient-wrapper))
test-var

…and test-var is still nil. (Further testing shows that the end of tinas-transient-wrapper is being run /before/ the code in tinas-suffix, hence why it’s so difficult to get a synchronous return value.)

What am I doing wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.