]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/command.go
Fix crash
[micro.git] / cmd / micro / command.go
index 8600d7a125632a34347027bf939afadaab1168bb..dac6ed58a7bbf7d03f1f63e7d82f2adfb60370e2 100644 (file)
@@ -4,92 +4,71 @@ import (
        "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:]
 
-       // Execute Command
        cmd := exec.Command(inputCmd, args...)
        outputBytes := &bytes.Buffer{}
-
-       cmd.Stdout = outputBytes // send output to buffer
+       cmd.Stdout = outputBytes
+       cmd.Stderr = outputBytes
        cmd.Start()
-       cmd.Wait() // wait for command to finish
+       err := cmd.Wait() // wait for command to finish
        outstring := outputBytes.String()
-       totalLines := strings.Split(outstring, "\n")
-
-       if len(totalLines) < 3 {
-               messenger.Message(outstring)
-               return
-       }
-
-       if outstring != "" {
-               // Display nonblank output
-               DisplayBlock(outstring)
-       }
+       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
-                               }
-                       case tcell.KeyUp:
-                               if topline > 0 {
-                                       topline--
+                                       messenger.Message(inputCmd, " exited with error: ", err, ": ", output)
                                }
-                       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()
        }
 }
 
@@ -98,7 +77,7 @@ func HandleCommand(input string, view *View) {
        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
@@ -116,8 +95,10 @@ func HandleCommand(input string, view *View) {
        switch inputCmd {
        case "set":
                SetOption(view, args)
+       case "run":
+               HandleShellCommand(strings.Join(args, " "), view, false)
        case "quit":
-               if view.CanClose("Quit anyway? ") {
+               if view.CanClose("Quit anyway? (yes, no, save) ") {
                        screen.Fini()
                        os.Exit(0)
                }
@@ -160,20 +141,41 @@ func HandleCommand(input string, view *View) {
 
                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.Buf.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.Buf.Replace(match[0], match[1], replace)
                        }
-                       view.eh.Replace(match[0], match[1], replace)
                }
                if !found {
                        messenger.Message("Nothing matched " + search)