7 "github.com/zyedidia/micro/v2/internal/clipboard"
8 "github.com/zyedidia/micro/v2/internal/config"
9 "github.com/zyedidia/micro/v2/internal/display"
10 "github.com/zyedidia/micro/v2/internal/screen"
11 "github.com/zyedidia/micro/v2/internal/shell"
12 "github.com/zyedidia/tcell/v2"
13 "github.com/zyedidia/terminal"
16 type TermKeyAction func(*TermPane)
18 var TermBindings *KeyTree
21 TermBindings = NewKeyTree()
24 func TermKeyActionGeneral(a TermKeyAction) PaneKeyAction {
25 return func(p Pane) bool {
31 func TermMapEvent(k Event, action string) {
32 config.Bindings["terminal"][k.Name()] = action
34 switch e := k.(type) {
35 case KeyEvent, KeySequenceEvent, RawEvent:
38 termMapMouse(e, action)
42 func termMapKey(k Event, action string) {
43 if f, ok := TermKeyActions[action]; ok {
44 TermBindings.RegisterKeyBinding(k, TermKeyActionGeneral(f))
48 func termMapMouse(k MouseEvent, action string) {
53 type TermPane struct {
62 func NewTermPane(x, y, w, h int, t *shell.Terminal, id uint64, tab *Tab) (*TermPane, error) {
63 if !TermEmuSupported {
64 return nil, errors.New("Terminal emulator is not supported on this system")
70 th.mouseReleased = true
71 th.Window = display.NewTermWindow(x, y, w, h, t)
76 func (t *TermPane) ID() uint64 {
80 func (t *TermPane) SetID(i uint64) {
84 func (t *TermPane) SetTab(tab *Tab) {
88 func (t *TermPane) Tab() *Tab {
92 func (t *TermPane) Close() {}
94 // Quit closes this termpane
95 func (t *TermPane) Quit() {
97 if len(MainTab().Panes) > 1 {
99 } else if len(Tabs.List) > 1 {
108 // Unsplit removes this split
109 func (t *TermPane) Unsplit() {
110 n := MainTab().GetNode(t.id)
113 MainTab().RemovePane(MainTab().GetPane(t.id))
115 MainTab().SetActive(len(MainTab().Panes) - 1)
118 // HandleEvent handles a tcell event by forwarding it to the terminal emulator
119 // If the event is a mouse event and the program running in the emulator
120 // does not have mouse support, the emulator will support selections and
122 func (t *TermPane) HandleEvent(event tcell.Event) {
123 if e, ok := event.(*tcell.EventKey); ok {
126 mod: metaToAlt(e.Modifiers()),
129 action, more := TermBindings.NextEvent(ke, nil)
134 TermBindings.ResetEvents()
137 TermBindings.ResetEvents()
144 if t.Status == shell.TTDone {
146 case tcell.KeyEscape, tcell.KeyCtrlQ, tcell.KeyEnter:
152 if e.Key() == tcell.KeyCtrlC && t.HasSelection() {
153 clipboard.Write(t.GetSelection(t.GetView().Width), clipboard.ClipboardReg)
154 InfoBar.Message("Copied selection to clipboard")
155 } else if t.Status != shell.TTDone {
156 t.WriteString(event.EscSeq())
158 } else if _, ok := event.(*tcell.EventPaste); ok {
159 if t.Status != shell.TTDone {
160 t.WriteString(event.EscSeq())
162 } else if e, ok := event.(*tcell.EventMouse); e != nil && (!ok || t.State.Mode(terminal.ModeMouseMask)) {
163 // t.WriteString(event.EscSeq())
170 if e.Buttons() == tcell.Button1 {
171 if !t.mouseReleased {
182 t.mouseReleased = false
183 } else if e.Buttons() == tcell.ButtonNone {
184 if !t.mouseReleased {
188 t.mouseReleased = true
192 if t.Status == shell.TTClose {
197 // Exit closes the termpane
198 func (t *TermPane) Exit() {
203 // CommandMode opens the termpane's command mode
204 func (t *TermPane) CommandMode() {
205 InfoBar.Prompt("> ", "", "TerminalCommand", nil, func(resp string, canceled bool) {
207 t.HandleCommand(resp)
212 // NextSplit moves to the next split
213 func (t *TermPane) NextSplit() {
215 if a < len(t.tab.Panes)-1 {
224 // HandleCommand handles a command for the term pane
225 func (t *TermPane) HandleCommand(input string) {
226 InfoBar.Error("Commands are unsupported in term for now")
229 // TermKeyActions contains the list of all possible key actions the termpane could execute
230 var TermKeyActions = map[string]TermKeyAction{
231 "Exit": (*TermPane).Exit,
232 "CommandMode": (*TermPane).CommandMode,
233 "NextSplit": (*TermPane).NextSplit,