1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2026-05-22 10:15:43 +02:00

Copy gocui into lazygit repo (#5561)

Over the past few months or even years, [Jesse's gocui
fork](https://github.com/jesseduffield/gocui) has become more and more
tied to lazygit; I have repeatedly made API-breaking changes to it
without caring much about what this means for other clients like
lazydocker or lazynpm (and Jesse was ok with that).

Given that situation, it no longer makes much sense to maintain it in a
standalone repo, so copy it into lazygit; this will greatly reduce the
friction of making changes to it. If/when the time comes to update those
other clients to also benefit from the improvements we make here, we can
always copy the files back to the gocui fork and resume it there.
This commit is contained in:
Stefan Haller
2026-04-30 22:14:07 +02:00
committed by GitHub
131 changed files with 1882 additions and 427 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
skip = .git*,go.sum,*.lock,.codespellrc,vendor,translations,Keybindings_*.md
skip = .git*,go.sum,*.lock,.codespellrc,vendor,translations,Keybindings_*.md,./pkg/gocui
check-hidden = true
# camel-cased
ignore-regex = (\b[A-Za-z][a-z]*[A-Z]\S+\b|\.edn\b|\S+…|\\nd\b)
-1
View File
@@ -18,7 +18,6 @@ require (
github.com/gookit/color v1.6.0
github.com/integrii/flaggy v1.8.0
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c
github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3
-2
View File
@@ -50,8 +50,6 @@ github.com/invopop/jsonschema v0.10.0 h1:c1ktzNLBun3LyQQhyty5WE3lulbOdIIyOVlkmDL
github.com/invopop/jsonschema v0.10.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c h1:tC2PaiisXAC5sOjDPfMArSnbswDObtCssx+xn28edX4=
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c/go.mod h1:F2fEBk0ddf6ixrBrJjY7phfQ3hL9rXG0uSjvwYe50bE=
github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980 h1:LEZwOrBm9S+4lRlXpoz+RSzSvhOVE+6v/Rk+A7Kg00Q=
github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980/go.mod h1:lQCd2TvvNXVKFBowy4A7xxZbUp+1KEiGs4j0Q5Zt9gQ=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/samber/lo"
)
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/gocui"
)
type SyncCommands struct {
+1 -1
View File
@@ -3,8 +3,8 @@ package git_commands
import (
"testing"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/stretchr/testify/assert"
)
+1 -1
View File
@@ -3,8 +3,8 @@ package git_commands
import (
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/gocui"
)
type TagCommands struct {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os/exec"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/samber/lo"
"github.com/sasha-s/go-deadlock"
)
@@ -4,7 +4,7 @@ import (
"strings"
"testing"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/utils"
)
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os/exec"
"testing"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
)
func TestCmdObjToString(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"strings"
"unicode/utf8"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/samber/lo"
)
+160
View File
@@ -0,0 +1,160 @@
package gocui
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseOne(t *testing.T) {
var ei *escapeInterpreter
ei = newEscapeInterpreter(OutputNormal)
isEscape, err := ei.parseOne([]byte{'a'})
assert.Equal(t, false, isEscape)
assert.NoError(t, err)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b[0K")
_, ok := ei.instruction.(eraseInLineFromCursor)
assert.Equal(t, true, ok)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b[K")
_, ok = ei.instruction.(eraseInLineFromCursor)
assert.Equal(t, true, ok)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b[1K")
_, ok = ei.instruction.(noInstruction)
assert.Equal(t, true, ok)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b(B")
_, ok = ei.instruction.(noInstruction)
assert.Equal(t, true, ok)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b)0")
_, ok = ei.instruction.(noInstruction)
assert.Equal(t, true, ok)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b*A")
_, ok = ei.instruction.(noInstruction)
assert.Equal(t, true, ok)
ei = newEscapeInterpreter(OutputNormal)
parseEscRunes(t, ei, "\x1b+K")
_, ok = ei.instruction.(noInstruction)
assert.Equal(t, true, ok)
}
func TestParseOneColours(t *testing.T) {
scenarios := []struct {
outputMode OutputMode
input string
expectedFg Attribute
expectedBg Attribute
}{
{OutputNormal, "\x1b[30m", ColorBlack, ColorDefault},
{OutputNormal, "\x1b[31m", ColorRed, ColorDefault},
{OutputNormal, "\x1b[32m", ColorGreen, ColorDefault},
{OutputNormal, "\x1b[33m", ColorYellow, ColorDefault},
{OutputNormal, "\x1b[34m", ColorBlue, ColorDefault},
{OutputNormal, "\x1b[35m", ColorMagenta, ColorDefault},
{OutputNormal, "\x1b[36m", ColorCyan, ColorDefault},
{OutputNormal, "\x1b[37m", ColorWhite, ColorDefault},
{OutputNormal, "\x1b[40m", ColorDefault, ColorBlack},
{OutputNormal, "\x1b[41m", ColorDefault, ColorRed},
{OutputNormal, "\x1b[42m", ColorDefault, ColorGreen},
{OutputNormal, "\x1b[43m", ColorDefault, ColorYellow},
{OutputNormal, "\x1b[44m", ColorDefault, ColorBlue},
{OutputNormal, "\x1b[45m", ColorDefault, ColorMagenta},
{OutputNormal, "\x1b[46m", ColorDefault, ColorCyan},
{OutputNormal, "\x1b[47m", ColorDefault, ColorWhite},
{OutputNormal, "\x1b[47;31m", ColorRed, ColorWhite},
{OutputNormal, "\x1b[90m", Get256Color(8), ColorDefault},
{OutputNormal, "\x1b[91m", Get256Color(9), ColorDefault},
{OutputNormal, "\x1b[92m", Get256Color(10), ColorDefault},
{OutputNormal, "\x1b[93m", Get256Color(11), ColorDefault},
{OutputNormal, "\x1b[94m", Get256Color(12), ColorDefault},
{OutputNormal, "\x1b[95m", Get256Color(13), ColorDefault},
{OutputNormal, "\x1b[96m", Get256Color(14), ColorDefault},
{OutputNormal, "\x1b[97m", Get256Color(15), ColorDefault},
{OutputNormal, "\x1b[100m", ColorDefault, Get256Color(8)},
{OutputNormal, "\x1b[101m", ColorDefault, Get256Color(9)},
{OutputNormal, "\x1b[102m", ColorDefault, Get256Color(10)},
{OutputNormal, "\x1b[103m", ColorDefault, Get256Color(11)},
{OutputNormal, "\x1b[104m", ColorDefault, Get256Color(12)},
{OutputNormal, "\x1b[105m", ColorDefault, Get256Color(13)},
{OutputNormal, "\x1b[106m", ColorDefault, Get256Color(14)},
{OutputNormal, "\x1b[107m", ColorDefault, Get256Color(15)},
{Output256, "\x1b[38;5;32m", Get256Color(32), ColorDefault},
{OutputTrue, "\x1b[38;5;32m", Get256Color(32), ColorDefault},
{OutputTrue, "\x1b[38;2;50;103;205m", NewRGBColor(50, 103, 205), ColorDefault},
{Output256, "\x1b[48;5;32m", ColorDefault, Get256Color(32)},
{OutputTrue, "\x1b[48;5;32m", ColorDefault, Get256Color(32)},
{OutputTrue, "\x1b[48;2;50;103;205m", ColorDefault, NewRGBColor(50, 103, 205)},
{OutputTrue, "\x1b[1;95;48;2;255;224;224m", Get256Color(13), NewRGBColor(255, 224, 224)},
}
for _, scenario := range scenarios {
ei := newEscapeInterpreter(scenario.outputMode)
parseEscRunes(t, ei, scenario.input)
assert.Equal(t, scenario.expectedFg, ei.curFgColor&AttrColorBits)
assert.Equal(t, scenario.expectedBg, ei.curBgColor)
}
// resetting colours
scenarios = []struct {
outputMode OutputMode
input string
expectedFg Attribute
expectedBg Attribute
}{
{OutputNormal, "\x1b[39m", ColorDefault, ColorRed},
{OutputNormal, "\x1b[49m", ColorRed, ColorDefault},
{OutputNormal, "\x1b[0m", ColorDefault, ColorDefault},
}
for _, scenario := range scenarios {
ei := newEscapeInterpreter(scenario.outputMode)
ei.curFgColor = ColorRed
ei.curBgColor = ColorRed
parseEscRunes(t, ei, scenario.input)
assert.Equal(t, scenario.expectedFg, ei.curFgColor)
assert.Equal(t, scenario.expectedBg, ei.curBgColor)
}
// setting attributes
attrScenarios := []struct {
outputMode OutputMode
input string
expectedAttr Attribute
}{
{OutputNormal, "\x1b[1m", AttrBold},
{OutputNormal, "\x1b[2m", AttrDim},
{OutputNormal, "\x1b[3m", AttrItalic},
{OutputNormal, "\x1b[4m", AttrUnderline},
{OutputNormal, "\x1b[5m", AttrBlink},
{OutputNormal, "\x1b[7m", AttrReverse},
{OutputNormal, "\x1b[9m", AttrStrikeThrough},
}
for _, scenario := range attrScenarios {
ei := newEscapeInterpreter(scenario.outputMode)
parseEscRunes(t, ei, scenario.input)
style := ei.curFgColor & AttrStyleBits
assert.Equal(t, scenario.expectedAttr, style)
}
}
func parseEscRunes(t *testing.T, ei *escapeInterpreter, runes string) {
t.Helper()
for _, b := range []byte(runes) {
isEscape, err := ei.parseOne([]byte{b})
assert.Equal(t, true, isEscape)
assert.NoError(t, err)
}
}
@@ -5,10 +5,8 @@
package gocui
import (
"context"
standardErrors "errors"
"runtime"
"slices"
"strings"
"sync"
"time"
@@ -25,15 +23,6 @@ type OutputMode int
const DOUBLE_CLICK_THRESHOLD = 500 * time.Millisecond
var (
// ErrAlreadyBlacklisted is returned when the keybinding is already blacklisted.
ErrAlreadyBlacklisted = standardErrors.New("keybind already blacklisted")
// ErrBlacklisted is returned when the keybinding being parsed / used is blacklisted.
ErrBlacklisted = standardErrors.New("keybind blacklisted")
// ErrNotBlacklisted is returned when a keybinding being whitelisted is not blacklisted.
ErrNotBlacklisted = standardErrors.New("keybind not blacklisted")
// ErrNoSuchKeybind is returned when the keybinding being parsed does not exist.
ErrNoSuchKeybind = standardErrors.New("no such keybind")
@@ -105,10 +94,6 @@ type ViewMouseBindingOpts struct {
}
type GuiMutexes struct {
// tickingMutex ensures we don't have two loops ticking. The point of 'ticking'
// is to refresh the gui rapidly so that loader characters can be animated.
tickingMutex sync.Mutex
ViewsMutex sync.Mutex
}
@@ -155,7 +140,6 @@ type Gui struct {
maxX, maxY int
outputMode OutputMode
stop chan struct{}
blacklist []Key
// BgColor and FgColor allow to configure the background and foreground
// colors of the GUI.
@@ -573,10 +557,6 @@ func (g *Gui) SetKeybinding(viewname string, key any, mod Modifier, handler func
return err
}
if g.isBlacklisted(k) {
return ErrBlacklisted
}
kb = newKeybinding(viewname, k, ch, mod, handler)
g.keybindings = append(g.keybindings, kb)
return nil
@@ -632,26 +612,6 @@ func (g *Gui) SetViewClickBinding(binding *ViewMouseBinding) error {
return nil
}
// BlackListKeybinding adds a keybinding to the blacklist
func (g *Gui) BlacklistKeybinding(k Key) error {
if slices.Contains(g.blacklist, k) {
return ErrAlreadyBlacklisted
}
g.blacklist = append(g.blacklist, k)
return nil
}
// WhiteListKeybinding removes a keybinding from the blacklist
func (g *Gui) WhitelistKeybinding(k Key) error {
for i, j := range g.blacklist {
if j == k {
g.blacklist = append(g.blacklist[:i], g.blacklist[i+1:]...)
return nil
}
}
return ErrNotBlacklisted
}
func (g *Gui) SetFocusHandler(handler func(bool) error) {
g.focusHandler = handler
}
@@ -947,9 +907,9 @@ func calcScrollbarRune(
) rune {
if showScrollbar && (position >= scrollbarStart && position <= scrollbarEnd) {
return '▐'
} else {
return runeV
}
return runeV
}
func calcRealScrollbarStartEnd(v *View) (bool, int, int) {
@@ -1616,10 +1576,6 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) error {
// execKeybinding executes a given keybinding
func (g *Gui) execKeybinding(v *View, kb *keybinding) error {
if g.isBlacklisted(kb.key) {
return nil
}
if err := kb.handler(g, v); err != nil {
return err
}
@@ -1634,42 +1590,6 @@ func (g *Gui) onFocus(ev *GocuiEvent) error {
return nil
}
func (g *Gui) StartTicking(ctx context.Context) {
go func() {
g.Mutexes.tickingMutex.Lock()
defer g.Mutexes.tickingMutex.Unlock()
ticker := time.NewTicker(time.Millisecond * 50)
defer ticker.Stop()
outer:
for {
select {
case <-ticker.C:
// I'm okay with having a data race here: there's no harm in letting one of these updates through
if g.suspended {
continue outer
}
for _, view := range g.Views() {
if view.HasLoader {
g.UpdateAsync(func(g *Gui) error { return nil })
continue outer
}
}
return
case <-ctx.Done():
return
case <-g.stop:
return
}
}
}()
}
// isBlacklisted reports whether the key is blacklisted
func (g *Gui) isBlacklisted(k Key) bool {
return slices.Contains(g.blacklist, k)
}
func (g *Gui) Suspend() error {
g.suspendedMutex.Lock()
defer g.suspendedMutex.Unlock()
@@ -13,9 +13,7 @@ import (
)
type (
wchar uint16
short int16
dword uint32
word uint16
)
@@ -5,8 +5,6 @@
package gocui
import (
"strings"
"github.com/gdamore/tcell/v2"
)
@@ -26,71 +24,6 @@ type keybinding struct {
handler func(*Gui, *View) error
}
// Parse takes the input string and extracts the keybinding.
// Returns a Key / rune, a Modifier and an error.
func Parse(input string) (any, Modifier, error) {
if len(input) == 1 {
_, r, err := getKey(rune(input[0]))
if err != nil {
return nil, ModNone, err
}
return r, ModNone, nil
}
var modifier Modifier
cleaned := make([]string, 0)
tokens := strings.SplitSeq(input, "+")
for t := range tokens {
normalized := strings.Title(strings.ToLower(t))
if t == "Alt" {
modifier = ModAlt
continue
}
cleaned = append(cleaned, normalized)
}
key, exist := translate[strings.Join(cleaned, "")]
if !exist {
return nil, ModNone, ErrNoSuchKeybind
}
return key, modifier, nil
}
// ParseAll takes an array of strings and returns a map of all keybindings.
func ParseAll(input []string) (map[any]Modifier, error) {
ret := make(map[any]Modifier)
for _, i := range input {
k, m, err := Parse(i)
if err != nil {
return ret, err
}
ret[k] = m
}
return ret, nil
}
// MustParse takes the input string and returns a Key / rune and a Modifier.
// It will panic if any error occured.
func MustParse(input string) (any, Modifier) {
k, m, err := Parse(input)
if err != nil {
panic(err)
}
return k, m
}
// MustParseAll takes an array of strings and returns a map of all keybindings.
// It will panic if any error occured.
func MustParseAll(input []string) map[any]Modifier {
result, err := ParseAll(input)
if err != nil {
panic(err)
}
return result
}
// newKeybinding returns a new Keybinding object.
func newKeybinding(viewname string, key Key, ch rune, mod Modifier, handler func(*Gui, *View) error) (kb *keybinding) {
kb = &keybinding{
@@ -122,87 +55,6 @@ func (kb *keybinding) matchKeypress(key Key, ch rune, mod Modifier) bool {
return kb.key == key && kb.ch == ch && kb.mod == mod
}
// translations for strings to keys
var translate = map[string]Key{
"F1": KeyF1,
"F2": KeyF2,
"F3": KeyF3,
"F4": KeyF4,
"F5": KeyF5,
"F6": KeyF6,
"F7": KeyF7,
"F8": KeyF8,
"F9": KeyF9,
"F10": KeyF10,
"F11": KeyF11,
"F12": KeyF12,
"Insert": KeyInsert,
"Delete": KeyDelete,
"Home": KeyHome,
"End": KeyEnd,
"Pgup": KeyPgup,
"Pgdn": KeyPgdn,
"ArrowUp": KeyArrowUp,
"ShiftArrowUp": KeyShiftArrowUp,
"ArrowDown": KeyArrowDown,
"ShiftArrowDown": KeyShiftArrowDown,
"ArrowLeft": KeyArrowLeft,
"ArrowRight": KeyArrowRight,
"CtrlTilde": KeyCtrlTilde,
"Ctrl2": KeyCtrl2,
"CtrlSpace": KeyCtrlSpace,
"CtrlA": KeyCtrlA,
"CtrlB": KeyCtrlB,
"CtrlC": KeyCtrlC,
"CtrlD": KeyCtrlD,
"CtrlE": KeyCtrlE,
"CtrlF": KeyCtrlF,
"CtrlG": KeyCtrlG,
"Backspace": KeyBackspace,
"CtrlH": KeyCtrlH,
"Tab": KeyTab,
"BackTab": KeyBacktab,
"CtrlI": KeyCtrlI,
"CtrlJ": KeyCtrlJ,
"CtrlK": KeyCtrlK,
"CtrlL": KeyCtrlL,
"Enter": KeyEnter,
"CtrlM": KeyCtrlM,
"CtrlN": KeyCtrlN,
"CtrlO": KeyCtrlO,
"CtrlP": KeyCtrlP,
"CtrlQ": KeyCtrlQ,
"CtrlR": KeyCtrlR,
"CtrlS": KeyCtrlS,
"CtrlT": KeyCtrlT,
"CtrlU": KeyCtrlU,
"CtrlV": KeyCtrlV,
"CtrlW": KeyCtrlW,
"CtrlX": KeyCtrlX,
"CtrlY": KeyCtrlY,
"CtrlZ": KeyCtrlZ,
"Esc": KeyEsc,
"CtrlLsqBracket": KeyCtrlLsqBracket,
"Ctrl3": KeyCtrl3,
"Ctrl4": KeyCtrl4,
"CtrlBackslash": KeyCtrlBackslash,
"Ctrl5": KeyCtrl5,
"CtrlRsqBracket": KeyCtrlRsqBracket,
"Ctrl6": KeyCtrl6,
"Ctrl7": KeyCtrl7,
"CtrlSlash": KeyCtrlSlash,
"CtrlUnderscore": KeyCtrlUnderscore,
"Space": KeySpace,
"Backspace2": KeyBackspace2,
"Ctrl8": KeyCtrl8,
"Mouseleft": MouseLeft,
"Mousemiddle": MouseMiddle,
"Mouseright": MouseRight,
"Mouserelease": MouseRelease,
"MousewheelUp": MouseWheelUp,
"MousewheelDown": MouseWheelDown,
}
// Special keys.
const (
KeyF1 Key = Key(tcell.KeyF1)
+114
View File
@@ -0,0 +1,114 @@
package gocui
import "testing"
func TestCalcScrollbar(t *testing.T) {
tests := []struct {
testName string
listSize int
pageSize int
position int
scrollAreaSize int
expectedStart int
expectedHeight int
}{
{
testName: "page size greater than list size",
listSize: 5,
pageSize: 10,
position: 0,
scrollAreaSize: 20,
expectedStart: 0,
expectedHeight: 20,
},
{
testName: "page size matches list size",
listSize: 10,
pageSize: 10,
position: 0,
scrollAreaSize: 20,
expectedStart: 0,
expectedHeight: 20,
},
{
testName: "page size half of list size",
listSize: 10,
pageSize: 5,
position: 0,
scrollAreaSize: 20,
expectedStart: 0,
expectedHeight: 10,
},
{
testName: "page size half of list size at scroll end",
listSize: 10,
pageSize: 5,
position: 5,
scrollAreaSize: 20,
expectedStart: 10,
expectedHeight: 10,
},
{
testName: "page size third of list size having scrolled half the way",
listSize: 15,
// Recall that my max position is listSize - pageSize i.e 15 - 5 i.e. 10.
// So if I've scrolled to position 5 that means I've done one page and I've got
// one page to go which means by scrollbar should take up a third of the available
// space and appear in the centre of the scrollbar area
pageSize: 5,
position: 5,
scrollAreaSize: 21,
expectedStart: 7,
expectedHeight: 7,
},
{
testName: "page size third of list size having scrolled the full way",
listSize: 15,
pageSize: 5,
position: 10,
scrollAreaSize: 21,
expectedStart: 14,
expectedHeight: 7,
},
{
testName: "page size third of list size having scrolled by one",
listSize: 15,
pageSize: 5,
position: 1,
scrollAreaSize: 21,
expectedStart: 2,
expectedHeight: 7,
},
{
testName: "page size third of list size having scrolled up from the bottom by one",
listSize: 15,
pageSize: 5,
position: 9,
scrollAreaSize: 21,
expectedStart: 12,
expectedHeight: 7,
},
}
for _, test := range tests {
t.Run(test.testName, func(t *testing.T) {
start, height := calcScrollbar(test.listSize, test.pageSize, test.position, test.scrollAreaSize)
if start != test.expectedStart {
t.Errorf("expected start to be %d, got %d", test.expectedStart, start)
}
if height != test.expectedHeight {
t.Errorf("expected height to be %d, got %d", test.expectedHeight, height)
}
})
}
}
@@ -55,17 +55,20 @@ var runeReplacements = map[rune]string{
func (g *Gui) tcellInit(runeReplacements map[rune]string) error {
tcell.SetEncodingFallback(tcell.EncodingFallbackASCII)
if s, e := tcell.NewScreen(); e != nil {
s, e := tcell.NewScreen()
if e != nil {
return e
} else if e = s.Init(); e != nil {
return e
} else {
registerRuneFallbacks(s, runeReplacements)
g.screen = s
Screen = s
return nil
}
if e = s.Init(); e != nil {
return e
}
registerRuneFallbacks(s, runeReplacements)
g.screen = s
Screen = s
return nil
}
func registerRuneFallbacks(s tcell.Screen, additional map[rune]string) {
@@ -83,15 +86,15 @@ func (g *Gui) tcellInitSimulation(width int, height int) error {
s := tcell.NewSimulationScreen("")
if e := s.Init(); e != nil {
return e
} else {
g.screen = s
Screen = s
// setting to a larger value than the typical terminal size
// so that during a test we're more likely to see an item to select in a view.
s.SetSize(width, height)
s.Sync()
return nil
}
g.screen = s
Screen = s
// setting to a larger value than the typical terminal size
// so that during a test we're more likely to see an item to select in a view.
s.SetSize(width, height)
s.Sync()
return nil
}
// tcellSetCell sets the character cell at a given location to the given
@@ -194,9 +197,9 @@ const (
var (
lastMouseKey tcell.ButtonMask = tcell.ButtonNone
lastMouseMod tcell.ModMask = tcell.ModNone
dragState int = NOT_DRAGGING
lastX int = 0
lastY int = 0
dragState = NOT_DRAGGING
lastX = 0
lastY = 0
)
// this wrapper struct has public keys so we can easily serialize/deserialize to JSON
File diff suppressed because it is too large Load Diff
@@ -164,9 +164,6 @@ type View struct {
// Overlaps describes which edges are overlapping with another view's edges
Overlaps byte
// If HasLoader is true, the message will be appended with a spinning loader animation
HasLoader bool
// ParentView is the view which catches events bubbled up from the given view if there's no matching handler
ParentView *View
@@ -881,9 +878,9 @@ func (v *View) writeString(s string) {
var linkStartChars = []string{"h", "t", "t", "p", "s", ":", "/", "/"}
func findLinkStart(line []cell) int {
for i := 0; i < len(line)-len(linkStartChars); i++ {
for i := range len(line) - len(linkStartChars) {
for j := range linkStartChars {
if line[i+j].chr != string(linkStartChars[j]) {
if line[i+j].chr != linkStartChars[j] {
break
}
if j == len(linkStartChars)-1 {
@@ -899,7 +896,7 @@ func findLinkStart(line []cell) int {
// enough, because in markdown it's common to have a hyperlink followed by a
// ')', so we want to stop there. Hopefully URLs containing ')' are uncommon
// enough that this is not a problem.
var lineEndCharacters map[string]bool = map[string]bool{
var lineEndCharacters = map[string]bool{
"": true,
" ": true,
"\n": true,
@@ -927,7 +924,7 @@ func (v *View) autoRenderHyperlinksInCurrentLine() {
if _, ok := lineEndCharacters[line[linkEnd].chr]; ok {
break
}
link.WriteString(string(line[linkEnd].chr))
link.WriteString(line[linkEnd].chr)
}
for i := linkStart; i < linkEnd; i++ {
v.lines[v.wy][i].hyperlink = link.String()
@@ -988,7 +985,7 @@ func (v *View) parseInput(ch []byte, width int, x int, _ int) (bool, []cell) {
chr: string(ch),
width: width,
}
for i := 0; i < repeatCount; i++ {
for range repeatCount {
cells = append(cells, c)
}
}
@@ -1265,21 +1262,17 @@ func (v *View) draw() {
cellIdx := 0
var c cell
for {
if x >= maxX {
break
}
for x < maxX {
if x < 0 {
if cellIdx < len(vline.line) {
x += uniseg.StringWidth(vline.line[cellIdx].chr)
cellIdx++
continue
} else {
// no more characters to write so we're only going to be printing empty cells
// past this point
x = 0
}
// no more characters to write so we're only going to be printing empty cells
// past this point
x = 0
}
// if we're out of cells to write, we'll just print empty cells.
@@ -1319,9 +1312,6 @@ func (v *View) refreshViewLinesIfNeeded() {
maxX := v.InnerWidth()
lineIdx := 0
lines := v.lines
if v.HasLoader {
lines = v.loaderLines()
}
for i, line := range lines {
wrap := 0
if v.Wrap {
@@ -1340,9 +1330,7 @@ func (v *View) refreshViewLinesIfNeeded() {
lineIdx++
}
}
if !v.HasLoader {
v.tainted = false
}
v.tainted = false
}
}
@@ -1424,7 +1412,7 @@ func (v *View) BufferLines() []string {
lines := make([]string, len(v.lines))
for i, l := range v.lines {
str := lineType(l).String()
str = strings.Replace(str, "\x00", "", -1)
str = strings.ReplaceAll(str, "\x00", "")
lines[i] = str
}
return lines
@@ -1447,7 +1435,7 @@ func (v *View) ViewBufferLines() []string {
lines := make([]string, len(v.viewLines))
for i, l := range v.viewLines {
str := lineType(l.line).String()
str = strings.Replace(str, "\x00", "", -1)
str = strings.ReplaceAll(str, "\x00", "")
lines[i] = str
}
return lines
@@ -1696,7 +1684,7 @@ func (v *View) SelectedLines() []string {
func (v *View) lineContentAtIdx(idx int) string {
line := v.lines[idx]
str := lineType(line).String()
return strings.Replace(str, "\x00", "", -1)
return strings.ReplaceAll(str, "\x00", "")
}
func (v *View) SelectedPoint() (int, int) {
@@ -1719,9 +1707,9 @@ func (v *View) SelectedLineRange() (int, int) {
if start > end {
return end, start
} else {
return start, end
}
return start, end
}
func (v *View) RenderTextArea() {
@@ -1773,7 +1761,7 @@ func (v *View) overwriteLines(y int, content string) {
v.wy = y
v.clearViewLines()
lines := strings.Replace(content, "\n", "\x1b[K\n", -1)
lines := strings.ReplaceAll(content, "\n", "\x1b[K\n")
// If the last line doesn't end with a linefeed, add the erase command at
// the end too
if !strings.HasSuffix(lines, "\n") {
@@ -1799,7 +1787,7 @@ func (v *View) OverwriteLinesAndClearEverythingElse(lineCount int, y int, conten
v.overwriteLines(y, content)
for i := 0; i < y; i += 1 {
for i := range y {
v.lines[i] = nil
}
@@ -1924,9 +1912,9 @@ func (v *View) adjustDownwardScrollAmount(scrollHeight int) int {
}
if oy+scrollHeight < 0 {
return 0
} else {
return scrollHeight
}
return scrollHeight
}
// scrollMargin is about how many lines must still appear if you scroll
@@ -1938,9 +1926,9 @@ func (v *View) scrollMargin() int {
// we should make this into a field on the view to be configured by the client.
// For now we're hardcoding it.
return 2
} else {
return 0
}
return 0
}
// Returns true if the view contains a line containing the given text with the given
@@ -1966,7 +1954,7 @@ func containsColoredTextInLine(fgColorStr string, text string, line []cell) bool
cellColor := tcell.NewHexColor(cell.fgColor.Hex())
if cellColor == fgColor {
currentMatch += string(cell.chr)
currentMatch += cell.chr
} else if currentMatch != "" {
if strings.Contains(currentMatch, text) {
return true
+415
View File
@@ -0,0 +1,415 @@
// Copyright 2014 The gocui Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gocui
import (
"strings"
"testing"
"github.com/rivo/uniseg"
"github.com/stretchr/testify/assert"
)
func TestWriteString(t *testing.T) {
tests := []struct {
existingLines []string
stringsToWrite []string
expectedLines [][]string
}{
{
[]string{},
[]string{""},
[][]string{{}},
},
{
[]string{},
[]string{"1\n"},
[][]string{{"1", ""}},
},
{
[]string{},
[]string{"1\n", "2\n"},
[][]string{{"1", ""}, {"2", ""}},
},
{
[]string{"a"},
[]string{"1\n"},
[][]string{{"1", ""}},
},
{
[]string{"a\x00"},
[]string{"1\n"},
[][]string{{"1", "\x00"}},
},
{
[]string{"ab"},
[]string{"1\n"},
[][]string{{"1", "b"}},
},
{
[]string{"abc"},
[]string{"1\n"},
[][]string{{"1", "b", "c"}},
},
{
[]string{},
[]string{"1\r"},
[][]string{{"1", ""}},
},
{
[]string{"a"},
[]string{"1\r"},
[][]string{{"1", ""}},
},
{
[]string{"a\x00"},
[]string{"1\r"},
[][]string{{"1", "\x00"}},
},
{
[]string{"ab"},
[]string{"1\r"},
[][]string{{"1", "b"}},
},
{
[]string{"abc"},
[]string{"1\r"},
[][]string{{"1", "b", "c"}},
},
}
for _, test := range tests {
v := NewView("name", 0, 0, 10, 10, OutputNormal)
for _, l := range test.existingLines {
v.lines = append(v.lines, stringToCells(l))
}
for _, s := range test.stringsToWrite {
v.writeString(s)
}
var resultingLines [][]string
for _, l := range v.lines {
resultingLines = append(resultingLines, cellsToStrings(l))
}
assert.Equal(t, test.expectedLines, resultingLines)
}
}
func TestUpdatedCursorAndOrigin(t *testing.T) {
tests := []struct {
prevOrigin int
size int
cursor int
expectedCursor int
expectedOrigin int
}{
{0, 10, 0, 0, 0},
{0, 10, 9, 9, 0},
{0, 10, 10, 9, 1},
{0, 10, 19, 9, 10},
{0, 10, 20, 9, 11},
{20, 10, 19, 0, 19},
{20, 10, 25, 5, 20},
}
for _, test := range tests {
cursor, origin := updatedCursorAndOrigin(test.prevOrigin, test.size, test.cursor)
assert.EqualValues(t, test.expectedCursor, cursor, "Cursor is wrong")
assert.EqualValues(t, test.expectedOrigin, origin, "Origin in wrong")
}
}
func TestAutoRenderingHyperlinks(t *testing.T) {
v := NewView("name", 0, 0, 10, 10, OutputNormal)
v.AutoRenderHyperLinks = true
v.writeString("htt")
// No hyperlinks are generated for incomplete URLs
assert.Equal(t, "", v.lines[0][0].hyperlink)
// Writing more characters to the same line makes the link complete (even
// though we didn't see a newline yet)
v.writeString("ps://example.com")
assert.Equal(t, "https://example.com", v.lines[0][0].hyperlink)
v.Clear()
// Valid but incomplete URL
v.writeString("https://exa")
assert.Equal(t, "https://exa", v.lines[0][0].hyperlink)
// Writing more characters to the same fixes the link
v.writeString("mple.com")
assert.Equal(t, "https://example.com", v.lines[0][0].hyperlink)
}
func TestContainsColoredText(t *testing.T) {
hexColor := func(text string, hexStr string) []cell {
cells := make([]cell, len(text))
hex := GetColor(hexStr)
for i, chr := range text {
cells[i] = cell{fgColor: hex, chr: string(chr)}
}
return cells
}
red := "#ff0000"
green := "#00ff00"
redStr := func(text string) []cell { return hexColor(text, red) }
greenStr := func(text string) []cell { return hexColor(text, green) }
concat := func(lines ...[]cell) []cell {
var cells []cell
for _, line := range lines {
cells = append(cells, line...)
}
return cells
}
tests := []struct {
lines [][]cell
fgColorStr string
text string
expected bool
}{
{
lines: [][]cell{concat(redStr("a"))},
fgColorStr: red,
text: "a",
expected: true,
},
{
lines: [][]cell{concat(redStr("a"))},
fgColorStr: red,
text: "b",
expected: false,
},
{
lines: [][]cell{concat(redStr("a"))},
fgColorStr: green,
text: "b",
expected: false,
},
{
lines: [][]cell{concat(redStr("hel"), greenStr("lo"), redStr(" World!"))},
fgColorStr: red,
text: "hello",
expected: false,
},
{
lines: [][]cell{concat(redStr("hel"), greenStr("lo"), redStr(" World!"))},
fgColorStr: green,
text: "lo",
expected: true,
},
{
lines: [][]cell{
redStr("hel"),
redStr("lo"),
},
fgColorStr: red,
text: "hello",
expected: false,
},
}
for i, test := range tests {
v := &View{lines: test.lines}
assert.Equal(t, test.expected, v.ContainsColoredText(test.fgColorStr, test.text), "Test %d failed", i)
}
}
func stringToCells(s string) []cell {
var cells []cell
state := -1
for len(s) > 0 {
var c string
var w int
c, s, w, state = uniseg.FirstGraphemeClusterInString(s, state)
cells = append(cells, cell{chr: c, width: w})
}
return cells
}
func cellsToString(cells []cell) string {
var s strings.Builder
for _, c := range cells {
s.WriteString(c.chr)
}
return s.String()
}
func cellsToStrings(cells []cell) []string {
s := []string{}
for _, c := range cells {
s = append(s, c.chr)
}
return s
}
func TestLineWrap(t *testing.T) {
testCases := []struct {
name string
line string
columns int
expected []string
}{
{
name: "Wrap on space",
line: "Hello World",
columns: 5,
expected: []string{
"Hello",
"World",
},
},
{
name: "Wrap on hyphen",
line: "Hello-World",
columns: 6,
expected: []string{
"Hello-",
"World",
},
},
{
name: "Wrap on hyphen 2",
line: "Blah Hello-World",
columns: 12,
expected: []string{
"Blah Hello-",
"World",
},
},
{
name: "Wrap on hyphen 3",
line: "Blah Hello-World",
columns: 11,
expected: []string{
"Blah Hello-",
"World",
},
},
{
name: "Wrap on hyphen 4",
line: "Blah Hello-World",
columns: 10,
expected: []string{
"Blah Hello",
"-World",
},
},
{
name: "Wrap on space 2",
line: "Blah Hello World",
columns: 10,
expected: []string{
"Blah Hello",
"World",
},
},
{
name: "Wrap on space with more words",
line: "Longer word here",
columns: 10,
expected: []string{
"Longer",
"word here",
},
},
{
name: "Split word that's too long",
line: "ThisWordIsWayTooLong",
columns: 10,
expected: []string{
"ThisWordIs",
"WayTooLong",
},
},
{
name: "Split word that's too long over multiple lines",
line: "ThisWordIsWayTooLong",
columns: 5,
expected: []string{
"ThisW",
"ordIs",
"WayTo",
"oLong",
},
},
{
name: "Lots of hyphens",
line: "one-two-three-four-five",
columns: 8,
expected: []string{
"one-two-",
"three-",
"four-",
"five",
},
},
{
name: "Several lines using all the available width",
line: "aaa bb cc ddd-ee ff",
columns: 5,
expected: []string{
"aaa",
"bb cc",
"ddd-",
"ee ff",
},
},
{
name: "Multi-cell runes",
line: "🐤🐤🐤 🐝🐝 🙉 🦊🦊🦊-🐬🐬 🦢🦢",
columns: 9,
expected: []string{
"🐤🐤🐤",
"🐝🐝 🙉",
"🦊🦊🦊-",
"🐬🐬 🦢🦢",
},
},
{
name: "Space in last column",
line: "hello world",
columns: 6,
expected: []string{
"hello",
"world",
},
},
{
name: "Hyphen in last column",
line: "hello-world",
columns: 6,
expected: []string{
"hello-",
"world",
},
},
{
name: "English text",
line: "+The sea reach of the Thames stretched before us like the bedinnind of an interminable waterway. In the offind the sea and the sky were welded todether without a joint, and in the luminous space the tanned sails of the bardes drifting blah blah",
columns: 81,
expected: []string{
"+The sea reach of the Thames stretched before us like the bedinnind of an",
"interminable waterway. In the offind the sea and the sky were welded todether",
"without a joint, and in the luminous space the tanned sails of the bardes",
"drifting blah blah",
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
lineCells := stringToCells(tc.line)
result := lineWrap(lineCells, tc.columns)
resultStrings := make([]string, len(result))
for i, line := range result {
resultStrings[i] = cellsToString(line)
}
assert.EqualValues(t, tc.expected, resultStrings)
})
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"runtime"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
+1 -1
View File
@@ -1,7 +1,7 @@
package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -6,8 +6,8 @@ import (
"strings"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
+1 -1
View File
@@ -1,7 +1,7 @@
package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -1,7 +1,7 @@
package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
"github.com/jesseduffield/lazygit/pkg/gui/types"
deadlock "github.com/sasha-s/go-deadlock"
+1 -1
View File
@@ -1,7 +1,7 @@
package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -4,9 +4,9 @@ import (
"fmt"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
+1 -1
View File
@@ -1,7 +1,7 @@
package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -1,8 +1,8 @@
package gui
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/controllers"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands"
+1 -1
View File
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -6,9 +6,9 @@ import (
"strings"
"github.com/gookit/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -3,8 +3,8 @@ package controllers
import (
"errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types"
@@ -6,11 +6,11 @@ import (
"path/filepath"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/constants"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
@@ -5,8 +5,8 @@ import (
"fmt"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
+1 -1
View File
@@ -7,9 +7,9 @@ import (
"strings"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+1 -1
View File
@@ -3,7 +3,7 @@ package controllers
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -3,7 +3,7 @@ package helpers
import (
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/status"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -5,9 +5,9 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -6,8 +6,8 @@ import (
"strings"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
+1 -1
View File
@@ -3,9 +3,9 @@ package helpers
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -3,7 +3,7 @@ package helpers
import (
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -7,9 +7,9 @@ import (
"path/filepath"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
@@ -7,10 +7,10 @@ import (
"time"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts"
+1 -1
View File
@@ -5,9 +5,9 @@ import (
"strings"
"text/template"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+1 -1
View File
@@ -8,11 +8,11 @@ import (
"strings"
"sync"
"github.com/jesseduffield/gocui"
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/env"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
@@ -5,8 +5,8 @@ import (
"strings"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
+1 -1
View File
@@ -3,7 +3,7 @@ package helpers
import (
"errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/updates"
"github.com/jesseduffield/lazygit/pkg/utils"
+1 -1
View File
@@ -3,7 +3,7 @@ package helpers
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
@@ -4,9 +4,9 @@ import (
"errors"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -3,7 +3,7 @@ package controllers
import (
"log"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
+1 -1
View File
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -4,9 +4,9 @@ import (
"strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
+1 -1
View File
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -3,7 +3,7 @@ package controllers
import (
"os"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts"
"github.com/jesseduffield/lazygit/pkg/gui/types"
@@ -3,7 +3,7 @@ package controllers
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
@@ -3,7 +3,7 @@ package controllers
import (
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
+1 -1
View File
@@ -3,7 +3,7 @@ package controllers
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -7,8 +7,8 @@ import (
"slices"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+1 -1
View File
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -4,9 +4,9 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -6,8 +6,8 @@ import (
"strings"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/constants"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"path/filepath"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/style"
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -5,9 +5,9 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"errors"
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -1,7 +1,7 @@
package controllers
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -8,7 +8,7 @@ import (
"math/rand"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+1 -1
View File
@@ -1,7 +1,7 @@
package gui
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
)
func (gui *Gui) handleEditorKeypress(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier, allowMultiline bool) bool {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
+1 -1
View File
@@ -14,7 +14,6 @@ import (
"sync"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazycore/pkg/boxlayout"
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
"github.com/jesseduffield/lazygit/pkg/commands"
@@ -24,6 +23,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
+1 -1
View File
@@ -1,10 +1,10 @@
package gui
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/tasks"
+1 -1
View File
@@ -7,9 +7,9 @@ import (
"time"
"github.com/gdamore/tcell/v2"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"errors"
"log"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
+1 -1
View File
@@ -6,9 +6,9 @@ import (
"strings"
"unicode/utf8"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/constants"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -3,7 +3,7 @@ package gui
import (
"errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
+1 -1
View File
@@ -1,7 +1,7 @@
package gui
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"strings"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)

Some files were not shown because too many files have changed in this diff Show More