2019-01-11 05:26:58 +03:00
|
|
|
package shell
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strconv"
|
|
|
|
|
2019-02-04 07:17:24 +03:00
|
|
|
"github.com/zyedidia/micro/internal/buffer"
|
|
|
|
"github.com/zyedidia/micro/internal/screen"
|
2019-01-11 05:26:58 +03:00
|
|
|
"github.com/zyedidia/terminal"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TermType int
|
|
|
|
|
|
|
|
const (
|
2019-01-11 22:49:22 +03:00
|
|
|
TTClose = iota // Should be closed
|
2019-01-11 05:26:58 +03:00
|
|
|
TTRunning // Currently running a command
|
|
|
|
TTDone // Finished running a command
|
|
|
|
)
|
|
|
|
|
|
|
|
// A Terminal holds information for the terminal emulator
|
|
|
|
type Terminal struct {
|
|
|
|
State terminal.State
|
|
|
|
Term *terminal.VT
|
|
|
|
title string
|
|
|
|
Status TermType
|
|
|
|
Selection [2]buffer.Loc
|
|
|
|
wait bool
|
|
|
|
getOutput bool
|
|
|
|
output *bytes.Buffer
|
|
|
|
callback string
|
|
|
|
}
|
|
|
|
|
|
|
|
// HasSelection returns whether this terminal has a valid selection
|
|
|
|
func (t *Terminal) HasSelection() bool {
|
|
|
|
return t.Selection[0] != t.Selection[1]
|
|
|
|
}
|
|
|
|
|
2019-01-11 22:49:22 +03:00
|
|
|
func (t *Terminal) Name() string {
|
|
|
|
return t.title
|
|
|
|
}
|
|
|
|
|
2019-01-11 05:26:58 +03:00
|
|
|
// GetSelection returns the selected text
|
|
|
|
func (t *Terminal) GetSelection(width int) string {
|
|
|
|
start := t.Selection[0]
|
|
|
|
end := t.Selection[1]
|
|
|
|
if start.GreaterThan(end) {
|
|
|
|
start, end = end, start
|
|
|
|
}
|
|
|
|
var ret string
|
|
|
|
var l buffer.Loc
|
|
|
|
for y := start.Y; y <= end.Y; y++ {
|
|
|
|
for x := 0; x < width; x++ {
|
|
|
|
l.X, l.Y = x, y
|
|
|
|
if l.GreaterEqual(start) && l.LessThan(end) {
|
|
|
|
c, _, _ := t.State.Cell(x, y)
|
|
|
|
ret += string(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start begins a new command in this terminal with a given view
|
2019-01-11 22:49:22 +03:00
|
|
|
func (t *Terminal) Start(execCmd []string, getOutput bool, wait bool) error {
|
2019-01-11 05:26:58 +03:00
|
|
|
if len(execCmd) <= 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd := exec.Command(execCmd[0], execCmd[1:]...)
|
|
|
|
t.output = nil
|
|
|
|
if getOutput {
|
|
|
|
t.output = bytes.NewBuffer([]byte{})
|
|
|
|
}
|
|
|
|
Term, _, err := terminal.Start(&t.State, cmd, t.output)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
t.Term = Term
|
|
|
|
t.getOutput = getOutput
|
|
|
|
t.Status = TTRunning
|
|
|
|
t.title = execCmd[0] + ":" + strconv.Itoa(cmd.Process.Pid)
|
2019-01-11 22:49:22 +03:00
|
|
|
t.wait = wait
|
2019-01-11 05:26:58 +03:00
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
err := Term.Parse()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, "[Press enter to close]")
|
|
|
|
break
|
|
|
|
}
|
|
|
|
screen.Redraw()
|
|
|
|
}
|
2019-01-11 22:49:22 +03:00
|
|
|
t.Stop()
|
2019-01-11 05:26:58 +03:00
|
|
|
}()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop stops execution of the terminal and sets the Status
|
|
|
|
// to TTDone
|
|
|
|
func (t *Terminal) Stop() {
|
|
|
|
t.Term.File().Close()
|
|
|
|
t.Term.Close()
|
|
|
|
if t.wait {
|
|
|
|
t.Status = TTDone
|
|
|
|
} else {
|
|
|
|
t.Close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 22:49:22 +03:00
|
|
|
// Close sets the Status to TTClose indicating that the terminal
|
|
|
|
// is done and should be closed
|
2019-01-11 05:26:58 +03:00
|
|
|
func (t *Terminal) Close() {
|
2019-01-11 22:49:22 +03:00
|
|
|
t.Status = TTClose
|
2019-01-11 05:26:58 +03:00
|
|
|
// call the lua function that the user has given as a callback
|
|
|
|
if t.getOutput {
|
|
|
|
// TODO: plugin callback on Term emulator
|
|
|
|
// _, err := Call(t.callback, t.output.String())
|
|
|
|
// if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
|
|
|
|
// TermMessage(err)
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteString writes a given string to this terminal's pty
|
|
|
|
func (t *Terminal) WriteString(str string) {
|
|
|
|
t.Term.File().WriteString(str)
|
|
|
|
}
|