1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-05-27 23:08:02 +02:00

build: bump tcell version

This commit is contained in:
Ryooooooga 2023-02-21 21:53:55 +09:00
parent 526c9dea9b
commit 90772e1eaa
No known key found for this signature in database
GPG Key ID: 07CF200DFCC20C25
18 changed files with 870 additions and 23 deletions

5
go.mod
View File

@ -11,7 +11,7 @@ require (
github.com/creack/pty v1.1.11 github.com/creack/pty v1.1.11
github.com/fsmiamoto/git-todo-parser v0.0.2 github.com/fsmiamoto/git-todo-parser v0.0.2
github.com/fsnotify/fsnotify v1.4.7 github.com/fsnotify/fsnotify v1.4.7
github.com/gdamore/tcell/v2 v2.5.4 github.com/gdamore/tcell/v2 v2.6.0
github.com/go-errors/errors v1.4.2 github.com/go-errors/errors v1.4.2
github.com/gookit/color v1.4.2 github.com/gookit/color v1.4.2
github.com/imdario/mergo v0.3.11 github.com/imdario/mergo v0.3.11
@ -46,6 +46,7 @@ require (
github.com/emirpasic/gods v1.12.0 // indirect github.com/emirpasic/gods v1.12.0 // indirect
github.com/fatih/color v1.9.0 // indirect github.com/fatih/color v1.9.0 // indirect
github.com/gdamore/encoding v1.0.0 // indirect github.com/gdamore/encoding v1.0.0 // indirect
github.com/gdamore/tcell v1.4.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.0.0 // indirect github.com/go-git/go-billy/v5 v5.0.0 // indirect
github.com/go-logfmt/logfmt v0.5.0 // indirect github.com/go-logfmt/logfmt v0.5.0 // indirect
@ -62,7 +63,7 @@ require (
github.com/onsi/ginkgo v1.10.3 // indirect github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect github.com/onsi/gomega v1.7.1 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/rivo/uniseg v0.4.3 // indirect github.com/rivo/uniseg v0.4.4 // indirect
github.com/sergi/go-diff v1.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect
github.com/xanzy/ssh-agent v0.2.1 // indirect github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect

8
go.sum
View File

@ -34,9 +34,13 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
github.com/gdamore/tcell/v2 v2.5.4 h1:TGU4tSjD3sCL788vFNeJnTdzpNKIw1H5dgLnJRQVv/k= github.com/gdamore/tcell/v2 v2.5.4 h1:TGU4tSjD3sCL788vFNeJnTdzpNKIw1H5dgLnJRQVv/k=
github.com/gdamore/tcell/v2 v2.5.4/go.mod h1:dZgRy5v4iMobMEcWNYBtREnDZAT9DYmfqIkrgEMxLyw= github.com/gdamore/tcell/v2 v2.5.4/go.mod h1:dZgRy5v4iMobMEcWNYBtREnDZAT9DYmfqIkrgEMxLyw=
github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg=
github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
@ -113,6 +117,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@ -138,6 +143,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/samber/lo v1.31.0 h1:Sfa+/064Tdo4SvlohQUQzBhgSer9v/coGvKQI/XLWAM= github.com/samber/lo v1.31.0 h1:Sfa+/064Tdo4SvlohQUQzBhgSer9v/coGvKQI/XLWAM=
@ -196,6 +203,7 @@ golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

61
vendor/github.com/gdamore/tcell/v2/README-wasm.md generated vendored Normal file
View File

@ -0,0 +1,61 @@
# WASM for _Tcell_
You can build _Tcell_ project into a webpage by compiling it slightly differently. This will result in a _Tcell_ project you can embed into another html page, or use as a standalone page.
## Building your project
WASM needs special build flags in order to work. You can build it by executing
```sh
GOOS=js GOARCH=wasm go build -o yourfile.wasm
```
## Additional files
You also need 5 other files in the same directory as the wasm. Four (`tcell.html`, `tcell.js`, `termstyle.css`, and `beep.wav`) are provided in the `webfiles` directory. The last one, `wasm_exec.js`, can be copied from GOROOT into the current directory by executing
```sh
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" ./
```
In `tcell.js`, you also need to change the constant
```js
const wasmFilePath = "yourfile.wasm"
```
to the file you outputed to when building.
## Displaying your project
### Standalone
You can see the project (with an white background around the terminal) by serving the directory. You can do this using any framework, including another golang project:
```golang
// server.go
package main
import (
"log"
"net/http"
)
func main() {
log.Fatal(http.ListenAndServe(":8080",
http.FileServer(http.Dir("/path/to/dir/to/serve")),
))
}
```
To see the webpage with this example, you can type in `localhost:8080/tcell.html` into your browser while `server.go` is running.
### Embedding
It is recomended to use an iframe if you want to embed the app into a webpage:
```html
<iframe src="tcell.html" title="Tcell app"></iframe>
```
## Other considerations
### Accessing files
`io.Open(filename)` and other related functions for reading file systems do not work; use `http.Get(filename)` instead.

View File

@ -264,7 +264,11 @@ Windows console mode applications are supported.
Modern console applications like ConEmu and the Windows 10 terminal, Modern console applications like ConEmu and the Windows 10 terminal,
support all the good features (resize, mouse tracking, etc.) support all the good features (resize, mouse tracking, etc.)
### Plan9, WASM, and others ### WASM
WASM is supported, but needs additional setup detailed in [README-wasm](README-wasm.md).
### Plan9 and others
These platforms won't work, but compilation stubs are supplied These platforms won't work, but compilation stubs are supplied
for folks that want to include parts of this in software for those for folks that want to include parts of this in software for those
@ -279,4 +283,4 @@ please let me know. PRs are especially welcome.
_Tcell_ is absolutely free, but if you want to obtain commercial, professional support, there are options. _Tcell_ is absolutely free, but if you want to obtain commercial, professional support, there are options.
- [TideLift](https://tidelift.com/) subscriptions include support for _Tcell_, as well as many other open source packages. - [TideLift](https://tidelift.com/) subscriptions include support for _Tcell_, as well as many other open source packages.
- [Staysail Systems Inc.](mailto:info@staysail.tech) offers direct support, and custom development around _Tcell_ on an hourly basis. - [Staysail Systems Inc.](mailto:info@staysail.tech) offers direct support, and custom development around _Tcell_ on an hourly basis.

View File

@ -50,6 +50,10 @@ func (cb *CellBuffer) SetContent(x int, y int,
if x >= 0 && y >= 0 && x < cb.w && y < cb.h { if x >= 0 && y >= 0 && x < cb.w && y < cb.h {
c := &cb.cells[(y*cb.w)+x] c := &cb.cells[(y*cb.w)+x]
for i := 1; i < c.width; i++ {
cb.SetDirty(x+i, y, true)
}
c.currComb = append([]rune{}, combc...) c.currComb = append([]rune{}, combc...)
if c.currMain != mainc { if c.currMain != mainc {
@ -178,13 +182,14 @@ func (cb *CellBuffer) Fill(r rune, style Style) {
} }
} }
var runeConfig *runewidth.Condition; var runeConfig *runewidth.Condition
func init() { func init() {
// The defaults for the runewidth package are poorly chosen for terminal // The defaults for the runewidth package are poorly chosen for terminal
// applications. We however will honor the setting in the environment if // applications. We however will honor the setting in the environment if
// it is set. // it is set.
if os.Getenv("RUNEWIDTH_EASTASIAN") == "" { if os.Getenv("RUNEWIDTH_EASTASIAN") == "" {
runewidth.DefaultCondition.EastAsianWidth = false; runewidth.DefaultCondition.EastAsianWidth = false
} }
// For performance reasons, we create a lookup table. However some users // For performance reasons, we create a lookup table. However some users

View File

@ -1002,14 +1002,14 @@ func (c Color) IsRGB() bool {
} }
// Hex returns the color's hexadecimal RGB 24-bit value with each component // Hex returns the color's hexadecimal RGB 24-bit value with each component
// consisting of a single byte, ala R << 16 | G << 8 | B. If the color // consisting of a single byte, R << 16 | G << 8 | B. If the color
// is unknown or unset, -1 is returned. // is unknown or unset, -1 is returned.
func (c Color) Hex() int32 { func (c Color) Hex() int32 {
if !c.Valid() { if !c.Valid() {
return -1 return -1
} }
if c&ColorIsRGB != 0 { if c&ColorIsRGB != 0 {
return int32(c) & 0xffffff return int32(c & 0xffffff)
} }
if v, ok := ColorValues[c]; ok { if v, ok := ColorValues[c]; ok {
return v return v
@ -1036,7 +1036,7 @@ func (c Color) TrueColor() Color {
return ColorDefault return ColorDefault
} }
if c&ColorIsRGB != 0 { if c&ColorIsRGB != 0 {
return c return c | ColorValid
} }
return Color(c.Hex()) | ColorIsRGB | ColorValid return Color(c.Hex()) | ColorIsRGB | ColorValid
} }

View File

@ -0,0 +1,69 @@
// Generated automatically. DO NOT HAND-EDIT.
package alacritty
import "github.com/gdamore/tcell/v2/terminfo"
func init() {
// alacritty with direct color indexing
terminfo.AddTerminfo(&terminfo.Terminfo{
Name: "alacritty-direct",
Columns: 80,
Lines: 24,
Colors: 16777216,
Bell: "\a",
Clear: "\x1b[H\x1b[2J",
EnterCA: "\x1b[?1049h\x1b[22;0;0t",
ExitCA: "\x1b[?1049l\x1b[23;0;0t",
ShowCursor: "\x1b[?12l\x1b[?25h",
HideCursor: "\x1b[?25l",
AttrOff: "\x1b(B\x1b[m",
Underline: "\x1b[4m",
Bold: "\x1b[1m",
Dim: "\x1b[2m",
Italic: "\x1b[3m",
Reverse: "\x1b[7m",
EnterKeypad: "\x1b[?1h\x1b=",
ExitKeypad: "\x1b[?1l\x1b>",
SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m",
ResetFgBg: "\x1b[39;49m",
AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~",
EnterAcs: "\x1b(0",
ExitAcs: "\x1b(B",
StrikeThrough: "\x1b[9m",
Mouse: "\x1b[M",
SetCursor: "\x1b[%i%p1%d;%p2%dH",
CursorBack1: "\b",
CursorUp1: "\x1b[A",
KeyUp: "\x1bOA",
KeyDown: "\x1bOB",
KeyRight: "\x1bOC",
KeyLeft: "\x1bOD",
KeyInsert: "\x1b[2~",
KeyDelete: "\x1b[3~",
KeyBackspace: "\x7f",
KeyHome: "\x1bOH",
KeyEnd: "\x1bOF",
KeyPgUp: "\x1b[5~",
KeyPgDn: "\x1b[6~",
KeyF1: "\x1bOP",
KeyF2: "\x1bOQ",
KeyF3: "\x1bOR",
KeyF4: "\x1bOS",
KeyF5: "\x1b[15~",
KeyF6: "\x1b[17~",
KeyF7: "\x1b[18~",
KeyF8: "\x1b[19~",
KeyF9: "\x1b[20~",
KeyF10: "\x1b[21~",
KeyF11: "\x1b[23~",
KeyF12: "\x1b[24~",
KeyBacktab: "\x1b[Z",
Modifiers: 1,
TrueColor: true,
AutoMargin: true,
})
}

View File

@ -1,5 +1,5 @@
//go:build tcell_minimal || nacl || js || zos || plan9 || windows || android //go:build tcell_minimal || nacl || zos || plan9 || windows || android || js
// +build tcell_minimal nacl js zos plan9 windows android // +build tcell_minimal nacl zos plan9 windows android js
// Copyright 2019 The TCell Authors // Copyright 2019 The TCell Authors
// //

View File

@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build !(js && wasm)
// +build !js !wasm
package tcell package tcell
import ( import (
@ -341,6 +344,11 @@ func (t *tScreen) prepareBracketedPaste() {
} }
func (t *tScreen) prepareExtendedOSC() { func (t *tScreen) prepareExtendedOSC() {
// Linux is a special beast - because it has a mouse entry, but does
// not swallow these OSC commands properly.
if (strings.Contains(t.ti.Name, "linux")) {
return;
}
// More stuff for limits in terminfo. This time we are applying // More stuff for limits in terminfo. This time we are applying
// the most common OSC (operating system commands). Generally // the most common OSC (operating system commands). Generally
// terminals that don't understand these will ignore them. // terminals that don't understand these will ignore them.

View File

@ -1,5 +1,5 @@
//go:build js || plan9 || windows //go:build plan9 || windows
// +build js plan9 windows // +build plan9 windows
// Copyright 2022 The TCell Authors // Copyright 2022 The TCell Authors
// //

678
vendor/github.com/gdamore/tcell/v2/wscreen.go generated vendored Normal file
View File

@ -0,0 +1,678 @@
// Copyright 2023 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.
//go:build js && wasm
// +build js,wasm
package tcell
import (
"errors"
"strings"
"sync"
"syscall/js"
"unicode/utf8"
)
func NewTerminfoScreen() (Screen, error) {
t := &wScreen{}
t.fallback = make(map[rune]string)
return t, nil
}
type wScreen struct {
w, h int
style Style
cells CellBuffer
running bool
clear bool
flagsPresent bool
pasteEnabled bool
mouseFlags MouseFlags
cursorStyle CursorStyle
quit chan struct{}
evch chan Event
fallback map[rune]string
sync.Mutex
}
func (t *wScreen) Init() error {
t.w, t.h = 80, 24 // default for html as of now
t.evch = make(chan Event, 10)
t.quit = make(chan struct{})
t.Lock()
t.running = true
t.style = StyleDefault
t.cells.Resize(t.w, t.h)
t.Unlock()
js.Global().Set("onKeyEvent", js.FuncOf(t.onKeyEvent))
return nil
}
func (t *wScreen) Fini() {
close(t.quit)
}
func (t *wScreen) SetStyle(style Style) {
t.Lock()
t.style = style
t.Unlock()
}
func (t *wScreen) Clear() {
t.Fill(' ', t.style)
}
func (t *wScreen) Fill(r rune, style Style) {
t.Lock()
t.cells.Fill(r, style)
t.Unlock()
}
func (t *wScreen) SetContent(x, y int, mainc rune, combc []rune, style Style) {
t.Lock()
t.cells.SetContent(x, y, mainc, combc, style)
t.Unlock()
}
func (t *wScreen) GetContent(x, y int) (rune, []rune, Style, int) {
t.Lock()
mainc, combc, style, width := t.cells.GetContent(x, y)
t.Unlock()
return mainc, combc, style, width
}
func (t *wScreen) SetCell(x, y int, style Style, ch ...rune) {
if len(ch) > 0 {
t.SetContent(x, y, ch[0], ch[1:], style)
} else {
t.SetContent(x, y, ' ', nil, style)
}
}
// paletteColor gives a more natural palette color actually matching
// typical XTerm. We might in the future want to permit styling these
// via CSS.
var palette = map[Color]int32{
ColorBlack: 0x000000,
ColorMaroon: 0xcd0000,
ColorGreen: 0x00cd00,
ColorOlive: 0xcdcd00,
ColorNavy: 0x0000ee,
ColorPurple: 0xcd00cd,
ColorTeal: 0x00cdcd,
ColorSilver: 0xe5e5e5,
ColorGray: 0x7f7f7f,
ColorRed: 0xff0000,
ColorLime: 0x00ff00,
ColorYellow: 0xffff00,
ColorBlue: 0x5c5cff,
ColorFuchsia: 0xff00ff,
ColorAqua: 0x00ffff,
ColorWhite: 0xffffff,
}
func paletteColor(c Color) int32 {
if (c.IsRGB()) {
return int32(c & 0xffffff);
}
if (c >= ColorBlack && c <= ColorWhite) {
return palette[c]
}
return c.Hex()
}
func (t *wScreen) drawCell(x, y int) int {
mainc, combc, style, width := t.cells.GetContent(x, y)
if !t.cells.Dirty(x, y) {
return width
}
if style == StyleDefault {
style = t.style
}
fg, bg := paletteColor(style.fg), paletteColor(style.bg)
if (fg == -1) {
fg = 0xe5e5e5;
}
if (bg == -1) {
bg = 0x000000;
}
var combcarr []interface{} = make([]interface{}, len(combc))
for i, c := range combc {
combcarr[i] = c
}
t.cells.SetDirty(x, y, false)
js.Global().Call("drawCell", x, y, mainc, combcarr, fg, bg, int(style.attrs))
return width
}
func (t *wScreen) ShowCursor(x, y int) {
t.Lock()
js.Global().Call("showCursor", x, y)
t.Unlock()
}
func (t *wScreen) SetCursorStyle(cs CursorStyle) {
t.Lock()
js.Global().Call("setCursorStyle", curStyleClasses[cs])
t.Unlock()
}
func (t *wScreen) HideCursor() {
t.ShowCursor(-1, -1)
}
func (t *wScreen) Show() {
t.Lock()
t.resize()
t.draw()
t.Unlock()
}
func (t *wScreen) clearScreen() {
js.Global().Call("clearScreen", t.style.fg.Hex(), t.style.bg.Hex())
t.clear = false
}
func (t *wScreen) draw() {
if t.clear {
t.clearScreen()
}
for y := 0; y < t.h; y++ {
for x := 0; x < t.w; x++ {
width := t.drawCell(x, y)
x += width - 1
}
}
js.Global().Call("show")
}
func (t *wScreen) EnableMouse(flags ...MouseFlags) {
var f MouseFlags
flagsPresent := false
for _, flag := range flags {
f |= flag
flagsPresent = true
}
if !flagsPresent {
f = MouseMotionEvents | MouseDragEvents | MouseButtonEvents
}
t.Lock()
t.mouseFlags = f
t.enableMouse(f)
t.Unlock()
}
func (t *wScreen) enableMouse(f MouseFlags) {
if f&MouseButtonEvents != 0 {
js.Global().Set("onMouseClick", js.FuncOf(t.onMouseEvent))
} else {
js.Global().Set("onMouseClick", js.FuncOf(t.unset))
}
if f&MouseDragEvents != 0 || f&MouseMotionEvents != 0 {
js.Global().Set("onMouseMove", js.FuncOf(t.onMouseEvent))
} else {
js.Global().Set("onMouseMove", js.FuncOf(t.unset))
}
}
func (t *wScreen) DisableMouse() {
t.Lock()
t.mouseFlags = 0
t.enableMouse(0)
t.Unlock()
}
func (t *wScreen) EnablePaste() {
t.Lock()
t.pasteEnabled = true
t.enablePasting(true)
t.Unlock()
}
func (t *wScreen) DisablePaste() {
t.Lock()
t.pasteEnabled = false
t.enablePasting(false)
t.Unlock()
}
func (t *wScreen) enablePasting(on bool) {
if on {
js.Global().Set("onPaste", js.FuncOf(t.onPaste))
} else {
js.Global().Set("onPaste", js.FuncOf(t.unset))
}
}
func (t *wScreen) Size() (int, int) {
t.Lock()
w, h := t.w, t.h
t.Unlock()
return w, h
}
// resize does nothing, as asking the web window to resize
// without a specified width or height will cause no change.
func (t *wScreen) resize() {}
func (t *wScreen) Colors() int {
return 16777216 // 256 ^ 3
}
func (t *wScreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) {
defer close(ch)
for {
select {
case <-quit:
return
case <-t.quit:
return
case ev := <-t.evch:
select {
case <-quit:
return
case <-t.quit:
return
case ch <- ev:
}
}
}
}
func (t *wScreen) PollEvent() Event {
select {
case <-t.quit:
return nil
case ev := <-t.evch:
return ev
}
}
func (t *wScreen) HasPendingEvent() bool {
return len(t.evch) > 0
}
func (t *wScreen) PostEventWait(ev Event) {
t.evch <- ev
}
func (t *wScreen) PostEvent(ev Event) error {
select {
case t.evch <- ev:
return nil
default:
return ErrEventQFull
}
}
func (t *wScreen) clip(x, y int) (int, int) {
w, h := t.cells.Size()
if x < 0 {
x = 0
}
if y < 0 {
y = 0
}
if x > w-1 {
x = w - 1
}
if y > h-1 {
y = h - 1
}
return x, y
}
func (t *wScreen) onMouseEvent(this js.Value, args []js.Value) interface{} {
mod := ModNone
button := ButtonNone
switch args[2].Int() {
case 0:
if t.mouseFlags&MouseMotionEvents == 0 {
// don't want this event! is a mouse motion event, but user has asked not.
return nil
}
button = ButtonNone
case 1:
button = Button1
case 2:
button = Button3 // Note we prefer to treat right as button 2
case 3:
button = Button2 // And the middle button as button 3
}
if args[3].Bool() { // mod shift
mod |= ModShift
}
if args[4].Bool() { // mod alt
mod |= ModAlt
}
if args[5].Bool() { // mod ctrl
mod |= ModCtrl
}
t.PostEventWait(NewEventMouse(args[0].Int(), args[1].Int(), button, mod))
return nil
}
func (t *wScreen) onKeyEvent(this js.Value, args []js.Value) interface{} {
key := args[0].String()
// don't accept any modifier keys as their own
if key == "Control" || key == "Alt" || key == "Meta" || key == "Shift" {
return nil
}
mod := ModNone
if args[1].Bool() { // mod shift
mod |= ModShift
}
if args[2].Bool() { // mod alt
mod |= ModAlt
}
if args[3].Bool() { // mod ctrl
mod |= ModCtrl
}
if args[4].Bool() { // mod meta
mod |= ModMeta
}
// check for special case of Ctrl + key
if mod == ModCtrl {
if k, ok := WebKeyNames["Ctrl-"+strings.ToLower(key)]; ok {
t.PostEventWait(NewEventKey(k, 0, mod))
return nil
}
}
// next try function keys
if k, ok := WebKeyNames[key]; ok {
t.PostEventWait(NewEventKey(k, 0, mod))
return nil
}
// finally try normal, printable chars
r, _ := utf8.DecodeRuneInString(key)
t.PostEventWait(NewEventKey(KeyRune, r, mod))
return nil
}
func (t *wScreen) onPaste(this js.Value, args []js.Value) interface{} {
t.PostEventWait(NewEventPaste(args[0].Bool()))
return nil
}
// unset is a dummy function for js when we want nothing to
// happen when javascript calls a function (for example, when
// mouse input is disabled, when onMouseEvent() is called from
// js, it redirects here and does nothing).
func (t *wScreen) unset(this js.Value, args []js.Value) interface{} {
return nil
}
func (t *wScreen) Sync() {
t.Lock()
t.resize()
t.clear = true
t.cells.Invalidate()
t.draw()
t.Unlock()
}
func (t *wScreen) CharacterSet() string {
return "UTF-8"
}
func (t *wScreen) RegisterRuneFallback(orig rune, fallback string) {
t.Lock()
t.fallback[orig] = fallback
t.Unlock()
}
func (t *wScreen) UnregisterRuneFallback(orig rune) {
t.Lock()
delete(t.fallback, orig)
t.Unlock()
}
func (t *wScreen) CanDisplay(r rune, checkFallbacks bool) bool {
if utf8.ValidRune(r) {
return true
}
if !checkFallbacks {
return false
}
if _, ok := t.fallback[r]; ok {
return true
}
return false
}
func (t *wScreen) HasMouse() bool {
return true
}
func (t *wScreen) HasKey(k Key) bool {
return true
}
func (t *wScreen) SetSize(w, h int) {
if w == t.w && h == t.h {
return
}
t.cells.Invalidate()
t.cells.Resize(w, h)
js.Global().Call("resize", w, h)
t.w, t.h = w, h
t.PostEvent(NewEventResize(w, h))
}
func (t *wScreen) Resize(int, int, int, int) {}
// Suspend simply pauses all input and output, and clears the screen.
// There isn't a "default terminal" to go back to.
func (t *wScreen) Suspend() error {
t.Lock()
if !t.running {
t.Unlock()
return nil
}
t.running = false
t.clearScreen()
t.enableMouse(0)
t.enablePasting(false)
js.Global().Set("onKeyEvent", js.FuncOf(t.unset)) // stop keypresses
return nil
}
func (t *wScreen) Resume() error {
t.Lock()
if t.running {
return errors.New("already engaged")
}
t.running = true
t.enableMouse(t.mouseFlags)
t.enablePasting(t.pasteEnabled)
js.Global().Set("onKeyEvent", js.FuncOf(t.onKeyEvent))
t.Unlock()
return nil
}
func (t *wScreen) Beep() error {
js.Global().Call("beep")
return nil
}
// WebKeyNames maps string names reported from HTML
// (KeyboardEvent.key) to tcell accepted keys.
var WebKeyNames = map[string]Key{
"Enter": KeyEnter,
"Backspace": KeyBackspace,
"Tab": KeyTab,
"Backtab": KeyBacktab,
"Escape": KeyEsc,
"Backspace2": KeyBackspace2,
"Delete": KeyDelete,
"Insert": KeyInsert,
"ArrowUp": KeyUp,
"ArrowDown": KeyDown,
"ArrowLeft": KeyLeft,
"ArrowRight": KeyRight,
"Home": KeyHome,
"End": KeyEnd,
"UpLeft": KeyUpLeft, // not supported by HTML
"UpRight": KeyUpRight, // not supported by HTML
"DownLeft": KeyDownLeft, // not supported by HTML
"DownRight": KeyDownRight, // not supported by HTML
"Center": KeyCenter,
"PgDn": KeyPgDn,
"PgUp": KeyPgUp,
"Clear": KeyClear,
"Exit": KeyExit,
"Cancel": KeyCancel,
"Pause": KeyPause,
"Print": KeyPrint,
"F1": KeyF1,
"F2": KeyF2,
"F3": KeyF3,
"F4": KeyF4,
"F5": KeyF5,
"F6": KeyF6,
"F7": KeyF7,
"F8": KeyF8,
"F9": KeyF9,
"F10": KeyF10,
"F11": KeyF11,
"F12": KeyF12,
"F13": KeyF13,
"F14": KeyF14,
"F15": KeyF15,
"F16": KeyF16,
"F17": KeyF17,
"F18": KeyF18,
"F19": KeyF19,
"F20": KeyF20,
"F21": KeyF21,
"F22": KeyF22,
"F23": KeyF23,
"F24": KeyF24,
"F25": KeyF25,
"F26": KeyF26,
"F27": KeyF27,
"F28": KeyF28,
"F29": KeyF29,
"F30": KeyF30,
"F31": KeyF31,
"F32": KeyF32,
"F33": KeyF33,
"F34": KeyF34,
"F35": KeyF35,
"F36": KeyF36,
"F37": KeyF37,
"F38": KeyF38,
"F39": KeyF39,
"F40": KeyF40,
"F41": KeyF41,
"F42": KeyF42,
"F43": KeyF43,
"F44": KeyF44,
"F45": KeyF45,
"F46": KeyF46,
"F47": KeyF47,
"F48": KeyF48,
"F49": KeyF49,
"F50": KeyF50,
"F51": KeyF51,
"F52": KeyF52,
"F53": KeyF53,
"F54": KeyF54,
"F55": KeyF55,
"F56": KeyF56,
"F57": KeyF57,
"F58": KeyF58,
"F59": KeyF59,
"F60": KeyF60,
"F61": KeyF61,
"F62": KeyF62,
"F63": KeyF63,
"F64": KeyF64,
"Ctrl-a": KeyCtrlA, // not reported by HTML- need to do special check
"Ctrl-b": KeyCtrlB, // not reported by HTML- need to do special check
"Ctrl-c": KeyCtrlC, // not reported by HTML- need to do special check
"Ctrl-d": KeyCtrlD, // not reported by HTML- need to do special check
"Ctrl-e": KeyCtrlE, // not reported by HTML- need to do special check
"Ctrl-f": KeyCtrlF, // not reported by HTML- need to do special check
"Ctrl-g": KeyCtrlG, // not reported by HTML- need to do special check
"Ctrl-j": KeyCtrlJ, // not reported by HTML- need to do special check
"Ctrl-k": KeyCtrlK, // not reported by HTML- need to do special check
"Ctrl-l": KeyCtrlL, // not reported by HTML- need to do special check
"Ctrl-n": KeyCtrlN, // not reported by HTML- need to do special check
"Ctrl-o": KeyCtrlO, // not reported by HTML- need to do special check
"Ctrl-p": KeyCtrlP, // not reported by HTML- need to do special check
"Ctrl-q": KeyCtrlQ, // not reported by HTML- need to do special check
"Ctrl-r": KeyCtrlR, // not reported by HTML- need to do special check
"Ctrl-s": KeyCtrlS, // not reported by HTML- need to do special check
"Ctrl-t": KeyCtrlT, // not reported by HTML- need to do special check
"Ctrl-u": KeyCtrlU, // not reported by HTML- need to do special check
"Ctrl-v": KeyCtrlV, // not reported by HTML- need to do special check
"Ctrl-w": KeyCtrlW, // not reported by HTML- need to do special check
"Ctrl-x": KeyCtrlX, // not reported by HTML- need to do special check
"Ctrl-y": KeyCtrlY, // not reported by HTML- need to do special check
"Ctrl-z": KeyCtrlZ, // not reported by HTML- need to do special check
"Ctrl- ": KeyCtrlSpace, // not reported by HTML- need to do special check
"Ctrl-_": KeyCtrlUnderscore, // not reported by HTML- need to do special check
"Ctrl-]": KeyCtrlRightSq, // not reported by HTML- need to do special check
"Ctrl-\\": KeyCtrlBackslash, // not reported by HTML- need to do special check
"Ctrl-^": KeyCtrlCarat, // not reported by HTML- need to do special check
}
var curStyleClasses = map[CursorStyle]string{
CursorStyleDefault: "cursor-blinking-block",
CursorStyleBlinkingBlock: "cursor-blinking-block",
CursorStyleSteadyBlock: "cursor-steady-block",
CursorStyleBlinkingUnderline: "cursor-blinking-underline",
CursorStyleSteadyUnderline: "cursor-steady-underline",
CursorStyleBlinkingBar: "cursor-blinking-bar",
CursorStyleSteadyBar: "cursor-steady-bar",
}

View File

@ -187,8 +187,8 @@ func ReverseString(s string) string {
const shiftGraphemePropState = 4 const shiftGraphemePropState = 4
// FirstGraphemeCluster returns the first grapheme cluster found in the given // FirstGraphemeCluster returns the first grapheme cluster found in the given
// byte slice according to the rules of Unicode Standard Annex #29, Grapheme // byte slice according to the rules of [Unicode Standard Annex #29, Grapheme
// Cluster Boundaries. This function can be called continuously to extract all // Cluster Boundaries]. This function can be called continuously to extract all
// grapheme clusters from a byte slice, as illustrated in the example below. // grapheme clusters from a byte slice, as illustrated in the example below.
// //
// If you don't know the current state, for example when calling the function // If you don't know the current state, for example when calling the function
@ -209,6 +209,8 @@ const shiftGraphemePropState = 4
// While slightly less convenient than using the Graphemes class, this function // While slightly less convenient than using the Graphemes class, this function
// has much better performance and makes no allocations. It lends itself well to // has much better performance and makes no allocations. It lends itself well to
// large byte slices. // large byte slices.
//
// [Unicode Standard Annex #29, Grapheme Cluster Boundaries]: http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
func FirstGraphemeCluster(b []byte, state int) (cluster, rest []byte, width, newState int) { func FirstGraphemeCluster(b []byte, state int) (cluster, rest []byte, width, newState int) {
// An empty byte slice returns nothing. // An empty byte slice returns nothing.
if len(b) == 0 { if len(b) == 0 {

View File

@ -48,7 +48,7 @@ var grTransitions = map[[2]int][3]int{
{grControlLF, prAny}: {grAny, grBoundary, 40}, {grControlLF, prAny}: {grAny, grBoundary, 40},
// GB3. // GB3.
{grCR, prLF}: {grAny, grNoBoundary, 30}, {grCR, prLF}: {grControlLF, grNoBoundary, 30},
// GB6. // GB6.
{grAny, prL}: {grL, grBoundary, 9990}, {grAny, prL}: {grL, grBoundary, 9990},

View File

@ -4,7 +4,7 @@ import "unicode/utf8"
// FirstLineSegment returns the prefix of the given byte slice after which a // FirstLineSegment returns the prefix of the given byte slice after which a
// decision to break the string over to the next line can or must be made, // decision to break the string over to the next line can or must be made,
// according to the rules of Unicode Standard Annex #14. This is used to // according to the rules of [Unicode Standard Annex #14]. This is used to
// implement line breaking. // implement line breaking.
// //
// Line breaking, also known as word wrapping, is the process of breaking a // Line breaking, also known as word wrapping, is the process of breaking a
@ -35,7 +35,7 @@ import "unicode/utf8"
// //
// Given an empty byte slice "b", the function returns nil values. // Given an empty byte slice "b", the function returns nil values.
// //
// Note that in accordance with UAX #14 LB3, the final segment will end with // Note that in accordance with [UAX #14 LB3], the final segment will end with
// "mustBreak" set to true. You can choose to ignore this by checking if the // "mustBreak" set to true. You can choose to ignore this by checking if the
// length of the "rest" slice is 0 and calling [HasTrailingLineBreak] or // length of the "rest" slice is 0 and calling [HasTrailingLineBreak] or
// [HasTrailingLineBreakInString] on the last rune. // [HasTrailingLineBreakInString] on the last rune.
@ -43,6 +43,9 @@ import "unicode/utf8"
// Note also that this algorithm may break within grapheme clusters. This is // Note also that this algorithm may break within grapheme clusters. This is
// addressed in Section 8.2 Example 6 of UAX #14. To avoid this, you can use // addressed in Section 8.2 Example 6 of UAX #14. To avoid this, you can use
// the [Step] function instead. // the [Step] function instead.
//
// [Unicode Standard Annex #14]: https://www.unicode.org/reports/tr14/
// [UAX #14 LB3]: https://www.unicode.org/reports/tr14/#Algorithm
func FirstLineSegment(b []byte, state int) (segment, rest []byte, mustBreak bool, newState int) { func FirstLineSegment(b []byte, state int) (segment, rest []byte, mustBreak bool, newState int) {
// An empty byte slice returns nothing. // An empty byte slice returns nothing.
if len(b) == 0 { if len(b) == 0 {

View File

@ -3,7 +3,7 @@ package uniseg
import "unicode/utf8" import "unicode/utf8"
// FirstSentence returns the first sentence found in the given byte slice // FirstSentence returns the first sentence found in the given byte slice
// according to the rules of Unicode Standard Annex #29, Sentence Boundaries. // according to the rules of [Unicode Standard Annex #29, Sentence Boundaries].
// This function can be called continuously to extract all sentences from a byte // This function can be called continuously to extract all sentences from a byte
// slice, as illustrated in the example below. // slice, as illustrated in the example below.
// //
@ -17,6 +17,8 @@ import "unicode/utf8"
// slice is the sub-slice of the input slice containing the identified sentence. // slice is the sub-slice of the input slice containing the identified sentence.
// //
// Given an empty byte slice "b", the function returns nil values. // Given an empty byte slice "b", the function returns nil values.
//
// [Unicode Standard Annex #29, Sentence Boundaries]: http://unicode.org/reports/tr29/#Sentence_Boundaries
func FirstSentence(b []byte, state int) (sentence, rest []byte, newState int) { func FirstSentence(b []byte, state int) (sentence, rest []byte, newState int) {
// An empty byte slice returns nothing. // An empty byte slice returns nothing.
if len(b) == 0 { if len(b) == 0 {

View File

@ -83,10 +83,12 @@ const (
// has much better performance and makes no allocations. It lends itself well to // has much better performance and makes no allocations. It lends itself well to
// large byte slices. // large byte slices.
// //
// Note that in accordance with UAX #14 LB3, the final segment will end with // Note that in accordance with [UAX #14 LB3], the final segment will end with
// a mandatory line break (boundaries&MaskLine == LineMustBreak). You can choose // a mandatory line break (boundaries&MaskLine == LineMustBreak). You can choose
// to ignore this by checking if the length of the "rest" slice is 0 and calling // to ignore this by checking if the length of the "rest" slice is 0 and calling
// [HasTrailingLineBreak] or [HasTrailingLineBreakInString] on the last rune. // [HasTrailingLineBreak] or [HasTrailingLineBreakInString] on the last rune.
//
// [UAX #14 LB3]: https://www.unicode.org/reports/tr14/#Algorithm
func Step(b []byte, state int) (cluster, rest []byte, boundaries int, newState int) { func Step(b []byte, state int) (cluster, rest []byte, boundaries int, newState int) {
// An empty byte slice returns nothing. // An empty byte slice returns nothing.
if len(b) == 0 { if len(b) == 0 {

View File

@ -3,7 +3,7 @@ package uniseg
import "unicode/utf8" import "unicode/utf8"
// FirstWord returns the first word found in the given byte slice according to // FirstWord returns the first word found in the given byte slice according to
// the rules of Unicode Standard Annex #29, Word Boundaries. This function can // the rules of [Unicode Standard Annex #29, Word Boundaries]. This function can
// be called continuously to extract all words from a byte slice, as illustrated // be called continuously to extract all words from a byte slice, as illustrated
// in the example below. // in the example below.
// //
@ -17,6 +17,8 @@ import "unicode/utf8"
// the sub-slice of the input slice containing the identified word. // the sub-slice of the input slice containing the identified word.
// //
// Given an empty byte slice "b", the function returns nil values. // Given an empty byte slice "b", the function returns nil values.
//
// [Unicode Standard Annex #29, Word Boundaries]: http://unicode.org/reports/tr29/#Word_Boundaries
func FirstWord(b []byte, state int) (word, rest []byte, newState int) { func FirstWord(b []byte, state int) (word, rest []byte, newState int) {
// An empty byte slice returns nothing. // An empty byte slice returns nothing.
if len(b) == 0 { if len(b) == 0 {

6
vendor/modules.txt vendored
View File

@ -39,7 +39,9 @@ github.com/fsnotify/fsnotify
# github.com/gdamore/encoding v1.0.0 # github.com/gdamore/encoding v1.0.0
## explicit; go 1.9 ## explicit; go 1.9
github.com/gdamore/encoding github.com/gdamore/encoding
# github.com/gdamore/tcell/v2 v2.5.4 # github.com/gdamore/tcell v1.4.0
## explicit; go 1.12
# github.com/gdamore/tcell/v2 v2.6.0
## explicit; go 1.12 ## explicit; go 1.12
github.com/gdamore/tcell/v2 github.com/gdamore/tcell/v2
github.com/gdamore/tcell/v2/terminfo github.com/gdamore/tcell/v2/terminfo
@ -233,7 +235,7 @@ github.com/petermattis/goid
# github.com/pmezard/go-difflib v1.0.0 # github.com/pmezard/go-difflib v1.0.0
## explicit ## explicit
github.com/pmezard/go-difflib/difflib github.com/pmezard/go-difflib/difflib
# github.com/rivo/uniseg v0.4.3 # github.com/rivo/uniseg v0.4.4
## explicit; go 1.18 ## explicit; go 1.18
github.com/rivo/uniseg github.com/rivo/uniseg
# github.com/sahilm/fuzzy v0.1.0 # github.com/sahilm/fuzzy v0.1.0