mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-28 02:07:09 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2585c4b3ec |
@@ -39,7 +39,7 @@ require (
|
||||
github.com/spkg/bom v1.0.1
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20250905083220-c50528f08304
|
||||
github.com/stretchr/testify v1.12.1
|
||||
github.com/xo/terminfo v1.0.0
|
||||
github.com/xo/terminfo v1.2.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
golang.org/x/sync v0.22.0
|
||||
golang.org/x/sys v0.47.0
|
||||
|
||||
@@ -127,8 +127,8 @@ github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUm
|
||||
github.com/urfave/cli v1.20.1-0.20180226030253-8e01ec4cd3e2/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/xo/terminfo v1.0.0 h1:2ZpYzqWzyyytjk3TP6aJVDhkMAkc99/1xKQdA3TDTBY=
|
||||
github.com/xo/terminfo v1.0.0/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/xo/terminfo v1.2.0 h1:d0ZTOCpuGE0lwSAOs0zcJjwz3jWQyqcRt9XbGJpCOl4=
|
||||
github.com/xo/terminfo v1.2.0/go.mod h1:lGzkSo8Fe7IRh/w+Gqz7n5mDog4FVXCj3gy/DYTBqio=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||
|
||||
+4
-4
@@ -353,9 +353,9 @@ const (
|
||||
KeyStab
|
||||
// The KeyUp [key_up, kcuu1] string capability is the up-arrow key.
|
||||
KeyUp
|
||||
// The KeypadLocal [keypad_local, rmkx] string capability is the leave 'keyboard_transmit' mode.
|
||||
// The KeypadLocal [keypad_local, rmkx] string capability is the leave keypad transmit mode.
|
||||
KeypadLocal
|
||||
// The KeypadXmit [keypad_xmit, smkx] string capability is the enter 'keyboard_transmit' mode.
|
||||
// The KeypadXmit [keypad_xmit, smkx] string capability is the enter keypad transmit mode.
|
||||
KeypadXmit
|
||||
// The LabF0 [lab_f0, lf0] string capability is the label on function key f0 if not f0.
|
||||
LabF0
|
||||
@@ -719,7 +719,7 @@ const (
|
||||
ClrBol
|
||||
// The ClearMargins [clear_margins, mgc] string capability is the clear right and left soft margins.
|
||||
ClearMargins
|
||||
// The SetLeftMargin [set_left_margin, smgl] string capability is the set left soft margin at current column. (ML is not in BSD termcap).
|
||||
// The SetLeftMargin [set_left_margin, smgl] string capability is the set left soft margin at current column (not in BSD \fItermcap\fP).
|
||||
SetLeftMargin
|
||||
// The SetRightMargin [set_right_margin, smgr] string capability is the set right soft margin at current column.
|
||||
SetRightMargin
|
||||
@@ -901,7 +901,7 @@ const (
|
||||
SetABackground
|
||||
// The PkeyPlab [pkey_plab, pfxl] string capability is the Program function key #1 to type string #2 and show string #3.
|
||||
PkeyPlab
|
||||
// The DeviceType [device_type, devt] string capability is the Indicate language/codeset support.
|
||||
// The DeviceType [device_type, devt] string capability is the Indicate language, codeset support.
|
||||
DeviceType
|
||||
// The CodeSetInit [code_set_init, csin] string capability is the Init sequence for multiple codesets.
|
||||
CodeSetInit
|
||||
|
||||
+43
-21
@@ -1,7 +1,7 @@
|
||||
package terminfo
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"slices"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,7 +29,7 @@ const (
|
||||
fieldExtBoolCount = iota
|
||||
fieldExtNumCount
|
||||
fieldExtStringCount
|
||||
fieldExtOffsetCount
|
||||
fieldExtOffsetUsed
|
||||
fieldExtTableSize
|
||||
)
|
||||
|
||||
@@ -50,11 +50,29 @@ func capLength(h []int) int {
|
||||
h[fieldTableSize]
|
||||
}
|
||||
|
||||
// extOffsetCount returns the number of offsets stored in the extended string
|
||||
// data table index.
|
||||
//
|
||||
// An offset is written for every extended string cap, followed by one for the
|
||||
// name of every extended bool, num and string cap.
|
||||
func extOffsetCount(h []int) int {
|
||||
return h[fieldExtBoolCount] +
|
||||
h[fieldExtNumCount] +
|
||||
h[fieldExtStringCount]*2
|
||||
}
|
||||
|
||||
// hasInvalidExtOffset determines if the extended offset field is valid.
|
||||
//
|
||||
// The field holds the number of offsets that are actually used (ie, that point
|
||||
// into the string data table), which excludes any absent or cancelled extended
|
||||
// string cap, and so is only ever less than or equal to the number of offsets
|
||||
// present in the file.
|
||||
func hasInvalidExtOffset(h []int) bool {
|
||||
return h[fieldExtBoolCount]+
|
||||
h[fieldExtNumCount]+
|
||||
h[fieldExtStringCount]*2 != h[fieldExtOffsetCount]
|
||||
return h[fieldExtBoolCount] < 0 ||
|
||||
h[fieldExtNumCount] < 0 ||
|
||||
h[fieldExtStringCount] < 0 ||
|
||||
h[fieldExtOffsetUsed] < 0 ||
|
||||
h[fieldExtOffsetUsed] > extOffsetCount(h)
|
||||
}
|
||||
|
||||
// extCapLength returns the total length of extended capabilities in bytes.
|
||||
@@ -62,7 +80,7 @@ func extCapLength(h []int, numWidth int) int {
|
||||
return h[fieldExtBoolCount] +
|
||||
h[fieldExtBoolCount]%2 + // account for word align
|
||||
h[fieldExtNumCount]*(numWidth/8) +
|
||||
h[fieldExtOffsetCount]*2 +
|
||||
extOffsetCount(h)*2 +
|
||||
h[fieldExtTableSize]
|
||||
}
|
||||
|
||||
@@ -76,22 +94,28 @@ func findNull(buf []byte, i int) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// readStrings decodes n strings from string data table buf using the indexes in idx.
|
||||
func readStrings(idx []int, buf []byte, n int) (map[int][]byte, int, error) {
|
||||
// readStrings decodes n strings from string data table buf using the indexes in
|
||||
// idx, returning the decoded strings, the cancelled strings, and the offset of
|
||||
// the end of the last decoded string.
|
||||
func readStrings(idx []int, buf []byte, n int) (map[int][]byte, map[int]bool, int, error) {
|
||||
var last int
|
||||
m := make(map[int][]byte)
|
||||
for i := 0; i < n; i++ {
|
||||
m, mm := make(map[int][]byte), make(map[int]bool)
|
||||
for i := range n {
|
||||
start := idx[i]
|
||||
if start == -2 {
|
||||
mm[i] = true
|
||||
continue
|
||||
}
|
||||
if start < 0 {
|
||||
continue
|
||||
}
|
||||
if end := findNull(buf, start); end != -1 {
|
||||
m[i], last = buf[start:end], end+1
|
||||
} else {
|
||||
return nil, 0, ErrInvalidStringTable
|
||||
return nil, nil, 0, ErrInvalidStringTable
|
||||
}
|
||||
}
|
||||
return m, last, nil
|
||||
return m, mm, last, nil
|
||||
}
|
||||
|
||||
// decoder holds state info while decoding a terminfo file.
|
||||
@@ -124,11 +148,11 @@ func (d *decoder) readInts(n, w int) ([]int, error) {
|
||||
for i, j := 0, 0; i < l; i, j = i+w, j+1 {
|
||||
switch w {
|
||||
case 1:
|
||||
z[i] = int(buf[i])
|
||||
z[j] = int(buf[i])
|
||||
case 2:
|
||||
z[j] = int(int16(buf[i+1])<<8 | int16(buf[i]))
|
||||
z[j] = int(int16(uint16(buf[i+1])<<8 | uint16(buf[i])))
|
||||
case 4:
|
||||
z[j] = int(buf[i+3])<<24 | int(buf[i+2])<<16 | int(buf[i+1])<<8 | int(buf[i])
|
||||
z[j] = int(int32(uint32(buf[i+3])<<24 | uint32(buf[i+2])<<16 | uint32(buf[i+1])<<8 | uint32(buf[i])))
|
||||
}
|
||||
}
|
||||
return z, nil
|
||||
@@ -159,7 +183,7 @@ func (d *decoder) readNums(n, w int) (map[int]int, map[int]bool, error) {
|
||||
}
|
||||
// process
|
||||
nums, numsM := make(map[int]int), make(map[int]bool)
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
nums[i] = buf[i]
|
||||
if buf[i] == -2 {
|
||||
numsM[i] = true
|
||||
@@ -185,7 +209,7 @@ func (d *decoder) readStringTable(n, sz int) ([][]byte, []int, error) {
|
||||
// process
|
||||
s := make([][]byte, n)
|
||||
var m []int
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
start := buf[i]
|
||||
if start == -2 {
|
||||
m = append(m, i)
|
||||
@@ -231,12 +255,10 @@ func canonicalizeAscChars(z []byte) []byte {
|
||||
if _, ok := enc[z[i]]; !ok {
|
||||
a, b := z[i], z[i+1]
|
||||
// log.Printf(">>> a: %d %c, b: %d %c", a, a, b, b)
|
||||
c, enc[a] = append(c, b), b
|
||||
c, enc[a] = append(c, a), b
|
||||
}
|
||||
}
|
||||
sort.Slice(c, func(i, j int) bool {
|
||||
return c[i] < c[j]
|
||||
})
|
||||
slices.Sort(c)
|
||||
r := make([]byte, 2*len(c))
|
||||
for i := 0; i < len(c); i++ {
|
||||
r[i*2], r[i*2+1] = c[i], enc[c[i]]
|
||||
|
||||
+19
-19
@@ -24,19 +24,19 @@ type parametizer struct {
|
||||
// buf is the result buffer.
|
||||
buf *bytes.Buffer
|
||||
// params are the parameters to interpolate.
|
||||
params [9]interface{}
|
||||
params [9]any
|
||||
// vars are dynamic variables.
|
||||
vars [26]interface{}
|
||||
vars [26]any
|
||||
}
|
||||
|
||||
// staticVars are the static, global variables.
|
||||
var staticVars = struct {
|
||||
vars [26]interface{}
|
||||
vars [26]any
|
||||
sync.Mutex
|
||||
}{}
|
||||
|
||||
var parametizerPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
p := new(parametizer)
|
||||
p.buf = bytes.NewBuffer(make([]byte, 0, 45))
|
||||
return p
|
||||
@@ -55,7 +55,7 @@ func (p *parametizer) reset() {
|
||||
p.pos, p.nest = 0, 0
|
||||
p.s.reset()
|
||||
p.buf.Reset()
|
||||
p.params, p.vars = [9]interface{}{}, [26]interface{}{}
|
||||
p.params, p.vars = [9]any{}, [26]any{}
|
||||
parametizerPool.Put(p)
|
||||
}
|
||||
|
||||
@@ -230,7 +230,8 @@ func (p *parametizer) scanFormatFn() stateFn {
|
||||
// the character was already read, so no need to check the error.
|
||||
ch, _ := p.peek()
|
||||
// 6 should be the maximum length of a format string, for example "%:-9.9d".
|
||||
f := []byte{'%', ch, 0, 0, 0, 0}
|
||||
f := make([]byte, 2, 6)
|
||||
f[0], f[1] = '%', ch
|
||||
var err error
|
||||
for {
|
||||
p.pos++
|
||||
@@ -242,17 +243,18 @@ func (p *parametizer) scanFormatFn() stateFn {
|
||||
switch ch {
|
||||
case 'o', 'd', 'x', 'X':
|
||||
fmt.Fprintf(p.buf, string(f), p.s.popInt())
|
||||
break
|
||||
p.pos++
|
||||
return p.scanTextFn
|
||||
case 's':
|
||||
fmt.Fprintf(p.buf, string(f), p.s.popString())
|
||||
break
|
||||
p.pos++
|
||||
return p.scanTextFn
|
||||
case 'c':
|
||||
fmt.Fprintf(p.buf, string(f), p.s.popByte())
|
||||
break
|
||||
p.pos++
|
||||
return p.scanTextFn
|
||||
}
|
||||
}
|
||||
p.pos++
|
||||
return p.scanTextFn
|
||||
}
|
||||
|
||||
func (p *parametizer) pushParamFn() stateFn {
|
||||
@@ -291,15 +293,13 @@ func (p *parametizer) getDsVarFn() stateFn {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var a byte
|
||||
if ch >= 'A' && ch <= 'Z' {
|
||||
a = 'A'
|
||||
staticVars.Lock()
|
||||
p.s.push(staticVars.vars[int(ch-'A')])
|
||||
staticVars.Unlock()
|
||||
} else if ch >= 'a' && ch <= 'z' {
|
||||
a = 'a'
|
||||
p.s.push(p.vars[int(ch-'a')])
|
||||
}
|
||||
staticVars.Lock()
|
||||
p.s.push(staticVars.vars[int(ch-a)])
|
||||
staticVars.Unlock()
|
||||
p.pos++
|
||||
return p.scanTextFn
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func (p *parametizer) skipElseFn() stateFn {
|
||||
}
|
||||
|
||||
// Printf evaluates a parameterized terminfo value z, interpolating params.
|
||||
func Printf(z []byte, params ...interface{}) string {
|
||||
func Printf(z []byte, params ...any) string {
|
||||
p := newParametizer(z)
|
||||
defer p.reset()
|
||||
// make sure we always have 9 parameters -- makes it easier
|
||||
@@ -400,6 +400,6 @@ func Printf(z []byte, params ...interface{}) string {
|
||||
|
||||
// Fprintf evaluates a parameterized terminfo value z, interpolating params and
|
||||
// writing to w.
|
||||
func Fprintf(w io.Writer, z []byte, params ...interface{}) {
|
||||
func Fprintf(w io.Writer, z []byte, params ...any) {
|
||||
w.Write([]byte(Printf(z, params...)))
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
package terminfo
|
||||
|
||||
type stack []interface{}
|
||||
type stack []any
|
||||
|
||||
func (s *stack) push(v interface{}) {
|
||||
func (s *stack) push(v any) {
|
||||
*s = append(*s, v)
|
||||
}
|
||||
|
||||
func (s *stack) pop() interface{} {
|
||||
func (s *stack) pop() any {
|
||||
if len(*s) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
+9
-7
@@ -72,6 +72,8 @@ type Terminfo struct {
|
||||
ExtNumNames map[int][]byte
|
||||
// ExtStrings are the extended string capabilities.
|
||||
ExtStrings map[int][]byte
|
||||
// ExtStringsM are the missing extended string capabilities.
|
||||
ExtStringsM map[int]bool
|
||||
// ExtStringsNames is the map of extended string capabilities to their index.
|
||||
ExtStringNames map[int][]byte
|
||||
}
|
||||
@@ -173,7 +175,7 @@ func Decode(buf []byte) (*Terminfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
// read extended string data table indexes
|
||||
extIndexes, err := d.readInts(eh[fieldExtOffsetCount], 16)
|
||||
extIndexes, err := d.readInts(extOffsetCount(eh), 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -188,25 +190,25 @@ func Decode(buf []byte) (*Terminfo, error) {
|
||||
}
|
||||
var last int
|
||||
// read extended string caps
|
||||
ti.ExtStrings, last, err = readStrings(extIndexes, extData, eh[fieldExtStringCount])
|
||||
ti.ExtStrings, ti.ExtStringsM, last, err = readStrings(extIndexes, extData, eh[fieldExtStringCount])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extIndexes, extData = extIndexes[eh[fieldExtStringCount]:], extData[last:]
|
||||
// read extended bool names
|
||||
ti.ExtBoolNames, _, err = readStrings(extIndexes, extData, eh[fieldExtBoolCount])
|
||||
ti.ExtBoolNames, _, _, err = readStrings(extIndexes, extData, eh[fieldExtBoolCount])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extIndexes = extIndexes[eh[fieldExtBoolCount]:]
|
||||
// read extended num names
|
||||
ti.ExtNumNames, _, err = readStrings(extIndexes, extData, eh[fieldExtNumCount])
|
||||
ti.ExtNumNames, _, _, err = readStrings(extIndexes, extData, eh[fieldExtNumCount])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extIndexes = extIndexes[eh[fieldExtNumCount]:]
|
||||
// read extended string names
|
||||
ti.ExtStringNames, _, err = readStrings(extIndexes, extData, eh[fieldExtStringCount])
|
||||
ti.ExtStringNames, _, _, err = readStrings(extIndexes, extData, eh[fieldExtStringCount])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -377,12 +379,12 @@ func (ti *Terminfo) Num(i int) int {
|
||||
}
|
||||
|
||||
// Printf formats the string cap i, interpolating parameters v.
|
||||
func (ti *Terminfo) Printf(i int, v ...interface{}) string {
|
||||
func (ti *Terminfo) Printf(i int, v ...any) string {
|
||||
return Printf(ti.Strings[i], v...)
|
||||
}
|
||||
|
||||
// Fprintf prints the string cap i to writer w, interpolating parameters v.
|
||||
func (ti *Terminfo) Fprintf(w io.Writer, i int, v ...interface{}) {
|
||||
func (ti *Terminfo) Fprintf(w io.Writer, i int, v ...any) {
|
||||
Fprintf(w, ti.Strings[i], v...)
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -157,8 +157,8 @@ github.com/stretchr/testify/internal/spew
|
||||
# github.com/wk8/go-ordered-map/v2 v2.1.8
|
||||
## explicit; go 1.18
|
||||
github.com/wk8/go-ordered-map/v2
|
||||
# github.com/xo/terminfo v1.0.0
|
||||
## explicit; go 1.19
|
||||
# github.com/xo/terminfo v1.2.0
|
||||
## explicit; go 1.25
|
||||
github.com/xo/terminfo
|
||||
# go.yaml.in/yaml/v3 v3.0.5
|
||||
## explicit; go 1.16
|
||||
|
||||
Reference in New Issue
Block a user