]> git.lizzy.rs Git - micro.git/blob - cmd/micro/shell/terminal.go
b4e5da31e813381f25687252f5dee6dff7b465d6
[micro.git] / cmd / micro / shell / terminal.go
1 package shell
2
3 import (
4         "bytes"
5         "fmt"
6         "os"
7         "os/exec"
8         "strconv"
9
10         "github.com/zyedidia/micro/cmd/micro/buffer"
11         "github.com/zyedidia/micro/cmd/micro/screen"
12         "github.com/zyedidia/terminal"
13 )
14
15 type TermType int
16
17 const (
18         TTIdle    = iota // Waiting for a new command
19         TTRunning        // Currently running a command
20         TTDone           // Finished running a command
21 )
22
23 // A Terminal holds information for the terminal emulator
24 type Terminal struct {
25         State     terminal.State
26         Term      *terminal.VT
27         title     string
28         Status    TermType
29         Selection [2]buffer.Loc
30         wait      bool
31         getOutput bool
32         output    *bytes.Buffer
33         callback  string
34 }
35
36 // HasSelection returns whether this terminal has a valid selection
37 func (t *Terminal) HasSelection() bool {
38         return t.Selection[0] != t.Selection[1]
39 }
40
41 // GetSelection returns the selected text
42 func (t *Terminal) GetSelection(width int) string {
43         start := t.Selection[0]
44         end := t.Selection[1]
45         if start.GreaterThan(end) {
46                 start, end = end, start
47         }
48         var ret string
49         var l buffer.Loc
50         for y := start.Y; y <= end.Y; y++ {
51                 for x := 0; x < width; x++ {
52                         l.X, l.Y = x, y
53                         if l.GreaterEqual(start) && l.LessThan(end) {
54                                 c, _, _ := t.State.Cell(x, y)
55                                 ret += string(c)
56                         }
57                 }
58         }
59         return ret
60 }
61
62 // Start begins a new command in this terminal with a given view
63 func (t *Terminal) Start(execCmd []string, getOutput bool) error {
64         if len(execCmd) <= 0 {
65                 return nil
66         }
67
68         cmd := exec.Command(execCmd[0], execCmd[1:]...)
69         t.output = nil
70         if getOutput {
71                 t.output = bytes.NewBuffer([]byte{})
72         }
73         Term, _, err := terminal.Start(&t.State, cmd, t.output)
74         if err != nil {
75                 return err
76         }
77         t.Term = Term
78         t.getOutput = getOutput
79         t.Status = TTRunning
80         t.title = execCmd[0] + ":" + strconv.Itoa(cmd.Process.Pid)
81
82         go func() {
83                 for {
84                         err := Term.Parse()
85                         if err != nil {
86                                 fmt.Fprintln(os.Stderr, "[Press enter to close]")
87                                 break
88                         }
89                         screen.Redraw()
90                 }
91                 // TODO: close Term
92                 // closeterm <- view.Num
93         }()
94
95         return nil
96 }
97
98 // Stop stops execution of the terminal and sets the Status
99 // to TTDone
100 func (t *Terminal) Stop() {
101         t.Term.File().Close()
102         t.Term.Close()
103         if t.wait {
104                 t.Status = TTDone
105         } else {
106                 t.Close()
107         }
108 }
109
110 // Close sets the Status to TTIdle indicating that the terminal
111 // is ready for a new command to execute
112 func (t *Terminal) Close() {
113         t.Status = TTIdle
114         // call the lua function that the user has given as a callback
115         if t.getOutput {
116                 // TODO: plugin callback on Term emulator
117                 // _, err := Call(t.callback, t.output.String())
118                 // if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
119                 //      TermMessage(err)
120                 // }
121         }
122 }
123
124 // WriteString writes a given string to this terminal's pty
125 func (t *Terminal) WriteString(str string) {
126         t.Term.File().WriteString(str)
127 }