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:
+1
-1
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
)
|
||||
|
||||
func TestCmdObjToString(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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,7 +1,7 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,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,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"
|
||||
)
|
||||
|
||||
@@ -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,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"
|
||||
)
|
||||
|
||||
@@ -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,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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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,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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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,7 +1,7 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user