"bytes"
"os"
"os/exec"
+ "os/signal"
"regexp"
"strings"
-
- "github.com/gdamore/tcell"
)
-// HandleShellCommand runs the shell command and outputs to DisplayBlock
-func HandleShellCommand(input string, view *View) {
+// RunShellCommand executes a shell command and returns the output/error
+func RunShellCommand(input string) (string, error) {
inputCmd := strings.Split(input, " ")[0]
args := strings.Split(input, " ")[1:]
- if inputCmd == "exit" {
- messenger.Message("Ctrl+Q to exit")
- return
- }
- if inputCmd == "help" {
- DisplayHelp()
- return
- }
- cmd := exec.Command(inputCmd, args...)
- var stdout bytes.Buffer
- var stderr bytes.Buffer
- cmd.Stdout = &stdout // send output to buffer
- cmd.Stderr = &stderr // send error to a different buffer
- // Execute Command
- err := cmd.Run()
- if err != nil {
- messenger.Message(err.Error() + "... " + stderr.String())
- return
- }
-
- outstring := stdout.String()
- totalLines := strings.Split(outstring, "\n")
- if len(totalLines) < 3 {
- messenger.Message(outstring)
- return
- }
-
- if outstring != "" {
- DisplayBlock(outstring)
- }
+ cmd := exec.Command(inputCmd, args...)
+ outputBytes := &bytes.Buffer{}
+ cmd.Stdout = outputBytes
+ cmd.Stderr = outputBytes
+ cmd.Start()
+ err := cmd.Wait() // wait for command to finish
+ outstring := outputBytes.String()
+ return outstring, err
}
-// DisplayBlock displays txt
-// It blocks the main loop
-func DisplayBlock(text string) {
- topline := 0
- _, height := screen.Size()
- screen.HideCursor()
- totalLines := strings.Split(text, "\n")
- for {
- screen.Clear()
-
- lineEnd := topline + height
- if lineEnd > len(totalLines) {
- lineEnd = len(totalLines)
- }
- lines := totalLines[topline:lineEnd]
- for y, line := range lines {
- for x, ch := range line {
- st := defStyle
- screen.SetContent(x, y, ch, nil, st)
- }
- }
-
- screen.Show()
-
- event := screen.PollEvent()
- switch e := event.(type) {
- case *tcell.EventResize:
- _, height = e.Size()
- case *tcell.EventKey:
- switch e.Key() {
- case tcell.KeyPgUp:
- if topline > height {
- topline = topline - height
+// HandleShellCommand runs the shell command and outputs to DisplayBlock
+func HandleShellCommand(input string, view *View, openTerm bool) {
+ inputCmd := strings.Split(input, " ")[0]
+ if !openTerm {
+ messenger.Message("Running...")
+ go func() {
+ output, err := RunShellCommand(input)
+ totalLines := strings.Split(output, "\n")
+
+ if len(totalLines) < 3 {
+ if err == nil {
+ messenger.Message(inputCmd, " exited without error")
} else {
- topline = 0
- }
- case tcell.KeyPgDn:
- if topline < len(totalLines)-height {
- topline = topline + height
+ messenger.Message(inputCmd, " exited with error: ", err, ": ", output)
}
- case tcell.KeyUp:
- if topline > 0 {
- topline--
- }
- case tcell.KeyDown:
- if topline < len(totalLines)-height {
- topline++
- }
- case tcell.KeyCtrlQ, tcell.KeyCtrlW, tcell.KeyEscape, tcell.KeyCtrlC:
- return
- default:
- return
+ } else {
+ messenger.Message(output)
}
- }
+ Redraw(view)
+ }()
+ } else {
+ screen.Fini()
+ screen = nil
+
+ args := strings.Split(input, " ")[1:]
+
+ cmd := exec.Command(inputCmd, args...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt)
+ go func() {
+ for range c {
+ cmd.Process.Kill()
+ }
+ }()
+
+ cmd.Start()
+ cmd.Wait()
+
+ TermMessage("")
+
+ InitScreen()
}
}
inputCmd := strings.Split(input, " ")[0]
args := strings.Split(input, " ")[1:]
- commands := []string{"set", "quit", "save", "replace"}
+ commands := []string{"set", "quit", "save", "replace", "run"}
i := 0
cmd := inputCmd
switch inputCmd {
case "set":
SetOption(view, args)
+ case "run":
+ HandleShellCommand(strings.Join(args, " "), view, false)
case "quit":
if view.CanClose("Quit anyway? (yes, no, save) ") {
screen.Fini()
found := false
for {
- match := regex.FindStringIndex(view.buf.text)
+ match := regex.FindStringIndex(view.Buf.String())
if match == nil {
break
}
found = true
if strings.Contains(flags, "c") {
- // // The 'check' flag was used
- // if messenger.YesNoPrompt("Perform replacement?") {
- // view.eh.Replace(match[0], match[1], replace)
- // } else {
- // continue
- // }
+ // The 'check' flag was used
+ Search(search, view, true)
+ view.Relocate()
+ Redraw(view)
+ choice, canceled := messenger.YesNoPrompt("Perform replacement? (y,n)")
+ if canceled {
+ if view.Cursor.HasSelection() {
+ view.Cursor.SetLoc(view.Cursor.curSelection[0])
+ view.Cursor.ResetSelection()
+ }
+ messenger.Reset()
+ return
+ }
+ if choice {
+ view.Cursor.DeleteSelection()
+ view.eh.Insert(match[0], replace)
+ view.Cursor.ResetSelection()
+ messenger.Reset()
+ } else {
+ if view.Cursor.HasSelection() {
+ searchStart = view.Cursor.curSelection[1]
+ } else {
+ searchStart = ToCharPos(view.Cursor.x, view.Cursor.y, view.Buf)
+ }
+ continue
+ }
+ } else {
+ view.eh.Replace(match[0], match[1], replace)
}
- view.eh.Replace(match[0], match[1], replace)
}
if !found {
messenger.Message("Nothing matched " + search)