From 6ef00c4c3bcd72f1c8621a51416c988e4733ba9c Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Fri, 19 Jan 2018 00:28:51 -0500 Subject: [PATCH] Clean up terminal emulator a bit --- cmd/micro/terminal.go | 81 +++++++++++++++++++++++++++++++++++++------ cmd/micro/view.go | 48 ++----------------------- 2 files changed, 73 insertions(+), 56 deletions(-) diff --git a/cmd/micro/terminal.go b/cmd/micro/terminal.go index 45b61db1..06a24ce3 100644 --- a/cmd/micro/terminal.go +++ b/cmd/micro/terminal.go @@ -6,6 +6,7 @@ import ( "os/exec" "strconv" + "github.com/zyedidia/clipboard" "github.com/zyedidia/tcell" "github.com/zyedidia/terminal" ) @@ -19,10 +20,13 @@ const ( // A Terminal holds information for the terminal emulator type Terminal struct { state terminal.State + view *View + vtOld ViewType term *terminal.VT title string status int selection [2]Loc + wait bool } // HasSelection returns whether this terminal has a valid selection @@ -63,6 +67,8 @@ func (t *Terminal) Start(execCmd []string, view *View) error { return err } t.term = term + t.view = view + t.vtOld = view.Type t.status = VTRunning t.title = execCmd[0] + ":" + strconv.Itoa(cmd.Process.Pid) @@ -86,12 +92,67 @@ func (t *Terminal) Resize(width, height int) { t.term.Resize(width, height) } +// HandleEvent handles a tcell event by forwarding it to the terminal emulator +// If the event is a mouse event and the program running in the emulator +// does not have mouse support, the emulator will support selections and +// copy-paste +func (t *Terminal) HandleEvent(event tcell.Event) { + if e, ok := event.(*tcell.EventKey); ok { + if t.status == VTDone { + switch e.Key() { + case tcell.KeyEscape, tcell.KeyCtrlQ, tcell.KeyEnter: + t.Close() + t.view.Type = vtDefault + default: + } + } + if e.Key() == tcell.KeyCtrlC && t.HasSelection() { + clipboard.WriteAll(t.GetSelection(t.view.Width), "clipboard") + messenger.Message("Copied selection to clipboard") + } else if t.status != VTDone { + t.WriteString(event.EscSeq()) + } + } else if e, ok := event.(*tcell.EventMouse); !ok || t.state.Mode(terminal.ModeMouseMask) { + t.WriteString(event.EscSeq()) + } else { + x, y := e.Position() + x -= t.view.x + y += t.view.y + + if e.Buttons() == tcell.Button1 { + if !t.view.mouseReleased { + // drag + t.selection[1].X = x + t.selection[1].Y = y + } else { + t.selection[0].X = x + t.selection[0].Y = y + t.selection[1].X = x + t.selection[1].Y = y + } + + t.view.mouseReleased = false + } else if e.Buttons() == tcell.ButtonNone { + if !t.view.mouseReleased { + t.selection[1].X = x + t.selection[1].Y = y + } + t.view.mouseReleased = true + } + } +} + // Stop stops execution of the terminal and sets the status // to VTDone func (t *Terminal) Stop() { t.term.File().Close() t.term.Close() - t.status = VTDone + if t.wait { + t.status = VTDone + } else { + t.status = VTIdle + t.view.Type = t.vtOld + } } // Close sets the status to VTIdle indicating that the terminal @@ -106,24 +167,24 @@ func (t *Terminal) WriteString(str string) { } // Display displays this terminal in a view -func (t *Terminal) Display(v *View) { +func (t *Terminal) Display() { divider := 0 - if v.x != 0 { + if t.view.x != 0 { divider = 1 dividerStyle := defStyle if style, ok := colorscheme["divider"]; ok { dividerStyle = style } - for i := 0; i < v.Height; i++ { - screen.SetContent(v.x, v.y+i, '|', nil, dividerStyle.Reverse(true)) + for i := 0; i < t.view.Height; i++ { + screen.SetContent(t.view.x, t.view.y+i, '|', nil, dividerStyle.Reverse(true)) } } t.state.Lock() defer t.state.Unlock() var l Loc - for y := 0; y < v.Height; y++ { - for x := 0; x < v.Width; x++ { + for y := 0; y < t.view.Height; y++ { + for x := 0; x < t.view.Width; x++ { l.X, l.Y = x, y c, f, b := t.state.Cell(x, y) @@ -140,11 +201,11 @@ func (t *Terminal) Display(v *View) { st = st.Reverse(true) } - screen.SetContent(v.x+x+divider, v.y+y, c, nil, st) + screen.SetContent(t.view.x+x+divider, t.view.y+y, c, nil, st) } } - if t.state.CursorVisible() && tabs[curTab].CurView == v.Num { + if t.state.CursorVisible() && tabs[curTab].CurView == t.view.Num { curx, cury := t.state.Cursor() - screen.ShowCursor(curx+v.x+divider, cury+v.y) + screen.ShowCursor(curx+t.view.x+divider, cury+t.view.y) } } diff --git a/cmd/micro/view.go b/cmd/micro/view.go index fcdb90de..fec32013 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -8,9 +8,7 @@ import ( "strings" "time" - "github.com/zyedidia/clipboard" "github.com/zyedidia/tcell" - "github.com/zyedidia/terminal" ) // The ViewType defines what kind of view this is @@ -561,49 +559,7 @@ func (v *View) SetCursor(c *Cursor) bool { // HandleEvent handles an event passed by the main loop func (v *View) HandleEvent(event tcell.Event) { if v.Type == vtTerm { - if e, ok := event.(*tcell.EventKey); ok { - if v.term.status == VTDone { - switch e.Key() { - case tcell.KeyEscape, tcell.KeyCtrlQ, tcell.KeyEnter: - v.term.Close() - v.Type = vtDefault - default: - } - } - if e.Key() == tcell.KeyCtrlC && v.term.HasSelection() { - clipboard.WriteAll(v.term.GetSelection(v.Width), "clipboard") - messenger.Message("Copied selection to clipboard") - } else if v.term.status != VTDone { - v.term.WriteString(event.EscSeq()) - } - } else if e, ok := event.(*tcell.EventMouse); !ok || v.term.state.Mode(terminal.ModeMouseMask) { - v.term.WriteString(event.EscSeq()) - } else { - x, y := e.Position() - x -= v.x - y += v.y - - if e.Buttons() == tcell.Button1 { - if !v.mouseReleased { - // drag - v.term.selection[1].X = x - v.term.selection[1].Y = y - } else { - v.term.selection[0].X = x - v.term.selection[0].Y = y - v.term.selection[1].X = x - v.term.selection[1].Y = y - } - - v.mouseReleased = false - } else if e.Buttons() == tcell.ButtonNone { - if !v.mouseReleased { - v.term.selection[1].X = x - v.term.selection[1].Y = y - } - v.mouseReleased = true - } - } + v.term.HandleEvent(event) return } @@ -842,7 +798,7 @@ func (v *View) openHelp(helpPage string) { // DisplayView draws the view to the screen func (v *View) DisplayView() { if v.Type == vtTerm { - v.term.Display(v) + v.term.Display() return } -- 2.44.0