1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-05 00:59:19 +02:00

bump gocui

This commit is contained in:
Jesse Duffield
2021-04-01 21:07:21 +11:00
parent 5d0cf3d919
commit 5f77ac8d6f
366 changed files with 17033 additions and 1164 deletions

View File

@ -28,8 +28,8 @@ Version 1.x remains available using the import `github.com/gdamore/tcell`.
* https://github.com/gdamore/gomatrix[gomatrix] - converted from Termbox
* https://github.com/zyedidia/micro/[micro] - lightweight text editor with syntax-highlighting and themes
* https://github.com/viktomas/godu[godu] - simple golang utility helping to discover large files/folders.
* https://github.com/rivo/tview[tview] - rich interactive widgets for terminal UIs
* https://github.com/marcusolsson/tui-go[tui-go] - UI library for terminal apps (_deprecated_)
* https://github.com/rivo/tview/[tview] - rich interactive widgets for terminal UIs
* https://github.com/awesome-gocui/gocui[awesome gocui] - Go Console User Interface
* https://github.com/rgm3/gomandelbrot[gomandelbrot] - Mandelbrot!
* https://github.com/senorprogrammer/wtf[WTF]- Personal information dashboard for your terminal
* https://github.com/browsh-org/browsh[browsh] - A fully-modern text-based browser, rendering to TTY and browsers (https://www.youtube.com/watch?v=HZq86XfBoRo[video])
@ -48,6 +48,9 @@ Version 1.x remains available using the import `github.com/gdamore/tcell`.
* https://github.com/Bios-Marcel/memoryalike[memoryalike] - A game where you have to memorize runes and hit their respective keys
* https://github.com/gokcehan/lf[lf] - Terminal file manager
* https://github.com/bunyk/gokeybr[gokeybr] - program that helps to deliberately practice your typing.
* https://github.com/jbaramidze/gonano[gonano] - CLI test editor
* https://github.com/tmountain/uchess[uchess] - A UCI chess client for your terminal
* https://github.com/a-h/min[min] - A Gemini browser
== Pure Go Terminfo Database
@ -246,9 +249,7 @@ platforms (e.g. AIX) may need to be added. Pull requests are welcome!
=== Windows
Windows console mode applications are supported. Unfortunately _mintty_
and other _cygwin_ style applications are not supported, and are
unlikely to be supportable due to limitations in their design.
Windows console mode applications are supported.
Modern console applications like ConEmu and the Windows 10 terminal,
support all the good features (resize, mouse tracking, etc.)

View File

