mirror of
https://github.com/peco/peco.git
synced 2026-09-10 07:16:29 -04:00
fix #538
This commit is contained in:
parent
4ed16af465
commit
b560fcbbe7
|
|
@ -96,6 +96,7 @@ type Peco struct {
|
|||
selection *Selection
|
||||
selectionPrefix string
|
||||
selectionRangeStart RangeStart
|
||||
exitZeroAndExit bool // True if --exit-0 is enabled
|
||||
selectOneAndExit bool // True if --select-1 is enabled
|
||||
singleKeyJumpMode bool
|
||||
singleKeyJumpPrefixes []rune
|
||||
|
|
@ -442,6 +443,7 @@ type CLIOptions struct {
|
|||
OptPrompt string `long:"prompt" description:"specify the prompt string"`
|
||||
OptLayout string `long:"layout" description:"layout to be used. 'top-down' or 'bottom-up'. default is 'top-down'"`
|
||||
OptSelect1 bool `long:"select-1" description:"select first item and immediately exit if the input contains only 1 item"`
|
||||
OptExitZero bool `long:"exit-0" description:"exit immediately with status 1 if the input is empty"`
|
||||
OptOnCancel string `long:"on-cancel" description:"specify action on user cancel. 'success' or 'error'.\ndefault is 'success'. This may change in future versions"`
|
||||
OptSelectionPrefix string `long:"selection-prefix" description:"use a prefix instead of changing line color to indicate currently selected lines.\ndefault is to use colors. This option is experimental"`
|
||||
OptExec string `long:"exec" description:"execute command instead of finishing/terminating peco.\nPlease note that this command will receive selected line(s) from stdin,\nand will be executed via '/bin/sh -c' or 'cmd /c'"`
|
||||
|
|
|
|||
15
peco.go
15
peco.go
|
|
@ -313,6 +313,12 @@ func (p *Peco) selectOneAndExitIfPossible() {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *Peco) exitZeroIfPossible() {
|
||||
if p.CurrentLineBuffer().Size() == 0 {
|
||||
p.Exit(setExitStatus(makeIgnorable(errors.New("no input, exiting")), 1))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Peco) Run(ctx context.Context) (err error) {
|
||||
if pdebug.Enabled {
|
||||
g := pdebug.Marker("Peco.Run").BindError(&err)
|
||||
|
|
@ -395,6 +401,14 @@ func (p *Peco) Run(ctx context.Context) (err error) {
|
|||
}()
|
||||
}
|
||||
|
||||
// If this is enabled, exit immediately with status 1 when input is empty
|
||||
if p.exitZeroAndExit {
|
||||
go func() {
|
||||
<-p.source.SetupDone()
|
||||
p.exitZeroIfPossible()
|
||||
}()
|
||||
}
|
||||
|
||||
readyOnce.Do(func() { close(p.readyCh) })
|
||||
|
||||
// This has tobe AFTER close(p.readyCh), otherwise the query is
|
||||
|
|
@ -561,6 +575,7 @@ func (p *Peco) ApplyConfig(opts CLIOptions) error {
|
|||
p.selectionPrefix = p.config.SelectionPrefix
|
||||
}
|
||||
p.selectOneAndExit = opts.OptSelect1
|
||||
p.exitZeroAndExit = opts.OptExitZero
|
||||
p.printQuery = opts.OptPrintQuery
|
||||
p.initialQuery = opts.OptQuery
|
||||
p.initialFilter = opts.OptInitialFilter
|
||||
|
|
|
|||
90
peco_test.go
90
peco_test.go
|
|
@ -333,6 +333,7 @@ func TestApplyConfig(t *testing.T) {
|
|||
opts.OptInitialFilter = "Regexp"
|
||||
opts.OptLayout = "bottom-up"
|
||||
opts.OptSelect1 = true
|
||||
opts.OptExitZero = true
|
||||
opts.OptOnCancel = "error"
|
||||
opts.OptSelectionPrefix = ">"
|
||||
opts.OptPrintQuery = true
|
||||
|
|
@ -374,6 +375,10 @@ func TestApplyConfig(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
if !assert.Equal(t, opts.OptExitZero, p.exitZeroAndExit, "p.exitZeroAndExit should be equal to opts.OptExitZero") {
|
||||
return
|
||||
}
|
||||
|
||||
if !assert.Equal(t, opts.OptOnCancel, p.onCancel, "p.onCancel should be equal to opts.OptOnCancel") {
|
||||
return
|
||||
}
|
||||
|
|
@ -504,6 +509,91 @@ func TestGHIssue367(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestExitZero(t *testing.T) {
|
||||
t.Run("Empty input exits with status 1", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
p := newPeco()
|
||||
p.Argv = []string{"--exit-0"}
|
||||
p.Stdin = bytes.NewBufferString("")
|
||||
var out bytes.Buffer
|
||||
p.Stdout = &out
|
||||
|
||||
resultCh := make(chan error)
|
||||
go func() {
|
||||
defer close(resultCh)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case resultCh <- p.Run(ctx):
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Errorf("timeout reached")
|
||||
return
|
||||
case err := <-resultCh:
|
||||
if !assert.True(t, util.IsIgnorableError(err), "error should be ignorable") {
|
||||
return
|
||||
}
|
||||
st, ok := util.GetExitStatus(err)
|
||||
if !assert.True(t, ok, "error should have exit status") {
|
||||
return
|
||||
}
|
||||
if !assert.Equal(t, 1, st, "exit status should be 1") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !assert.Empty(t, out.String(), "output should be empty") {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Non-empty input does not auto-exit", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
p := newPeco()
|
||||
p.Argv = []string{"--exit-0"}
|
||||
p.Stdin = bytes.NewBufferString("foo\n")
|
||||
var out bytes.Buffer
|
||||
p.Stdout = &out
|
||||
|
||||
resultCh := make(chan error)
|
||||
go func() {
|
||||
defer close(resultCh)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case resultCh <- p.Run(ctx):
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for peco to be ready, then cancel after a short delay
|
||||
// If --exit-0 incorrectly triggered, we'd get an ignorable error
|
||||
<-p.Ready()
|
||||
time.AfterFunc(500*time.Millisecond, cancel)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Expected: peco stayed running until we cancelled
|
||||
case err := <-resultCh:
|
||||
// If we got a result, it should NOT be an ignorable error with exit status 1
|
||||
if util.IsIgnorableError(err) {
|
||||
st, ok := util.GetExitStatus(err)
|
||||
if ok && st == 1 {
|
||||
t.Errorf("--exit-0 should not trigger when input is non-empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPrintQuery(t *testing.T) {
|
||||
t.Run("Match and print query", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
|
|
|
|||
Loading…
Reference in a new issue