Change exit status (0: OK, 1: No match, 2: Error/Interrupted)

A la grep. Close #345
This commit is contained in:
Junegunn Choi 2015-09-15 13:21:51 +09:00
parent fa2f9f1f21
commit 65d9d416b4
6 changed files with 76 additions and 20 deletions

View File

@ -47,3 +47,9 @@ const (
EvtHeader
EvtClose
)
const (
exitOk = 0
exitNoMatch = 1
exitError = 2
)

View File

@ -56,7 +56,7 @@ func Run(opts *Options) {
if opts.Version {
fmt.Println(version)
os.Exit(0)
os.Exit(exitOk)
}
// Event channel
@ -156,12 +156,14 @@ func Run(opts *Options) {
pattern := patternBuilder([]rune(*opts.Filter))
found := false
if streamingFilter {
reader := Reader{
func(runes []byte) bool {
item := chunkList.trans(runes, 0)
if item != nil && pattern.MatchItem(item) {
fmt.Println(string(item.text))
found = true
}
return false
}, eventBox, opts.ReadZero}
@ -176,9 +178,13 @@ func Run(opts *Options) {
pattern: pattern})
for i := 0; i < merger.Length(); i++ {
fmt.Println(merger.Get(i).AsString(opts.Ansi))
found = true
}
}
os.Exit(0)
if found {
os.Exit(exitOk)
}
os.Exit(exitNoMatch)
}
// Synchronous search
@ -253,7 +259,10 @@ func Run(opts *Options) {
for i := 0; i < count; i++ {
fmt.Println(val.Get(i).AsString(opts.Ansi))
}
os.Exit(0)
if count > 0 {
os.Exit(exitOk)
}
os.Exit(exitNoMatch)
}
deferred = false
terminal.startChan <- true

View File

@ -261,7 +261,7 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
_screen = C.newterm(nil, C.stderr, C.stdin)
if _screen == nil {
fmt.Println("Invalid $TERM: " + os.Getenv("TERM"))
os.Exit(1)
os.Exit(2)
}
C.set_term(_screen)
if mouse {
@ -275,7 +275,7 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
go func() {
<-intChan
Close()
os.Exit(1)
os.Exit(2)
}()
if theme != nil {

View File

@ -180,14 +180,14 @@ func defaultOptions() *Options {
Version: false}
}
func help(ok int) {
func help(code int) {
os.Stderr.WriteString(usage)
os.Exit(ok)
os.Exit(code)
}
func errorExit(msg string) {
os.Stderr.WriteString(msg + "\n")
os.Exit(1)
os.Exit(exitError)
}
func optString(arg string, prefixes ...string) (bool, string) {
@ -682,7 +682,7 @@ func parseOptions(opts *Options, allArgs []string) {
arg := allArgs[i]
switch arg {
case "-h", "--help":
help(0)
help(exitOk)
case "-x", "--extended":
opts.Mode = ModeExtended
case "-e", "--extended-exact":

View File

@ -280,17 +280,19 @@ func (t *Terminal) UpdateList(merger *Merger) {
t.reqBox.Set(reqList, nil)
}
func (t *Terminal) output() {
func (t *Terminal) output() bool {
if t.printQuery {
fmt.Println(string(t.input))
}
if len(t.expect) > 0 {
fmt.Println(t.pressed)
}
if len(t.selected) == 0 {
found := len(t.selected) > 0
if !found {
cnt := t.merger.Length()
if cnt > 0 && cnt > t.cy {
fmt.Println(t.merger.Get(t.cy).AsString(t.ansi))
found = true
}
} else {
sels := make([]selectedItem, 0, len(t.selected))
@ -302,6 +304,7 @@ func (t *Terminal) output() {
fmt.Println(*sel.text)
}
}
return found
}
func runeWidth(r rune, prefixWidth int) int {
@ -743,7 +746,7 @@ func (t *Terminal) Loop() {
}
exit := func(code int) {
if code == 0 && t.history != nil {
if code <= exitNoMatch && t.history != nil {
t.history.append(string(t.input))
}
os.Exit(code)
@ -776,11 +779,13 @@ func (t *Terminal) Loop() {
t.printAll()
case reqClose:
C.Close()
t.output()
exit(0)
if t.output() {
exit(exitOk)
}
exit(exitNoMatch)
case reqQuit:
C.Close()
exit(1)
exit(exitError)
}
}
t.placeCursor()

View File

@ -780,11 +780,6 @@ class TestGoFZF < TestBase
tmux.send_keys :Enter
end
def test_invalid_term
tmux.send_keys "TERM=xxx fzf", :Enter
tmux.until { |lines| lines.any? { |l| l.include? 'Invalid $TERM: xxx' } }
end
def test_with_nth
writelines tempname, ['hello world ', 'byebye']
assert_equal 'hello world ', `cat #{tempname} | #{FZF} -f"^he hehe" -x -n 2.. --with-nth 2,1,1`.chomp
@ -801,6 +796,47 @@ class TestGoFZF < TestBase
assert_equal src, `cat #{tempname} | #{FZF} -fhehe -x -n 2.. --with-nth 2,1,1 --no-ansi`.chomp
end
def test_exit_0_exit_code
`echo foo | #{FZF} -q bar -0`
assert_equal 1, $?.exitstatus
end
def test_invalid_term
lines = `TERM=xxx #{FZF}`
assert_equal 2, $?.exitstatus
assert lines.include?('Invalid $TERM: xxx')
end
def test_invalid_option
lines = `#{FZF} --foobar 2>&1`
assert_equal 2, $?.exitstatus
assert lines.include?('unknown option: --foobar'), lines
end
def test_filter_exitstatus
# filter / streaming filter
["", "--no-sort"].each do |opts|
assert `echo foo | #{FZF} -f foo #{opts}`.include?('foo')
assert_equal 0, $?.exitstatus
assert `echo foo | #{FZF} -f bar #{opts}`.empty?
assert_equal 1, $?.exitstatus
end
end
def test_exitstatus_empty
{ '99' => '0', '999' => '1' }.each do |query, status|
tmux.send_keys "seq 100 | #{FZF} -q #{query}", :Enter
tmux.until { |lines| lines[-2] =~ %r{ [10]/100} }
tmux.send_keys :Enter
tmux.send_keys 'echo --\$?--'
tmux.until { |lines| lines.last.include? "echo --$?--" }
tmux.send_keys :Enter
tmux.until { |lines| lines.last.include? "--#{status}--" }
end
end
private
def writelines path, lines
File.unlink path while File.exists? path