@ -1,6 +1,6 @@
// +build windows
// Copyright 2020 The TCell Authors
// Copyright 2021 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -53,6 +53,10 @@ type cScreen struct {
finiOnce sync.Once
mouseEnabled bool
wg sync.WaitGroup
stopQ chan struct{}
sync.Mutex
}
@ -176,7 +180,7 @@ func (s *cScreen) Init() error {
// ConEmu handling of colors and scrolling when in terminal
// mode is extremely problematic at the best. The color
// palette will scroll even though characters do not, when
// emiting stuff for the last character. In the future we
// emitting stuff for the last character. In the future we
// might change this to look at specific versions of ConEmu
// if they fix the bug.
if os.Getenv("ConEmuPID") != "" {
@ -189,16 +193,6 @@ func (s *cScreen) Init() error {
s.truecolor = true
}
cf, _, e := procCreateEvent.Call(
uintptr(0),
uintptr(1),
uintptr(0),
uintptr(0))
if cf == uintptr(0) {
return e
}
s.cancelflag = syscall.Handle(cf)
s.Lock()
s.curx = -1
@ -229,12 +223,9 @@ func (s *cScreen) Init() error {
s.setOutMode(0)
}
s.clearScreen(s.style)
s.hideCursor()
s.Unlock()
go s.scanInput()
return nil
return s.engage()
}
func (s *cScreen) CharacterSet() string {
@ -242,20 +233,36 @@ func (s *cScreen) CharacterSet() string {
return "UTF-16LE"
}
func (s *cScreen) EnableMouse() {
s.setInMode(modeResizeEn | modeMouseEn | modeExtndFlg)
func (s *cScreen) EnableMouse(...MouseFlags) {
s.Lock()
s.mouseEnabled = true
s.enableMouse(true)
s.Unlock()
}
func (s *cScreen) DisableMouse() {
s.setInMode(modeResizeEn | modeExtndFlg)
s.Lock()
s.mouseEnabled = false
s.enableMouse(false)
s.Unlock()
}
func (s *cScreen) enableMouse(on bool) {
if on {
s.setInMode(modeResizeEn | modeMouseEn | modeExtndFlg)
} else {
s.setInMode(modeResizeEn | modeExtndFlg)
}
}
// Windows lacks bracketed paste (for now)
func (s *cScreen) EnablePaste() {}
func (s *cScreen) DisablePaste() {}
func (s *cScreen) Fini() {
s.finiOnce.Do(s.finish)
s.disengage()
}
func (s *cScreen) finish() {
@ -271,8 +278,8 @@ func (s *cScreen) finish() {
s.setInMode(s.oimode)
s.setOutMode(s.oomode)
s.setBufferSize(int(s.oscreen.size.x), int(s.oscreen.size.y))
s.clearScreen(StyleDefault)
s.setCursorPos(0, 0)
s.clearScreen(StyleDefault, false)
s.setCursorPos(0, 0, false)
procSetConsoleTextAttribute.Call(
uintptr(s.out),
uintptr(s.mapStyle(StyleDefault)))
@ -286,6 +293,68 @@ func (s *cScreen) finish() {
syscall.Close(s.out)
}
func (s *cScreen) disengage() {
s.Lock()
stopQ := s.stopQ
if stopQ == nil {
s.Unlock()
return
}
s.stopQ = nil
procSetEvent.Call(uintptr(s.cancelflag))
close(stopQ)
s.Unlock()
s.wg.Wait()
s.setInMode(s.oimode)
s.setOutMode(s.oomode)
s.setBufferSize(int(s.oscreen.size.x), int(s.oscreen.size.y))
s.clearScreen(StyleDefault, false)
s.setCursorPos(0, 0, false)
procSetConsoleTextAttribute.Call(
uintptr(s.out),
uintptr(s.mapStyle(StyleDefault)))
}
func (s *cScreen) engage() error {
s.Lock()
defer s.Unlock()
if s.stopQ != nil {
return errors.New("already engaged")
}
s.stopQ = make(chan struct{})
cf, _, e := procCreateEvent.Call(
uintptr(0),
uintptr(1),
uintptr(0),
uintptr(0))
if cf == uintptr(0) {
return e
}
s.cancelflag = syscall.Handle(cf)
s.enableMouse(s.mouseEnabled)
if s.vten {
s.setOutMode(modeVtOutput | modeNoAutoNL | modeCookedOut)
} else {
s.setOutMode(0)
}
s.clearScreen(s.style, s.vten)
s.hideCursor()
s.cells.Invalidate()
s.hideCursor()
s.resize()
s.draw()
s.doCursor()
s.wg.Add(1)
go s.scanInput(s.stopQ)
return nil
}
func (s *cScreen) PostEventWait(ev Event) {
s.evch <- ev
}
@ -367,7 +436,7 @@ func (s *cScreen) doCursor() {
if x < 0 || y < 0 || x >= s.w || y >= s.h {
s.hideCursor()
} else {
s.setCursorPos(x, y)
s.setCursorPos(x, y, s.vten)
s.showCursor()
}
}
@ -691,10 +760,15 @@ func (s *cScreen) getConsoleInput() error {
return nil
}
func (s *cScreen) scanInput() {
func (s *cScreen) scanInput(stopQ chan struct{}) {
defer s.wg.Done()
for {
select {
case <-stopQ:
return
default:
}
if e := s.getConsoleInput(); e != nil {
close(s.scandone)
return
}
}
@ -843,7 +917,7 @@ func (s *cScreen) writeString(x, y int, style Style, ch []uint16) {
if len(ch) == 0 {
return
}
s.setCursorPos(x, y)
s.setCursorPos(x, y, s.vten)
if s.vten {
s.sendVtStyle(style)
@ -859,7 +933,7 @@ func (s *cScreen) draw() {
// allocate a scratch line bit enough for no combining chars.
// if you have combining characters, you may pay for extra allocs.
if s.clear {
s.clearScreen(s.style)
s.clearScreen(s.style, s.vten)
s.clear = false
s.cells.Invalidate()
}
@ -965,8 +1039,8 @@ func (s *cScreen) setCursorInfo(info *cursorInfo) {
}
func (s *cScreen) setCursorPos(x, y int) {
if s.vten {
func (s *cScreen) setCursorPos(x, y int, vtEnable bool) {
if vtEnable {
// Note that the string is Y first. Origin is 1,1.
s.emitVtString(fmt.Sprintf(vtCursorPos, y+1, x+1))
} else {
@ -1028,15 +1102,15 @@ func (s *cScreen) Fill(r rune, style Style) {
s.Unlock()
}
func (s *cScreen) clearScreen(style Style) {
if s.vten {
func (s *cScreen) clearScreen(style Style, vtEnable bool) {
if vtEnable {
s.sendVtStyle(style)
row := strings.Repeat(" ", s.w)
for y := 0; y < s.h; y++ {
s.setCursorPos(0, y)
s.setCursorPos(0, y, vtEnable)
s.emitVtString(row)
}
s.setCursorPos(0, 0)
s.setCursorPos(0, 0, vtEnable)
} else {
pos := coord{0, 0}
@ -1185,3 +1259,12 @@ func (s *cScreen) Beep() error {
}
return nil
}
func (s *cScreen) Suspend() error {
s.disengage()
return nil
}
func (s *cScreen) Resume() error {
return s.engage()
}

View File

@ -5,7 +5,8 @@ go 1.12
require (
github.com/gdamore/encoding v1.0.0
github.com/lucasb-eyer/go-colorful v1.0.3
github.com/mattn/go-runewidth v0.0.7
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756
github.com/mattn/go-runewidth v0.0.10
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf
golang.org/x/text v0.3.0
)

View File

@ -2,9 +2,15 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

50
vendor/github.com/gdamore/tcell/v2/nonblock_bsd.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2021 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.
// +build darwin dragonfly freebsd netbsd openbsd
package tcell
import (
"os"
"syscall"
"golang.org/x/sys/unix"
)
// BSD systems use TIOC style ioctls.
// nonBlocking changes VMIN to 0, and VTIME to 1. This basically ensures that
// we can wake up the input loop. We only want to do this if we are going to interrupt
// that loop. Normally we use VMIN 1 and VTIME 0, which ensures we pick up bytes when
// they come but don't spin burning cycles.
func (t *tScreen) nonBlocking(on bool) {
fd := int(os.Stdin.Fd())
tio, err := unix.IoctlGetTermios(fd, unix.TIOCGETA)
if err != nil {
return
}
if on {
tio.Cc[unix.VMIN] = 0
tio.Cc[unix.VTIME] = 0
} else {
// block for any output
tio.Cc[unix.VTIME] = 0
tio.Cc[unix.VMIN] = 1
}
_ = syscall.SetNonblock(fd, on)
// We want to set this *right now*.
_ = unix.IoctlSetTermios(fd, unix.TIOCSETA, tio)
}

21
vendor/github.com/gdamore/tcell/v2/nonblock_stub.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
// Copyright 2021 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.
// +build plan9 windows js
package tcell
func (t *tScreen) nonBlocking(on bool) error {
return nil
}

52
vendor/github.com/gdamore/tcell/v2/nonblock_unix.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2021 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.
// +build linux aix zos solaris
package tcell
import (
"os"
"syscall"
"golang.org/x/sys/unix"
)
// NB: We might someday wish to move Windows to this model. However,
// that would probably mean sacrificing some of the richer key reporting
// that we can obtain with the console API present on Windows.
// nonBlocking changes VMIN to 0, and VTIME to 1. This basically ensures that
// we can wake up the input loop. We only want to do this if we are going to interrupt
// that loop. Normally we use VMIN 1 and VTIME 0, which ensures we pick up bytes when
// they come but don't spin burning cycles.
func (t *tScreen) nonBlocking(on bool) {
fd := int(os.Stdin.Fd())
tio, err := unix.IoctlGetTermios(fd, unix.TCGETS)
if err != nil {
return
}
if on {
tio.Cc[unix.VMIN] = 0
tio.Cc[unix.VTIME] = 0
} else {
// block for any output
tio.Cc[unix.VTIME] = 0
tio.Cc[unix.VMIN] = 1
}
_ = syscall.SetNonblock(fd, on)
// We want to set this *right now*.
_ = unix.IoctlSetTermios(fd, unix.TCSETS, tio)
}

View File

@ -1,4 +1,4 @@
// Copyright 2019 The TCell Authors
// Copyright 2021 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -16,7 +16,7 @@ package tcell
// Screen represents the physical (or emulated) screen.
// This can be a terminal window or a physical console. Platforms implement
// this differerently.
// this differently.
type Screen interface {
// Init initializes the screen for use.
Init() error
@ -88,6 +88,9 @@ type Screen interface {
// is dropped, and ErrEventQFull is returned.
PostEvent(ev Event) error
// Deprecated: PostEventWait is unsafe, and will be removed
// in the future.
//
// PostEventWait is like PostEvent, but if the queue is full, it
// blocks until there is space in the queue, making delivery
// reliable. However, it is VERY important that this function
@ -99,7 +102,9 @@ type Screen interface {
PostEventWait(ev Event)
// EnableMouse enables the mouse. (If your terminal supports it.)
EnableMouse()
// If no flags are specified, then all events are reported, if the
// terminal supports them.
EnableMouse(...MouseFlags)
// DisableMouse disables the mouse.
DisableMouse()
@ -200,6 +205,14 @@ type Screen interface {
// runes) is always true.
HasKey(Key) bool
// Suspend pauses input and output processing. It also restores the
// terminal settings to what they were when the application started.
// This can be used to, for example, run a sub-shell.
Suspend() error
// Resume resumes after Suspend().
Resume() error
// Beep attempts to sound an OS-dependent audible alert and returns an error
// when unsuccessful.
Beep() error
@ -217,3 +230,13 @@ func NewScreen() (Screen, error) {
return nil, e
}
}
// MouseFlags are options to modify the handling of mouse events.
// Actual events can be or'd together.
type MouseFlags int
const (
MouseButtonEvents = MouseFlags(1) // Click events only
MouseDragEvents = MouseFlags(2) // Click-drag events (includes button events)
MouseMotionEvents = MouseFlags(4) // All mouse events (includes click and drag events)
)

View File

@ -1,4 +1,4 @@
// Copyright 2020 The TCell Authors
// Copyright 2021 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -314,7 +314,7 @@ func (s *simscreen) draw() {
s.showCursor()
}
func (s *simscreen) EnableMouse() {
func (s *simscreen) EnableMouse(...MouseFlags) {
s.mouse = true
}
@ -520,3 +520,11 @@ func (s *simscreen) HasKey(Key) bool {
func (s *simscreen) Beep() error {
return nil
}
func (s *simscreen) Suspend() error {
return nil
}
func (s *simscreen) Resume() error {
return nil
}

View File

@ -36,7 +36,6 @@ func init() {
ExitAcs: "\x1b(B",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[<",
MouseMode: "\x1b[?1006;1000%?%p1%{1}%=%th%el%;",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -1,4 +1,4 @@
// Copyright 2020 The TCell Authors
// Copyright 2021 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -394,26 +394,6 @@ func LoadTerminfo(name string) (*terminfo.Terminfo, string, error) {
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
// is an extension. The escapedape codes are documented in the XTerm
// manual, and all terminals that have kmous are expected to
// use these same codes, unless explicitly configured otherwise
// vi XM. Note that in any event, we only known how to parse either
// x11 or SGR mouse events -- if your terminal doesn't support one
// of these two forms, you maybe out of luck.
t.MouseMode = tc.getstr("XM")
if t.Mouse != "" && t.MouseMode == "" {
// we anticipate that all xterm mouse tracking compatible
// terminals understand mouse tracking (1000), but we hope
// that those that don't understand any-event tracking (1003)
// will at least ignore it. Likewise we hope that terminals
// that don't understand SGR reporting (1006) just ignore it.
t.MouseMode = "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;" +
"\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c"
}
// We only support colors in ANSI 8 or 256 color mode.
if t.Colors < 8 || t.SetFg == "" {
t.Colors = 0

View File

@ -36,7 +36,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -97,7 +96,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -36,7 +36,6 @@ func init() {
EnableAcs: "\x1b)0",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[<",
MouseMode: "\x1b[?1006;1000%?%p1%{1}%=%th%el%;",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -97,7 +96,6 @@ func init() {
EnableAcs: "\x1b)0",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[<",
MouseMode: "\x1b[?1006;1000%?%p1%{1}%=%th%el%;",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -31,7 +31,6 @@ func init() {
EnterAcs: "\x1b(0",
ExitAcs: "\x1b(B",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -30,7 +30,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -35,7 +35,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b(B\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -139,7 +138,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b(B\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -243,7 +241,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b(B\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -346,7 +343,6 @@ func init() {
EnterAcs: "\x1b(0",
ExitAcs: "\x1b(B",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -426,7 +422,6 @@ func init() {
EnterAcs: "\x1b(0",
ExitAcs: "\x1b(B",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -36,7 +36,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b(B\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1bM",
@ -96,7 +95,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b(B\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1bM",

View File

@ -37,7 +37,6 @@ func init() {
EnableAcs: "\x1b)0",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -101,7 +100,6 @@ func init() {
EnableAcs: "\x1b)0",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -33,7 +33,6 @@ func init() {
EnterAcs: "\x1b(0",
ExitAcs: "\x1b(B",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -38,7 +38,6 @@ func init() {
EnableAcs: "\x1b(B\x1b)0",
StrikeThrough: "\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1bM",
@ -101,7 +100,6 @@ func init() {
EnableAcs: "\x1b(B\x1b)0",
StrikeThrough: "\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1bM",

View File

@ -150,7 +150,6 @@ type Terminfo struct {
KeyPrint string // kprt
KeyCancel string // kcan
Mouse string // kmous
MouseMode string // XM
AltChars string // acsc
EnterAcs string // smacs
ExitAcs string // rmacs

View File

@ -34,7 +34,6 @@ func init() {
ExitAcs: "\x0f",
EnableAcs: "\x1b)0",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -37,7 +37,6 @@ func init() {
ExitAcs: "\x1b(B",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -98,7 +97,6 @@ func init() {
ExitAcs: "\x1b(B",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
@ -159,7 +157,6 @@ func init() {
ExitAcs: "\x1b(B",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -35,7 +35,6 @@ func init() {
ExitAcs: "\x1b(B",
StrikeThrough:"\x1b[9m",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -34,7 +34,6 @@ func init() {
EnterAcs: "\x1b(0",
ExitAcs: "\x1b(B",
Mouse: "\x1b[M",
MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",

View File

@ -1,4 +1,4 @@
// Copyright 2020 The TCell Authors
// Copyright 2021 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -24,6 +24,7 @@ import (
"time"
"unicode/utf8"
"golang.org/x/term"
"golang.org/x/text/transform"
"github.com/gdamore/tcell/v2/terminfo"
@ -89,7 +90,6 @@ type tScreen struct {
evch chan Event
sigwinch chan os.Signal
quit chan struct{}
indoneq chan struct{}
keyexist map[Key]bool
keycodes map[string]*tKeyCode
keychan chan []byte
@ -101,7 +101,6 @@ type tScreen struct {
clear bool
cursorx int
cursory int
tiosp *termiosPrivate
wasbtn bool
acs map[rune]string
charset string
@ -116,13 +115,21 @@ type tScreen struct {
finiOnce sync.Once
enablePaste string
disablePaste string
saved *term.State
stopQ chan struct{}
wg sync.WaitGroup
mouseFlags MouseFlags
pasteEnabled bool
sync.Mutex
}
func (t *tScreen) Init() error {
if e := t.initialize(); e != nil {
return e
}
t.evch = make(chan Event, 10)
t.indoneq = make(chan struct{})
t.keychan = make(chan []byte, 10)
t.keytimer = time.NewTimer(time.Millisecond * 50)
t.charset = "UTF-8"
@ -145,10 +152,6 @@ func (t *tScreen) Init() error {
if i, _ := strconv.Atoi(os.Getenv("COLUMNS")); i != 0 {
w = i
}
if e := t.termioInit(); e != nil {
return e
}
if t.ti.SetFgBgRGB != "" || t.ti.SetFgRGB != "" || t.ti.SetBgRGB != "" {
t.truecolor = true
}
@ -182,8 +185,9 @@ func (t *tScreen) Init() error {
t.resize()
t.Unlock()
go t.mainLoop()
go t.inputLoop()
if err := t.engage(); err != nil {
return err
}
return nil
}
@ -291,7 +295,7 @@ func (t *tScreen) prepareBracketedPaste() {
t.disablePaste = t.ti.DisablePaste
t.prepareKey(keyPasteStart, t.ti.PasteStart)
t.prepareKey(keyPasteEnd, t.ti.PasteEnd)
} else if t.ti.MouseMode != "" {
} else if t.ti.Mouse != "" {
t.enablePaste = "\x1b[?2004h"
t.disablePaste = "\x1b[?2004l"
t.prepareKey(keyPasteStart, "\x1b[200~")
@ -470,31 +474,8 @@ func (t *tScreen) Fini() {
}
func (t *tScreen) finish() {
t.Lock()
defer t.Unlock()
ti := t.ti
t.cells.Resize(0, 0)
t.TPuts(ti.ShowCursor)
t.TPuts(ti.AttrOff)
t.TPuts(ti.Clear)
t.TPuts(ti.ExitCA)
t.TPuts(ti.ExitKeypad)
t.TPuts(ti.TParm(ti.MouseMode, 0))
t.TPuts(t.disablePaste)
t.curstyle = styleInvalid
t.clear = false
t.fini = true
select {
case <-t.quit:
// do nothing, already closed
default:
close(t.quit)
}
t.termioFini()
close(t.quit)
t.finalize()
}
func (t *tScreen) SetStyle(style Style) {
@ -834,24 +815,71 @@ func (t *tScreen) draw() {
_, _ = t.buf.WriteTo(t.out)
}
func (t *tScreen) EnableMouse() {
func (t *tScreen) EnableMouse(flags ...MouseFlags) {
var f MouseFlags
flagsPresent := false
for _, flag := range flags {
f |= flag
flagsPresent = true
}
if !flagsPresent {
f = MouseMotionEvents
}
t.Lock()
t.mouseFlags = f
t.enableMouse(f)
t.Unlock()
}
func (t *tScreen) enableMouse(f MouseFlags) {
// Rather than using terminfo to find mouse escape sequences, we rely on the fact that
// pretty much *every* terminal that supports mouse tracking follows the
// XTerm standards (the modern ones).
if len(t.mouse) != 0 {
t.TPuts(t.ti.TParm(t.ti.MouseMode, 1))
// start by disabling all tracking.
t.TPuts("\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l")
if f&MouseMotionEvents != 0 {
t.TPuts("\x1b[?1003h\x1b[?1006h")
} else if f&MouseDragEvents != 0 {
t.TPuts("\x1b[?1002h\x1b[?1006h")
} else if f&MouseButtonEvents != 0 {
t.TPuts("\x1b[?1000h\x1b[?1006h")
}
}
}
func (t *tScreen) DisableMouse() {
if len(t.mouse) != 0 {
t.TPuts(t.ti.TParm(t.ti.MouseMode, 0))
}
t.Lock()
t.mouseFlags = 0
t.enableMouse(0)
t.Unlock()
}
func (t *tScreen) EnablePaste() {
t.TPuts(t.enablePaste)
t.Lock()
t.pasteEnabled = true
t.enablePasting(true)
t.Unlock()
}
func (t *tScreen) DisablePaste() {
t.TPuts(t.disablePaste)
t.Lock()
t.pasteEnabled = false
t.enablePasting(false)
t.Unlock()
}
func (t *tScreen) enablePasting(on bool) {
var s string
if on {
s = t.enablePaste
} else {
s = t.disablePaste
}
if s != "" {
t.TPuts(s)
}
}
func (t *tScreen) Size() (int, int) {
@ -1405,12 +1433,14 @@ func (t *tScreen) collectEventsFromInput(buf *bytes.Buffer, expire bool) []Event
return res
}
func (t *tScreen) mainLoop() {
func (t *tScreen) mainLoop(stopQ chan struct{}) {
defer t.wg.Done()
buf := &bytes.Buffer{}
for {
select {
case <-stopQ:
return
case <-t.quit:
close(t.indoneq)
return
case <-t.sigwinch:
t.Lock()
@ -1458,19 +1488,26 @@ func (t *tScreen) mainLoop() {
}
}
func (t *tScreen) inputLoop() {
func (t *tScreen) inputLoop(stopQ chan struct{}) {
defer t.wg.Done()
for {
select {
case <-stopQ:
return
default:
}
chunk := make([]byte, 128)
n, e := t.in.Read(chunk)
switch e {
case io.EOF:
case nil:
default:
_ = t.PostEvent(NewEventError(e))
return
}
t.keychan <- chunk[:n]
if n > 0 {
t.keychan <- chunk[:n]
}
}
}
@ -1542,3 +1579,13 @@ func (t *tScreen) HasKey(k Key) bool {
}
func (t *tScreen) Resize(int, int, int, int) {}
func (t *tScreen) Suspend() error {
t.disengage()
return nil
}
func (t *tScreen) Resume() error {
return t.engage()
}

View File

@ -1,121 +0,0 @@
// +build freebsd netbsd openbsd dragonfly
// Copyright 2019 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 (
"os"
"os/signal"
"syscall"
"unsafe"
)
type termiosPrivate syscall.Termios
func (t *tScreen) termioInit() error {
var e error
var newtios termiosPrivate
var fd uintptr
var tios uintptr
var ioc uintptr
t.tiosp = &termiosPrivate{}
if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
goto failed
}
if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil {
goto failed
}
tios = uintptr(unsafe.Pointer(t.tiosp))
ioc = uintptr(syscall.TIOCGETA)
fd = uintptr(t.out.Fd())
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
e = e1
goto failed
}
newtios = *t.tiosp
newtios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK |
syscall.ISTRIP | syscall.INLCR | syscall.IGNCR |
syscall.ICRNL | syscall.IXON
newtios.Oflag &^= syscall.OPOST
newtios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON |
syscall.ISIG | syscall.IEXTEN
newtios.Cflag &^= syscall.CSIZE | syscall.PARENB
newtios.Cflag |= syscall.CS8
tios = uintptr(unsafe.Pointer(&newtios))
ioc = uintptr(syscall.TIOCSETA)
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
e = e1
goto failed
}
signal.Notify(t.sigwinch, syscall.SIGWINCH)
if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 {
t.cells.Resize(w, h)
}
return nil
failed:
if t.in != nil {
t.in.Close()
}
if t.out != nil {
t.out.Close()
}
return e
}
func (t *tScreen) termioFini() {
signal.Stop(t.sigwinch)
<-t.indoneq
if t.out != nil {
fd := uintptr(t.out.Fd())
ioc := uintptr(syscall.TIOCSETAF)
tios := uintptr(unsafe.Pointer(t.tiosp))
syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0)
t.out.Close()
}
if t.in != nil {
t.in.Close()
}
}
func (t *tScreen) getWinSize() (int, int, error) {
fd := uintptr(t.out.Fd())
dim := [4]uint16{}
dimp := uintptr(unsafe.Pointer(&dim))
ioc := uintptr(syscall.TIOCGWINSZ)
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL,
fd, ioc, dimp, 0, 0, 0); err != 0 {
return -1, -1, err
}
return int(dim[1]), int(dim[0]), nil
}
func (t *tScreen) Beep() error {
t.writeString(string(byte(7)))
return nil
}

View File

@ -1,142 +0,0 @@
// +build darwin
// Copyright 2019 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
// The Darwin system is *almost* a real BSD system, but it suffers from
// a brain damaged TTY driver. This TTY driver does not actually
// wake up in poll() or similar calls, which means that we cannot reliably
// shut down the terminal without resorting to obscene custom C code
// and a dedicated poller thread.
//
// So instead, we do a best effort, and simply try to do the close in the
// background. Probably this will cause a leak of two goroutines and
// maybe also the file descriptor, meaning that applications on Darwin
// can't reinitialize the screen, but that's probably a very rare behavior,
// and accepting that is the best of some very poor alternative options.
//
// Maybe someday Apple will fix there tty driver, but its been broken for
// a long time (probably forever) so holding one's breath is contraindicated.
import (
"os"
"os/signal"
"syscall"
"unsafe"
)
type termiosPrivate syscall.Termios
func (t *tScreen) termioInit() error {
var e error
var newtios termiosPrivate
var fd uintptr
var tios uintptr
var ioc uintptr
t.tiosp = &termiosPrivate{}
if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
goto failed
}
if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil {
goto failed
}
tios = uintptr(unsafe.Pointer(t.tiosp))
ioc = uintptr(syscall.TIOCGETA)
fd = uintptr(t.out.Fd())
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
e = e1
goto failed
}
newtios = *t.tiosp
newtios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK |
syscall.ISTRIP | syscall.INLCR | syscall.IGNCR |
syscall.ICRNL | syscall.IXON
newtios.Oflag &^= syscall.OPOST
newtios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON |
syscall.ISIG | syscall.IEXTEN
newtios.Cflag &^= syscall.CSIZE | syscall.PARENB
newtios.Cflag |= syscall.CS8
tios = uintptr(unsafe.Pointer(&newtios))
ioc = uintptr(syscall.TIOCSETA)
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
e = e1
goto failed
}
signal.Notify(t.sigwinch, syscall.SIGWINCH)
if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 {
t.cells.Resize(w, h)
}
return nil
failed:
if t.in != nil {
t.in.Close()
}
if t.out != nil {
t.out.Close()
}
return e
}
func (t *tScreen) termioFini() {
signal.Stop(t.sigwinch)
<-t.indoneq
if t.out != nil {
fd := uintptr(t.out.Fd())
ioc := uintptr(syscall.TIOCSETAF)
tios := uintptr(unsafe.Pointer(t.tiosp))
syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0)
t.out.Close()
}
// See above -- we background this call which might help, but
// really the tty is probably open.
go func() {
if t.in != nil {
t.in.Close()
}
}()
}
func (t *tScreen) getWinSize() (int, int, error) {
fd := uintptr(t.out.Fd())
dim := [4]uint16{}
dimp := uintptr(unsafe.Pointer(&dim))
ioc := uintptr(syscall.TIOCGWINSZ)
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL,
fd, ioc, dimp, 0, 0, 0); err != 0 {
return -1, -1, err
}
return int(dim[1]), int(dim[0]), nil
}
func (t *tScreen) Beep() error {
t.writeString(string(byte(7)))
return nil
}

View File

@ -1,147 +0,0 @@
// +build linux
// Copyright 2019 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 (
"os"
"os/signal"
"strconv"
"syscall"
"golang.org/x/sys/unix"
)
type termiosPrivate struct {
tio *unix.Termios
}
func (t *tScreen) termioInit() error {
var e error
var raw *unix.Termios
var tio *unix.Termios
if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
goto failed
}
if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil {
goto failed
}
tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
if e != nil {
goto failed
}
t.tiosp = &termiosPrivate{tio: tio}
// make a local copy, to make it raw
raw = &unix.Termios{
Cflag: tio.Cflag,
Oflag: tio.Oflag,
Iflag: tio.Iflag,
Lflag: tio.Lflag,
Cc: tio.Cc,
}
raw.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP |
unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
raw.Oflag &^= unix.OPOST
raw.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG |
unix.IEXTEN)
raw.Cflag &^= (unix.CSIZE | unix.PARENB)
raw.Cflag |= unix.CS8
// This is setup for blocking reads. In the past we attempted to
// use non-blocking reads, but now a separate input loop and timer
// copes with the problems we had on some systems (BSD/Darwin)
// where close hung forever.
raw.Cc[unix.VMIN] = 1
raw.Cc[unix.VTIME] = 0
e = unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETS, raw)
if e != nil {
goto failed
}
signal.Notify(t.sigwinch, syscall.SIGWINCH)
if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 {
t.cells.Resize(w, h)
}
return nil
failed:
if t.in != nil {
t.in.Close()
}
if t.out != nil {
t.out.Close()
}
return e
}
func (t *tScreen) termioFini() {
signal.Stop(t.sigwinch)
<-t.indoneq
if t.out != nil && t.tiosp != nil {
unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETSF, t.tiosp.tio)
t.out.Close()
}
if t.in != nil {
t.in.Close()
}
}
func (t *tScreen) getWinSize() (int, int, error) {
wsz, err := unix.IoctlGetWinsize(int(t.out.Fd()), unix.TIOCGWINSZ)
if err != nil {
return -1, -1, err
}
cols := int(wsz.Col)
rows := int(wsz.Row)
if cols == 0 {
colsEnv := os.Getenv("COLUMNS")
if colsEnv != "" {
if cols, err = strconv.Atoi(colsEnv); err != nil {
return -1, -1, err
}
} else {
cols = t.ti.Columns
}
}
if rows == 0 {
rowsEnv := os.Getenv("LINES")
if rowsEnv != "" {
if rows, err = strconv.Atoi(rowsEnv); err != nil {
return -1, -1, err
}
} else {
rows = t.ti.Lines
}
}
return cols, rows, nil
}
func (t *tScreen) Beep() error {
t.writeString(string(byte(7)))
return nil
}

View File

@ -1,122 +0,0 @@
// +build solaris illumos
// 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 (
"os"
"os/signal"
"syscall"
"golang.org/x/sys/unix"
)
type termiosPrivate struct {
tio *unix.Termios
}
func (t *tScreen) termioInit() error {
var e error
var raw *unix.Termios
var tio *unix.Termios
if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
goto failed
}
if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil {
goto failed
}
tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
if e != nil {
goto failed
}
t.tiosp = &termiosPrivate{tio: tio}
// make a local copy, to make it raw
raw = &unix.Termios{
Cflag: tio.Cflag,
Oflag: tio.Oflag,
Iflag: tio.Iflag,
Lflag: tio.Lflag,
Cc: tio.Cc,
}
raw.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.INLCR |
unix.IGNCR | unix.ICRNL | unix.IXON)
raw.Oflag &^= unix.OPOST
raw.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
raw.Cflag &^= (unix.CSIZE | unix.PARENB)
raw.Cflag |= unix.CS8
// This is setup for blocking reads. In the past we attempted to
// use non-blocking reads, but now a separate input loop and timer
// copes with the problems we had on some systems (BSD/Darwin)
// where close hung forever.
raw.Cc[unix.VMIN] = 1
raw.Cc[unix.VTIME] = 0
e = unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETS, raw)
if e != nil {
goto failed
}
signal.Notify(t.sigwinch, syscall.SIGWINCH)
if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 {
t.cells.Resize(w, h)
}
return nil
failed:
if t.in != nil {
t.in.Close()
}
if t.out != nil {
t.out.Close()
}
return e
}
func (t *tScreen) termioFini() {
signal.Stop(t.sigwinch)
<-t.indoneq
if t.out != nil && t.tiosp != nil {
unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETSF, t.tiosp.tio)
t.out.Close()
}
if t.in != nil {
t.in.Close()
}
}
func (t *tScreen) getWinSize() (int, int, error) {
wsz, err := unix.IoctlGetWinsize(int(t.out.Fd()), unix.TIOCGWINSZ)
if err != nil {
return -1, -1, err
}
return int(wsz.Col), int(wsz.Row), nil
}
func (t *tScreen) Beep() error {
t.writeString(string(byte(7)))
return nil
}

View File

@ -1,6 +1,6 @@
// +build nacl plan9
// +build js plan9 windows
// Copyright 2015 The TCell Authors
// Copyright 2021 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -16,15 +16,22 @@
package tcell
// This stub file is for systems that have no termios.
// NB: We might someday wish to move Windows to this model. However,
// that would probably mean sacrificing some of the richer key reporting
// that we can obtain with the console API present on Windows.
type termiosPrivate struct{}
func (t *tScreen) termioInit() error {
func (t *tScreen) engage() error {
return ErrNoScreen
}
func (t *tScreen) termioFini() {
func (t *tScreen) disengage() {
}
func (t *tScreen) initialize() error {
return ErrNoScreen
}
func (t *tScreen) finalize() {
}
func (t *tScreen) getWinSize() (int, int, error) {

123
vendor/github.com/gdamore/tcell/v2/tscreen_unix.go generated vendored Normal file
View File

@ -0,0 +1,123 @@
// Copyright 2021 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.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
package tcell
import (
"errors"
"os"
"os/signal"
"syscall"
"golang.org/x/term"
)
// engage is used to place the terminal in raw mode and establish screen size, etc.
// Thing of this is as tcell "engaging" the clutch, as it's going to be driving the
// terminal interface.
func (t *tScreen) engage() error {
t.Lock()
defer t.Unlock()
if t.stopQ != nil {
return errors.New("already engaged")
}
if _, err := term.MakeRaw(int(t.in.Fd())); err != nil {
return err
}
if w, h, err := term.GetSize(int(t.in.Fd())); err == nil && w != 0 && h != 0 {
t.cells.Resize(w, h)
}
stopQ := make(chan struct{})
t.stopQ = stopQ
t.nonBlocking(false)
t.enableMouse(t.mouseFlags)
t.enablePasting(t.pasteEnabled)
signal.Notify(t.sigwinch, syscall.SIGWINCH)
t.wg.Add(2)
go t.inputLoop(stopQ)
go t.mainLoop(stopQ)
return nil
}
// disengage is used to release the terminal back to support from the caller.
// Think of this as tcell disengaging the clutch, so that another application
// can take over the terminal interface. This restores the TTY mode that was
// present when the application was first started.
func (t *tScreen) disengage() {
t.Lock()
t.nonBlocking(true)
stopQ := t.stopQ
t.stopQ = nil
close(stopQ)
t.Unlock()
// wait for everything to shut down
t.wg.Wait()
signal.Stop(t.sigwinch)
// put back normal blocking mode
t.nonBlocking(false)
// shutdown the screen and disable special modes (e.g. mouse and bracketed paste)
ti := t.ti
t.cells.Resize(0, 0)
t.TPuts(ti.ShowCursor)
t.TPuts(ti.AttrOff)
t.TPuts(ti.Clear)
t.TPuts(ti.ExitCA)
t.TPuts(ti.ExitKeypad)
t.enableMouse(0)
t.enablePasting(false)
// restore the termios that we were started with
_ = term.Restore(int(t.in.Fd()), t.saved)
}
// initialize is used at application startup, and sets up the initial values
// including file descriptors used for terminals and saving the initial state
// so that it can be restored when the application terminates.
func (t *tScreen) initialize() error {
var err error
t.out = os.Stdout
t.in = os.Stdin
t.saved, err = term.GetState(int(os.Stdin.Fd()))
if err != nil {
return err
}
return nil
}
// finalize is used to at application shutdown, and restores the terminal
// to it's initial state. It should not be called more than once.
func (t *tScreen) finalize() {
t.disengage()
}
// getWinSize is called to obtain the terminal dimensions.
func (t *tScreen) getWinSize() (int, int, error) {
return term.GetSize(int(t.in.Fd()))
}
// Beep emits a beep to the terminal.
func (t *tScreen) Beep() error {
t.writeString(string(byte(7)))
return nil
}

View File

@ -1,44 +0,0 @@
// +build windows
// Copyright 2015 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
// On Windows we don't have support for termios. We probably could, and
// may should, in a cygwin type environment. Its not clear how to make
// this all work nicely with both cygwin and Windows console, so we
// decline to do so here.
func (t *tScreen) termioInit() error {
return ErrNoScreen
}
func (t *tScreen) termioFini() {
return
}
func (t *tScreen) getWinSize() (int, int, error) {
return 0, 0, ErrNoScreen
}
func (t *tScreen) getCharset() string {
return "UTF-16LE"
}
func (t *tScreen) Beep() error {
return ErrNoScreen
}
type termiosPrivate struct{}

View File

@ -12,8 +12,14 @@ var (
// EastAsianWidth will be set true if the current locale is CJK
EastAsianWidth bool
// StrictEmojiNeutral should be set false if handle broken fonts
StrictEmojiNeutral bool = true
// DefaultCondition is a condition in current locale
DefaultCondition = &Condition{}
DefaultCondition = &Condition{
EastAsianWidth: false,
StrictEmojiNeutral: true,
}
)
func init() {
@ -83,26 +89,52 @@ var nonprint = table{
// Condition have flag EastAsianWidth whether the current locale is CJK or not.
type Condition struct {
EastAsianWidth bool
EastAsianWidth bool
StrictEmojiNeutral bool
}
// NewCondition return new instance of Condition which is current locale.
func NewCondition() *Condition {
return &Condition{
EastAsianWidth: EastAsianWidth,
EastAsianWidth: EastAsianWidth,
StrictEmojiNeutral: StrictEmojiNeutral,
}
}
// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func (c *Condition) RuneWidth(r rune) int {
switch {
case r < 0 || r > 0x10FFFF || inTables(r, nonprint, combining, notassigned):
return 0
case (c.EastAsianWidth && IsAmbiguousWidth(r)) || inTables(r, doublewidth):
return 2
default:
return 1
// optimized version, verified by TestRuneWidthChecksums()
if !c.EastAsianWidth {
switch {
case r < 0x20 || r > 0x10FFFF:
return 0
case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint
return 0
case r < 0x300:
return 1
case inTable(r, narrow):
return 1
case inTables(r, nonprint, combining):
return 0
case inTable(r, doublewidth):
return 2
default:
return 1
}
} else {
switch {
case r < 0 || r > 0x10FFFF || inTables(r, nonprint, combining):
return 0
case inTable(r, narrow):
return 1
case inTables(r, ambiguous, doublewidth):
return 2
case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
return 2
default:
return 1
}
}
}

View File

@ -124,8 +124,10 @@ var ambiguous = table{
{0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF},
{0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
}
var notassigned = table{
{0x27E6, 0x27ED}, {0x2985, 0x2986},
var narrow = table{
{0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6},
{0x00AC, 0x00AC}, {0x00AF, 0x00AF}, {0x27E6, 0x27ED},
{0x2985, 0x2986},
}
var neutral = table{