diff --git a/src/cmd.go b/src/cmd.go index 31a4763..f382783 100644 --- a/src/cmd.go +++ b/src/cmd.go @@ -5,10 +5,11 @@ import ( "fmt" "os" "os/exec" + "strconv" "strings" ) -func RunCommand(match string) (string, string) { +func RunCommand(match string) (string, string, string) { args := prepareArguments(match) cmd := exec.Command(config.program, args...) @@ -30,20 +31,24 @@ func RunCommand(match string) (string, string) { cmd.Stderr = os.Stderr } + exitCode := 0 err = cmd.Run() if err != nil { // Try to forward the command's exit code exitError, ok := err.(*exec.ExitError) if ok { - os.Exit(exitError.ExitCode()) + exitCode = exitError.ExitCode() + if !config.ignoreProgramError { + os.Exit(exitCode) + } } else { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } - return PrintCommand(match), buffer.String() + return PrintCommand(match), buffer.String(), strconv.Itoa(exitCode) } func PrintCommand(match string) string { diff --git a/src/config.go b/src/config.go index fe34dc1..769f84c 100644 --- a/src/config.go +++ b/src/config.go @@ -15,6 +15,7 @@ type Config struct { filter bool sort int showProgramOutput bool + ignoreProgramError bool test bool } @@ -29,6 +30,7 @@ func NewConfig() *Config { filter: false, sort: 0, showProgramOutput: false, + ignoreProgramError: false, test: false, } @@ -49,6 +51,8 @@ func NewConfig() *Config { config.sort = -1 case "--show-output": config.showProgramOutput = true + case "--ignore-error": + config.ignoreProgramError = true case "--line": inputPattern = "^.*$" case "--git-commit-hash": diff --git a/src/items.go b/src/items.go index 8fd4dfb..91f7642 100644 --- a/src/items.go +++ b/src/items.go @@ -94,7 +94,7 @@ func (item *Item) PrintCommand() string { return PrintCommand(item.match) } -func (item *Item) RunCommand() (string, string) { +func (item *Item) RunCommand() (string, string, string) { return RunCommand(item.match) } diff --git a/src/main.go b/src/main.go index f4a87f9..828f81e 100644 --- a/src/main.go +++ b/src/main.go @@ -49,7 +49,7 @@ func main() { itemList.Sort(config.sort) } - run(itemList, 0, "", "") + run(itemList, 0, "", "", "") } func PrintHelp() { @@ -75,6 +75,7 @@ func PrintHelp() { fmt.Println(" --dirname Match the name of an existing directory") fmt.Println("\nOther keyword OPTIONS:") fmt.Println("\n --show-output Show the output (both stdout and stderr) of COMMAND") + fmt.Println(" --ignore-error Ignore any error that occurred during execution of COMMAND") fmt.Println(" --filter Hide lines without a match") fmt.Println(" --sort Sort lines by their matches ignoring lines without a match") fmt.Println(" --sort-rev Reverse --sort") @@ -143,10 +144,10 @@ func readFromPipe() []string { return input } -func run(itemList *ItemList, selectedIndex int, programExecuted string, programOutput string) { +func run(itemList *ItemList, selectedIndex int, programExecuted string, programOutput string, exitStatus string) { ui := initUi() ui.fillList(itemList, selectedIndex) - ui.pageList.setStatus(programExecuted) + ui.pageList.setStatus(exitStatus) if programExecuted != "" && config.showProgramOutput { ui.setText(programExecuted, programOutput) @@ -250,7 +251,7 @@ func (ui *Ui) fillList(itemList *ItemList, selectedIndex int) { // Used for the tests ui.app.Stop() if config.program != "" && ui.pageList.list.GetItemCount() > 0 { - _, output := ui.pageList.itemList.Get(0).RunCommand() + _, output, _ := ui.pageList.itemList.Get(0).RunCommand() if output != "" { fmt.Println(output) } @@ -261,7 +262,7 @@ func (ui *Ui) fillList(itemList *ItemList, selectedIndex int) { } } -func (pageList *PageList) setStatus(programExecuted string) { +func (pageList *PageList) setStatus(exitStatus string) { info := "\n" space := " " @@ -278,8 +279,11 @@ func (pageList *PageList) setStatus(programExecuted string) { index := pageList.list.GetCurrentItem() info += fmt.Sprintf("Line %d of %d", index + 1, pageList.list.GetItemCount()) - if config.program != "" && programExecuted == "" && pageList.itemList.Get(index).HasMatch() { + if config.program != "" && pageList.itemList.Get(index).HasMatch() { info += space + pageList.itemList.Get(index).PrintCommand() + if exitStatus != "" { + info += space + "Exit=" + exitStatus + } } pageList.status.SetText(info) @@ -339,9 +343,9 @@ func (ui *Ui) lineClicked(index int, _ string, _ string, _ rune) { ui.app.Stop() // Run the program and fetch the output if it is not writing to stdout - program, output := item.RunCommand() + program, output, exitStatus := item.RunCommand() // Restart the list view - run(ui.pageList.itemList, index, program, output) + run(ui.pageList.itemList, index, program, output, exitStatus) } } diff --git a/test.sh b/test.sh index bc7562d..7e4e9e0 100755 --- a/test.sh +++ b/test.sh @@ -13,41 +13,49 @@ function run() { ;; 2) ! echo -e "" | ./lisst 2> test/RESULT_$1 + test $? -ne 0 && exit 1 echo "Empty input" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 3) ! echo -e "\n\n" | ./lisst 2> test/RESULT_$1 + test $? -ne 0 && exit 1 echo "Empty input" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 4) echo -e "test1\n test2\n\n\ttest3\ttest3\n\n" | ./lisst > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "test1\n test2\n test3 test3" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 5) ! echo "something" | ./lisst "no\match" 2> test/RESULT_$1 + test $? -ne 0 && exit 1 echo "Invalid regular expression" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 6) echo -e "test1\n test2\n\n\ttest3\ttest3\n\n" | ./lisst test > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[::-][::r]test[::-]1\n [::-][::r]test[::-]2\n [::-][::r]test[::-]3 test3" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 7) echo -e "[test]1\n [test]2\n\n\ttest3\t[test]3\n\n" | ./lisst test > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[[::-][::r]test[::-][]1\n [[::-][::r]test[::-][]2\n [::-][::r]test[::-]3 [test[]3" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 8) echo -e "test1\n test2\n\n\ttest3\ttest3\n\n" | ./lisst "t(est)" > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "t[::-][::r]est[::-]1\n t[::-][::r]est[::-]2\n t[::-][::r]est[::-]3 test3" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 9) echo -e "test1\n test2\n\n\ttest3\ttest3\n\n" | ./lisst nomatch > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "test1\n test2\n test3 test3" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; @@ -55,45 +63,54 @@ function run() { echo -e "#!/bin/sh\nexit 42" > test/EXIT chmod +x test/EXIT echo -e "something" | ./lisst some test/EXIT || echo "$?" > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "42" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 && rm test/EXIT ;; 11) echo -e "test1 test2\ntest3" | ./lisst "test[1-9]" echo > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "test1" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 12) echo -e "test1 test2\ntest3" | ./lisst "test[1-9]" echo foobar > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "foobar test1" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 13) echo -e "test1 test2\ntest3" | ./lisst --line > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[::-][::r]test1 test2[::-]\n[::-][::r]test3[::-]" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 14) echo -e "test1234 abcdef1\n0987654321 1234567\n--git-commit-hash" | ./lisst --git-commit-hash > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "test1234 [::-][::r]abcdef1[::-]\n[::-][::r]0987654321[::-] 1234567\n--git-commit-hash" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 15) echo -e "./src/main.go:content\nMakefile:42:content" | ./lisst --filename > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[::-][::r]./src/main.go[::-]:content\n[::-][::r]Makefile[::-]:42:content" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 16) echo -e "./src/main.go:content\nMakefile:42:content" | ./lisst --filename echo > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "./src/main.go" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 17) ! echo -e "test1\nztest2" | ./lisst "test" invalid 2> test/RESULT_$1 + test $? -ne 0 && exit 1 grep -q "file not found" test/RESULT_$1 ;; 18) echo -e "./src/main.go:content\nMakefile:42:content" | ./lisst --show-output --filename echo -n foo > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "foo ./src/main.go" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; @@ -101,80 +118,102 @@ function run() { echo -e "#!/bin/bash\necho \"\$@\";echo -n \"\$@\" 1>&2" > test/SCRIPT_$1 chmod +x test/SCRIPT_$1 echo -e "./src/main.go:content\nMakefile:42:content" | ./lisst --filename --show-output test/SCRIPT_$1 > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "./src/main.go\n./src/main.go" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 20) echo -e "test1 test2\ntest3" | ./lisst "test[1-9]" echo {} foobar > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "test1 foobar" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 21) echo -e "test1 test2\ntest3" | ./lisst "test[1-9]" echo foo{}b{}ar > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "footest1btest1ar" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 22) echo -e "extract the ./ file ./test.sh and not Makefile" | ./lisst --filename echo > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "./test.sh" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 23) echo -e "extract the ./ file ./test.sh and not Makefile" | ./lisst --dirname echo > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "./" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 24) echo -e "this text is \033[0;31mred\033[0m and \033[0;34mblue\033[0m" | ./lisst red > test/RESULT_$1 + test $? -ne 0 && exit 1 echo "this text is [maroon:][::-][::r]red[::-][-:-:] and [navy:]blue[-:-:]" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 25) echo -e "test1 test2\ntest3\ntest2" | ./lisst --filter test2 > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "test1 [::-][::r]test2[::-]\n[::-][::r]test2[::-]" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 26) echo -e "test1 test2\ntest3\ntest2" | ./lisst test2 --filter > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "test1 [::-][::r]test2[::-]\n[::-][::r]test2[::-]" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 27) ! echo -e "test1 test2\ntest3\ntest2" | ./lisst --filter no_match 2> test/RESULT_$1 + test $? -ne 0 && exit 1 echo "All lines filtered out" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 28) echo -e "./src/main.go:content:2\nMakefile:42:content\nMakefile:1:2:3" | ./lisst --filename-lineno > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "./src/main.go:content:2\n[::-][::r]Makefile:42[::-]:content\n[::-][::r]Makefile:1[::-]:2:3" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 29) echo -e "test3\ntest11\nfoobar2\ntest2\nfoobar1\n" | ./lisst --sort "test[0-9]" > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[::-][::r]test1[::-]1\n[::-][::r]test2[::-]\n[::-][::r]test3[::-]\nfoobar2\nfoobar1" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 30) echo -e "test3\ntest11\nfoobar2\ntest2\nfoobar1\n" | ./lisst --sort-rev "test[0-9]" > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[::-][::r]test3[::-]\n[::-][::r]test2[::-]\n[::-][::r]test1[::-]1\nfoobar2\nfoobar1" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 31) echo -e "200\n3.14\n\n70.1\n" | ./lisst --sort --line > test/RESULT_$1 + test $? -ne 0 && exit 1 echo -e "[::-][::r]3.14[::-]\n[::-][::r]70.1[::-]\n[::-][::r]200[::-]" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; 32) echo -e "foobar\n" | ./lisst --foobar 2> test/RESULT_$1 + test $? -ne 1 && exit 1 echo "Invalid command-line option --foobar" > test/EXPECT_$1 diff test/RESULT_$1 test/EXPECT_$1 ;; + 33) + echo -e "#!/bin/bash\necho \"\$@\"\nexit 1" > test/SCRIPT_$1 + chmod +x test/SCRIPT_$1 + echo -e "test1 test2\ntest3" | ./lisst --ignore-error "test[1-9]" test/SCRIPT_$1 > test/RESULT_$1 + test $? -ne 0 && exit 1 + echo "test1" > test/EXPECT_$1 + diff test/RESULT_$1 test/EXPECT_$1 + ;; esac } if [ $# -eq 0 ]; then result=0 - for i in {1..32}; do + for i in {1..33}; do echo "Test $i" run $i || { result=1; echo " FAILED"; } done