mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-18 23:07:13 +09:00
Add support for selection and copy in terminal
This commit adds mouse and copy support in the terminal emulator in micro.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
||||
@@ -16,10 +18,37 @@ const (
|
||||
|
||||
// A Terminal holds information for the terminal emulator
|
||||
type Terminal struct {
|
||||
state terminal.State
|
||||
term *terminal.VT
|
||||
title string
|
||||
status int
|
||||
state terminal.State
|
||||
term *terminal.VT
|
||||
title string
|
||||
status int
|
||||
selection [2]Loc
|
||||
}
|
||||
|
||||
// HasSelection returns whether this terminal has a valid selection
|
||||
func (t *Terminal) HasSelection() bool {
|
||||
return t.selection[0] != t.selection[1]
|
||||
}
|
||||
|
||||
// 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 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
|
||||
@@ -41,6 +70,7 @@ func (t *Terminal) Start(execCmd []string, view *View) error {
|
||||
for {
|
||||
err := term.Parse()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "[Press enter to close]")
|
||||
break
|
||||
}
|
||||
updateterm <- true
|
||||
@@ -91,9 +121,10 @@ func (t *Terminal) Display(v *View) {
|
||||
t.state.Lock()
|
||||
defer t.state.Unlock()
|
||||
|
||||
var l Loc
|
||||
for y := 0; y < v.Height; y++ {
|
||||
for x := 0; x < v.Width; x++ {
|
||||
|
||||
l.X, l.Y = x, y
|
||||
c, f, b := t.state.Cell(x, y)
|
||||
|
||||
fg, bg := int(f), int(b)
|
||||
@@ -105,6 +136,10 @@ func (t *Terminal) Display(v *View) {
|
||||
}
|
||||
st := tcell.StyleDefault.Foreground(GetColor256(int(fg))).Background(GetColor256(int(bg)))
|
||||
|
||||
if l.LessThan(t.selection[1]) && l.GreaterEqual(t.selection[0]) || l.LessThan(t.selection[0]) && l.GreaterEqual(t.selection[1]) {
|
||||
st = st.Reverse(true)
|
||||
}
|
||||
|
||||
screen.SetContent(v.x+x+divider, v.y+y, c, nil, st)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/zyedidia/clipboard"
|
||||
"github.com/zyedidia/tcell"
|
||||
"github.com/zyedidia/terminal"
|
||||
)
|
||||
@@ -534,15 +535,48 @@ 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 && v.term.status == VTDone {
|
||||
switch e.Key() {
|
||||
case tcell.KeyEscape, tcell.KeyCtrlQ, tcell.KeyEnter:
|
||||
v.term.Close()
|
||||
v.Type = vtDefault
|
||||
default:
|
||||
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:
|
||||
}
|
||||
}
|
||||
} else if _, ok := event.(*tcell.EventMouse); !ok || v.term.state.Mode(terminal.ModeMouseMask) {
|
||||
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
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user