1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-29 00:51:35 +02:00

Bump gocui

This commit is contained in:
Stefan Haller
2024-08-24 10:35:59 +02:00
parent 61ae5e16ae
commit 250eb14de1
7 changed files with 98 additions and 46 deletions

2
go.mod
View File

@ -16,7 +16,7 @@ require (
github.com/integrii/flaggy v1.4.0 github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
github.com/jesseduffield/gocui v0.3.1-0.20240824081936-a3adeb73f602 github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e

4
go.sum
View File

@ -188,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
github.com/jesseduffield/gocui v0.3.1-0.20240824081936-a3adeb73f602 h1:nzGt/sRT0WCancALG5Q9e4DlQWGo7QUMc35rApdt+aM= github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9 h1:1muwCO0cmCGHpOvNz1qTOrCFPECnBAV87yDE9Fgwy6U=
github.com/jesseduffield/gocui v0.3.1-0.20240824081936-a3adeb73f602/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8= github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=

View File

@ -17,6 +17,7 @@ type escapeInterpreter struct {
curFgColor, curBgColor Attribute curFgColor, curBgColor Attribute
mode OutputMode mode OutputMode
instruction instruction instruction instruction
hyperlink string
} }
type ( type (
@ -40,7 +41,11 @@ const (
stateCSI stateCSI
stateParams stateParams
stateOSC stateOSC
stateOSCEscape stateOSCWaitForParams
stateOSCParams
stateOSCHyperlink
stateOSCEndEscape
stateOSCSkipUnknown
bold fontEffect = 1 bold fontEffect = 1
faint fontEffect = 2 faint fontEffect = 2
@ -60,6 +65,7 @@ var (
errNotCSI = errors.New("Not a CSI escape sequence") errNotCSI = errors.New("Not a CSI escape sequence")
errCSIParseError = errors.New("CSI escape sequence parsing error") errCSIParseError = errors.New("CSI escape sequence parsing error")
errCSITooLong = errors.New("CSI escape sequence is too long") errCSITooLong = errors.New("CSI escape sequence is too long")
errOSCParseError = errors.New("OSC escape sequence parsing error")
) )
// runes in case of error will output the non-parsed runes as a string. // runes in case of error will output the non-parsed runes as a string.
@ -78,6 +84,7 @@ func (ei *escapeInterpreter) runes() []rune {
ret = append(ret, ';') ret = append(ret, ';')
} }
return append(ret, ei.curch) return append(ret, ei.curch)
default:
} }
return nil return nil
} }
@ -191,15 +198,47 @@ func (ei *escapeInterpreter) parseOne(ch rune) (isEscape bool, err error) {
return false, errCSIParseError return false, errCSIParseError
} }
case stateOSC: case stateOSC:
switch ch { if ch == '8' {
case 0x1b: ei.state = stateOSCWaitForParams
ei.state = stateOSCEscape ei.hyperlink = ""
return true, nil return true, nil
} }
ei.state = stateOSCSkipUnknown
return true, nil return true, nil
case stateOSCEscape: case stateOSCWaitForParams:
if ch != ';' {
return true, errOSCParseError
}
ei.state = stateOSCParams
return true, nil
case stateOSCParams:
if ch == ';' {
ei.state = stateOSCHyperlink
}
return true, nil
case stateOSCHyperlink:
switch ch {
case 0x07:
ei.state = stateNone
case 0x1b:
ei.state = stateOSCEndEscape
default:
ei.hyperlink += string(ch)
}
return true, nil
case stateOSCEndEscape:
ei.state = stateNone ei.state = stateNone
return true, nil return true, nil
case stateOSCSkipUnknown:
switch ch {
case 0x07:
ei.state = stateNone
case 0x1b:
ei.state = stateOSCEndEscape
}
return true, nil
} }
return false, nil return false, nil
} }
@ -267,58 +306,48 @@ func (ei *escapeInterpreter) outputCSI() error {
func (ei *escapeInterpreter) csiColor(param []string) (color Attribute, skip int, err error) { func (ei *escapeInterpreter) csiColor(param []string) (color Attribute, skip int, err error) {
if len(param) < 2 { if len(param) < 2 {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
switch param[1] { switch param[1] {
case "2": case "2":
// 24-bit color // 24-bit color
if ei.mode < OutputTrue { if ei.mode < OutputTrue {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
if len(param) < 5 { if len(param) < 5 {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
var red, green, blue int var red, green, blue int
red, err = strconv.Atoi(param[2]) red, err = strconv.Atoi(param[2])
if err != nil { if err != nil {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
green, err = strconv.Atoi(param[3]) green, err = strconv.Atoi(param[3])
if err != nil { if err != nil {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
blue, err = strconv.Atoi(param[4]) blue, err = strconv.Atoi(param[4])
if err != nil { if err != nil {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
return NewRGBColor(int32(red), int32(green), int32(blue)), 5, nil return NewRGBColor(int32(red), int32(green), int32(blue)), 5, nil
case "5": case "5":
// 8-bit color // 8-bit color
if ei.mode < Output256 { if ei.mode < Output256 {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
if len(param) < 3 { if len(param) < 3 {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
var hex int var hex int
hex, err = strconv.Atoi(param[2]) hex, err = strconv.Atoi(param[2])
if err != nil { if err != nil {
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
return Get256Color(int32(hex)), 3, nil return Get256Color(int32(hex)), 3, nil
default: default:
err = errCSIParseError return 0, 0, errCSIParseError
return
} }
} }

View File

@ -130,6 +130,7 @@ type Gui struct {
managers []Manager managers []Manager
keybindings []*keybinding keybindings []*keybinding
focusHandler func(bool) error focusHandler func(bool) error
openHyperlink func(string) error
maxX, maxY int maxX, maxY int
outputMode OutputMode outputMode OutputMode
stop chan struct{} stop chan struct{}
@ -624,6 +625,10 @@ func (g *Gui) SetFocusHandler(handler func(bool) error) {
g.focusHandler = handler g.focusHandler = handler
} }
func (g *Gui) SetOpenHyperlinkFunc(openHyperlinkFunc func(string) error) {
g.openHyperlink = openHyperlinkFunc
}
// getKey takes an empty interface with a key and returns the corresponding // getKey takes an empty interface with a key and returns the corresponding
// typed Key or rune. // typed Key or rune.
func getKey(key interface{}) (Key, rune, error) { func getKey(key interface{}) (Key, rune, error) {
@ -1302,7 +1307,7 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
switch ev.Type { switch ev.Type {
case eventKey: case eventKey:
_, err := g.execKeybindings(g.currentView, ev) err := g.execKeybindings(g.currentView, ev)
if err != nil { if err != nil {
return err return err
} }
@ -1367,6 +1372,14 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
} }
} }
if ev.Key == MouseLeft && !v.Editable && g.openHyperlink != nil {
if newY >= 0 && newY <= len(v.viewLines)-1 && newX >= 0 && newX <= len(v.viewLines[newY].line)-1 {
if link := v.viewLines[newY].line[newX].hyperlink; link != "" {
return g.openHyperlink(link)
}
}
}
if IsMouseKey(ev.Key) { if IsMouseKey(ev.Key) {
opts := ViewMouseBindingOpts{X: newX, Y: newY} opts := ViewMouseBindingOpts{X: newX, Y: newY}
matched, err := g.execMouseKeybindings(v, ev, opts) matched, err := g.execMouseKeybindings(v, ev, opts)
@ -1378,9 +1391,11 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
} }
} }
if _, err := g.execKeybindings(v, ev); err != nil { if err := g.execKeybindings(v, ev); err != nil {
return err return err
} }
default:
} }
return nil return nil
@ -1440,25 +1455,25 @@ func IsMouseScrollKey(key interface{}) bool {
} }
// execKeybindings executes the keybinding handlers that match the passed view // execKeybindings executes the keybinding handlers that match the passed view
// and event. The value of matched is true if there is a match and no errors. // and event.
func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) (matched bool, err error) { func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) error {
var globalKb *keybinding var globalKb *keybinding
var matchingParentViewKb *keybinding var matchingParentViewKb *keybinding
// if we're searching, and we've hit n/N/Esc, we ignore the default keybinding // if we're searching, and we've hit n/N/Esc, we ignore the default keybinding
if v != nil && v.IsSearching() && ev.Mod == ModNone { if v != nil && v.IsSearching() && ev.Mod == ModNone {
if eventMatchesKey(ev, g.NextSearchMatchKey) { if eventMatchesKey(ev, g.NextSearchMatchKey) {
return true, v.gotoNextMatch() return v.gotoNextMatch()
} else if eventMatchesKey(ev, g.PrevSearchMatchKey) { } else if eventMatchesKey(ev, g.PrevSearchMatchKey) {
return true, v.gotoPreviousMatch() return v.gotoPreviousMatch()
} else if eventMatchesKey(ev, g.SearchEscapeKey) { } else if eventMatchesKey(ev, g.SearchEscapeKey) {
v.searcher.clearSearch() v.searcher.clearSearch()
if g.OnSearchEscape != nil { if g.OnSearchEscape != nil {
if err := g.OnSearchEscape(); err != nil { if err := g.OnSearchEscape(); err != nil {
return true, err return err
} }
} }
return true, nil return nil
} }
} }
@ -1486,26 +1501,26 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) (matched bool, err error)
if g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil { if g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil {
matched := g.currentView.Editor.Edit(g.currentView, ev.Key, ev.Ch, ev.Mod) matched := g.currentView.Editor.Edit(g.currentView, ev.Key, ev.Ch, ev.Mod)
if matched { if matched {
return true, nil return nil
} }
} }
if globalKb != nil { if globalKb != nil {
return g.execKeybinding(v, globalKb) return g.execKeybinding(v, globalKb)
} }
return false, nil return nil
} }
// execKeybinding executes a given keybinding // execKeybinding executes a given keybinding
func (g *Gui) execKeybinding(v *View, kb *keybinding) (bool, error) { func (g *Gui) execKeybinding(v *View, kb *keybinding) error {
if g.isBlacklisted(kb.key) { if g.isBlacklisted(kb.key) {
return true, nil return nil
} }
if err := kb.handler(g, v); err != nil { if err := kb.handler(g, v); err != nil {
return false, err return err
} }
return true, nil return nil
} }
func (g *Gui) onFocus(ev *GocuiEvent) error { func (g *Gui) onFocus(ev *GocuiEvent) error {

View File

@ -363,6 +363,7 @@ func (g *Gui) pollEvent() GocuiEvent {
mouseKey = MouseRight mouseKey = MouseRight
case tcell.ButtonMiddle: case tcell.ButtonMiddle:
mouseKey = MouseMiddle mouseKey = MouseMiddle
default:
} }
} }
@ -374,11 +375,13 @@ func (g *Gui) pollEvent() GocuiEvent {
dragState = NOT_DRAGGING dragState = NOT_DRAGGING
case tcell.ButtonSecondary: case tcell.ButtonSecondary:
case tcell.ButtonMiddle: case tcell.ButtonMiddle:
default:
} }
mouseMod = Modifier(lastMouseMod) mouseMod = Modifier(lastMouseMod)
lastMouseMod = tcell.ModNone lastMouseMod = tcell.ModNone
lastMouseKey = tcell.ButtonNone lastMouseKey = tcell.ButtonNone
} }
default:
} }
if !wheeling { if !wheeling {

View File

@ -378,6 +378,7 @@ type viewLine struct {
type cell struct { type cell struct {
chr rune chr rune
bgColor, fgColor Attribute bgColor, fgColor Attribute
hyperlink string
} }
type lineType []cell type lineType []cell
@ -851,9 +852,10 @@ func (v *View) parseInput(ch rune, x int, _ int) (bool, []cell) {
repeatCount = tabStop - (x % tabStop) repeatCount = tabStop - (x % tabStop)
} }
c := cell{ c := cell{
fgColor: v.ei.curFgColor, fgColor: v.ei.curFgColor,
bgColor: v.ei.curBgColor, bgColor: v.ei.curBgColor,
chr: ch, hyperlink: v.ei.hyperlink,
chr: ch,
} }
for i := 0; i < repeatCount; i++ { for i := 0; i < repeatCount; i++ {
cells = append(cells, c) cells = append(cells, c)
@ -1188,6 +1190,9 @@ func (v *View) draw() error {
if bgColor == ColorDefault { if bgColor == ColorDefault {
bgColor = v.BgColor bgColor = v.BgColor
} }
if c.hyperlink != "" {
fgColor |= AttrUnderline
}
if err := v.setRune(x, y, c.chr, fgColor, bgColor); err != nil { if err := v.setRune(x, y, c.chr, fgColor, bgColor); err != nil {
return err return err

2
vendor/modules.txt vendored
View File

@ -172,7 +172,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem
github.com/jesseduffield/go-git/v5/utils/merkletrie/index github.com/jesseduffield/go-git/v5/utils/merkletrie/index
github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame
github.com/jesseduffield/go-git/v5/utils/merkletrie/noder github.com/jesseduffield/go-git/v5/utils/merkletrie/noder
# github.com/jesseduffield/gocui v0.3.1-0.20240824081936-a3adeb73f602 # github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9
## explicit; go 1.12 ## explicit; go 1.12
github.com/jesseduffield/gocui github.com/jesseduffield/gocui
# github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 # github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10