Skip to content

Commit

Permalink
fixes #120 Support for bracketed paste mode
Browse files Browse the repository at this point in the history
This adds Bracketed Paste support for terminals that have mouse
support and support it.  The bracketing events are EventPaste,
with methods to note Start() or End() of the paste.  Content
comes in as normal rune events.  Programs must opt-in to this by
calling screen.EnablePaste().
  • Loading branch information
gdamore committed Oct 16, 2020
1 parent aeb3a11 commit 197faf3
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 67 deletions.
30 changes: 28 additions & 2 deletions _demos/mouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,13 @@ func main() {
Foreground(tcell.ColorReset)
s.SetStyle(defStyle)
s.EnableMouse()
s.EnablePaste()
s.Clear()

posfmt := "Mouse: %d, %d "
btnfmt := "Buttons: %s"
keyfmt := "Keys: %s"
pastefmt := "Paste: [%d] %s"
white := tcell.StyleDefault.
Foreground(tcell.ColorWhite).Background(tcell.ColorRed)

Expand All @@ -131,15 +133,23 @@ func main() {
lchar := '*'
bstr := ""
lks := ""
pstr := ""
ecnt := 0
pasting := false

for {
drawBox(s, 1, 1, 42, 6, white, ' ')
drawBox(s, 1, 1, 42, 7, white, ' ')
emitStr(s, 2, 2, white, "Press ESC twice to exit, C to clear.")
emitStr(s, 2, 3, white, fmt.Sprintf(posfmt, mx, my))
emitStr(s, 2, 4, white, fmt.Sprintf(btnfmt, bstr))
emitStr(s, 2, 5, white, fmt.Sprintf(keyfmt, lks))

ps := pstr
if len(ps) > 26 {
ps = "..." + ps[len(ps)-24:]
}
emitStr(s, 2, 6, white, fmt.Sprintf(pastefmt, len(pstr), ps))

s.Show()
bstr = ""
ev := s.PollEvent()
Expand All @@ -160,6 +170,17 @@ func main() {
s.SetContent(w-1, h-1, 'R', nil, st)
case *tcell.EventKey:
s.SetContent(w-2, h-2, ev.Rune(), nil, st)
if pasting {
s.SetContent(w-1, h-1, 'P', nil, st)
if ev.Key() == tcell.KeyRune {
pstr = pstr + string(ev.Rune())
} else {
pstr = pstr + "\ufffd" // replacement for now
}
lks = ""
continue
}
pstr = ""
s.SetContent(w-1, h-1, 'K', nil, st)
if ev.Key() == tcell.KeyEscape {
ecnt++
Expand All @@ -176,6 +197,11 @@ func main() {
}
}
lks = ev.Name()
case *tcell.EventPaste:
pasting = ev.Start()
if pasting {
pstr = ""
}
case *tcell.EventMouse:
x, y := ev.Position()
button := ev.Buttons()
Expand Down Expand Up @@ -206,7 +232,7 @@ func main() {
switch ev.Buttons() {
case tcell.ButtonNone:
if ox >= 0 {
bg := tcell.Color((lchar - '0') * 2) | tcell.ColorValid
bg := tcell.Color((lchar-'0')*2) | tcell.ColorValid
drawBox(s, ox, oy, x, y,
up.Background(bg),
lchar)
Expand Down
4 changes: 4 additions & 0 deletions console_win.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ func (s *cScreen) DisableMouse() {
s.setInMode(modeResizeEn | modeExtndFlg)
}

func (s *cScreen) EnablePaste() {}

func (s *cScreen) DisablePaste() {}

func (s *cScreen) Fini() {
s.finiOnce.Do(s.finish)
}
Expand Down
6 changes: 6 additions & 0 deletions key.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,12 @@ const (
KeyF64
)

const (
// These key codes are used internally, and will never appear to applications.
keyPasteStart Key = iota + 16384
keyPasteEnd
)

// These are the control keys. Note that they overlap with other keys,
// perhaps. For example, KeyCtrlH is the same as KeyBackspace.
const (
Expand Down
48 changes: 48 additions & 0 deletions paste.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2020 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
// You may obtain a copy of the license at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tcell

import (
"time"
)

// EventPaste is used to mark the start and end of a bracketed paste.
// An event with .Start() true will be sent to mark the start.
// Then a number of keys will be sent to indicate that the content
// is pasted in. At the end, an event with .Start() false will be sent.
type EventPaste struct {
start bool
t time.Time
}

// When returns the time when this EventMouse was created.
func (ev *EventPaste) When() time.Time {
return ev.t
}

// Start returns true if this is the start of a paste.
func (ev *EventPaste) Start() bool {
return ev.start
}

// End returns true if this is the end of a paste.
func (ev *EventPaste) End() bool {
return !ev.start
}

// NewEventPaste returns a new EventPaste.
func NewEventPaste(start bool) *EventPaste {
return &EventPaste{t: time.Now(), start: start}
}
6 changes: 6 additions & 0 deletions screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ type Screen interface {
// DisableMouse disables the mouse.
DisableMouse()

// EnablePaste enables bracketed paste mode, if supported.
EnablePaste()

// DisablePaste() disables bracketed paste mode.
DisablePaste()

// HasMouse returns true if the terminal (apparently) supports a
// mouse. Note that the a return value of true doesn't guarantee that
// a mouse/pointing device is present; a false return definitely
Expand Down
11 changes: 10 additions & 1 deletion simulation.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 The TCell Authors
// Copyright 2020 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
Expand Down Expand Up @@ -97,6 +97,7 @@ type simscreen struct {
cursory int
cursorvis bool
mouse bool
paste bool
charset string
encoder transform.Transformer
decoder transform.Transformer
Expand Down Expand Up @@ -321,6 +322,14 @@ func (s *simscreen) DisableMouse() {
s.mouse = false
}

func (s *simscreen) EnablePaste() {
s.paste = true
}

func (s *simscreen) DisablePaste() {
s.paste = false
}

func (s *simscreen) Size() (int, int) {
s.Lock()
w, h := s.back.Size()
Expand Down
20 changes: 19 additions & 1 deletion terminfo/dynamic/dynamic.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 The TCell Authors
// Copyright 2020 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
Expand Down Expand Up @@ -376,6 +376,24 @@ func LoadTerminfo(name string) (*terminfo.Terminfo, string, error) {
t.KeyCtrlEnd = "\x1b[8^"
}

// Technically the RGB flag that is provided for xterm-direct is not
// quite right. The problem is that the -direct flag that was introduced
// with ncurses 6.1 requires a parsing for the parameters that we lack.
// For this case we'll just assume it's XTerm compatible. Someday this
// may be incorrect, but right now it is correct, and nobody uses it
// anyway.
if tc.getflag("Tc") {
// This presumes XTerm 24-bit true color.
t.TrueColor = true
} else if tc.getflag("RGB") {
// This is for xterm-direct, which uses a different scheme entirely.
// (ncurses went a very different direction from everyone else, and
// so it's unlikely anything is using this definition.)
t.TrueColor = true
t.SetBg = "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m"
t.SetFg = "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"
}

// If the kmous entry is present, then we need to record the
// the codes to enter and exit mouse mode. Sadly, this is not
// part of the terminfo databases anywhere that I've found, but
Expand Down
4 changes: 4 additions & 0 deletions terminfo/terminfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ type Terminfo struct {
KeyAltShfEnd string
KeyMetaShfHome string
KeyMetaShfEnd string
EnablePaste string // bracketed paste mode
DisablePaste string
PasteStart string
PasteEnd string
Modifiers int
TrueColor bool // true if the terminal supports direct color
}
Expand Down
Loading

0 comments on commit 197faf3

Please sign in to comment.