mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-25 12:24:47 +02:00
commit files kind of generalised
This commit is contained in:
parent
ddf25e14af
commit
2d90e1e8ee
@ -1045,9 +1045,14 @@ func (c *GitCommand) CherryPickCommits(commits []*Commit) error {
|
|||||||
return c.OSCommand.RunPreparedCommand(cmd)
|
return c.OSCommand.RunPreparedCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommitFiles get the specified commit files
|
// GetFilesInRef get the specified commit files
|
||||||
func (c *GitCommand) GetCommitFiles(commitSha string, patchManager *patch.PatchManager) ([]*CommitFile, error) {
|
func (c *GitCommand) GetFilesInRef(commitSha string, isStash bool, patchManager *patch.PatchManager) ([]*CommitFile, error) {
|
||||||
files, err := c.OSCommand.RunCommandWithOutput("git diff-tree --no-commit-id --name-only -r --no-renames %s", commitSha)
|
command := "git diff-tree"
|
||||||
|
if isStash {
|
||||||
|
command = "git stash show"
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := c.OSCommand.RunCommandWithOutput("%s --no-commit-id --name-only -r --no-renames %s", command, commitSha)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1083,7 +1088,7 @@ func (c *GitCommand) ShowCommitFileCmdStr(commitSha, fileName string, plain bool
|
|||||||
colorArg = "never"
|
colorArg = "never"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("git show --no-renames --color=%s %s -- %s", colorArg, commitSha, fileName)
|
return fmt.Sprintf("git diff --no-renames --color=%s %s^..%s -- %s", colorArg, commitSha, commitSha, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckoutFile checks out the file for the given commit
|
// CheckoutFile checks out the file for the given commit
|
||||||
|
@ -1852,8 +1852,8 @@ func TestGitCommandShowCommitFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandGetCommitFiles is a function.
|
// TestGitCommandGetFilesInRef is a function.
|
||||||
func TestGitCommandGetCommitFiles(t *testing.T) {
|
func TestGitCommandGetFilesInRef(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
commitSha string
|
commitSha string
|
||||||
@ -1886,7 +1886,7 @@ func TestGitCommandGetCommitFiles(t *testing.T) {
|
|||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
gitCmd.OSCommand.command = s.command
|
gitCmd.OSCommand.command = s.command
|
||||||
s.test(gitCmd.GetCommitFiles(s.commitSha, nil))
|
s.test(gitCmd.GetFilesInRef(s.commitSha, false, nil))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) mainSectionChildren() []*boxlayout.Box {
|
func (gui *Gui) mainSectionChildren() []*boxlayout.Box {
|
||||||
currentViewName := gui.currentViewName()
|
currentWindow := gui.currentWindow()
|
||||||
|
|
||||||
// if we're not in split mode we can just show the one main panel. Likewise if
|
// if we're not in split mode we can just show the one main panel. Likewise if
|
||||||
// the main panel is focused and we're in full-screen mode
|
// the main panel is focused and we're in full-screen mode
|
||||||
if !gui.isMainPanelSplit() || (gui.State.ScreenMode == SCREEN_FULL && currentViewName == "main") {
|
if !gui.isMainPanelSplit() || (gui.State.ScreenMode == SCREEN_FULL && currentWindow == "main") {
|
||||||
return []*boxlayout.Box{
|
return []*boxlayout.Box{
|
||||||
{
|
{
|
||||||
ViewName: "main",
|
Window: "main",
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,18 +28,18 @@ func (gui *Gui) mainSectionChildren() []*boxlayout.Box {
|
|||||||
|
|
||||||
return []*boxlayout.Box{
|
return []*boxlayout.Box{
|
||||||
{
|
{
|
||||||
ViewName: main,
|
Window: main,
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: secondary,
|
Window: secondary,
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getMidSectionWeights() (int, int) {
|
func (gui *Gui) getMidSectionWeights() (int, int) {
|
||||||
currentViewName := gui.currentViewName()
|
currentWindow := gui.currentWindow()
|
||||||
|
|
||||||
// we originally specified this as a ratio i.e. .20 would correspond to a weight of 1 against 4
|
// we originally specified this as a ratio i.e. .20 would correspond to a weight of 1 against 4
|
||||||
sidePanelWidthRatio := gui.Config.GetUserConfig().GetFloat64("gui.sidePanelWidth")
|
sidePanelWidthRatio := gui.Config.GetUserConfig().GetFloat64("gui.sidePanelWidth")
|
||||||
@ -51,7 +51,7 @@ func (gui *Gui) getMidSectionWeights() (int, int) {
|
|||||||
mainSectionWeight = 5 // need to shrink side panel to make way for main panels if side-by-side
|
mainSectionWeight = 5 // need to shrink side panel to make way for main panels if side-by-side
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentViewName == "main" {
|
if currentWindow == "main" {
|
||||||
if gui.State.ScreenMode == SCREEN_HALF || gui.State.ScreenMode == SCREEN_FULL {
|
if gui.State.ScreenMode == SCREEN_HALF || gui.State.ScreenMode == SCREEN_FULL {
|
||||||
sideSectionWeight = 0
|
sideSectionWeight = 0
|
||||||
}
|
}
|
||||||
@ -70,12 +70,12 @@ func (gui *Gui) infoSectionChildren(informationStr string, appStatus string) []*
|
|||||||
if gui.State.Searching.isSearching {
|
if gui.State.Searching.isSearching {
|
||||||
return []*boxlayout.Box{
|
return []*boxlayout.Box{
|
||||||
{
|
{
|
||||||
ViewName: "searchPrefix",
|
Window: "searchPrefix",
|
||||||
Size: len(SEARCH_PREFIX),
|
Size: len(SEARCH_PREFIX),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "search",
|
Window: "search",
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,8 +85,8 @@ func (gui *Gui) infoSectionChildren(informationStr string, appStatus string) []*
|
|||||||
if len(appStatus) > 0 {
|
if len(appStatus) > 0 {
|
||||||
result = append(result,
|
result = append(result,
|
||||||
&boxlayout.Box{
|
&boxlayout.Box{
|
||||||
ViewName: "appStatus",
|
Window: "appStatus",
|
||||||
Size: len(appStatus) + len(INFO_SECTION_PADDING),
|
Size: len(appStatus) + len(INFO_SECTION_PADDING),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -94,11 +94,11 @@ func (gui *Gui) infoSectionChildren(informationStr string, appStatus string) []*
|
|||||||
result = append(result,
|
result = append(result,
|
||||||
[]*boxlayout.Box{
|
[]*boxlayout.Box{
|
||||||
{
|
{
|
||||||
ViewName: "options",
|
Window: "options",
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "information",
|
Window: "information",
|
||||||
// unlike appStatus, informationStr has various colors so we need to decolorise before taking the length
|
// unlike appStatus, informationStr has various colors so we need to decolorise before taking the length
|
||||||
Size: len(INFO_SECTION_PADDING) + len(utils.Decolorise(informationStr)),
|
Size: len(INFO_SECTION_PADDING) + len(utils.Decolorise(informationStr)),
|
||||||
},
|
},
|
||||||
@ -108,7 +108,7 @@ func (gui *Gui) infoSectionChildren(informationStr string, appStatus string) []*
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getViewDimensions(informationStr string, appStatus string) map[string]boxlayout.Dimensions {
|
func (gui *Gui) getWindowDimensions(informationStr string, appStatus string) map[string]boxlayout.Dimensions {
|
||||||
width, height := gui.g.Size()
|
width, height := gui.g.Size()
|
||||||
|
|
||||||
sideSectionWeight, mainSectionWeight := gui.getMidSectionWeights()
|
sideSectionWeight, mainSectionWeight := gui.getMidSectionWeights()
|
||||||
@ -162,23 +162,23 @@ func (gui *Gui) getViewDimensions(informationStr string, appStatus string) map[s
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return boxlayout.ArrangeViews(root, 0, 0, width, height)
|
return boxlayout.ArrangeWindows(root, 0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
|
func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
|
||||||
currentCyclableViewName := gui.currentCyclableViewName()
|
currentWindow := gui.currentSideWindowName()
|
||||||
|
|
||||||
if gui.State.ScreenMode == SCREEN_FULL || gui.State.ScreenMode == SCREEN_HALF {
|
if gui.State.ScreenMode == SCREEN_FULL || gui.State.ScreenMode == SCREEN_HALF {
|
||||||
fullHeightBox := func(viewName string) *boxlayout.Box {
|
fullHeightBox := func(window string) *boxlayout.Box {
|
||||||
if viewName == currentCyclableViewName {
|
if window == currentWindow {
|
||||||
return &boxlayout.Box{
|
return &boxlayout.Box{
|
||||||
ViewName: viewName,
|
Window: window,
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return &boxlayout.Box{
|
return &boxlayout.Box{
|
||||||
ViewName: viewName,
|
Window: window,
|
||||||
Size: 0,
|
Size: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,10 +193,10 @@ func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
|
|||||||
} else if height >= 28 {
|
} else if height >= 28 {
|
||||||
accordianMode := gui.Config.GetUserConfig().GetBool("gui.expandFocusedSidePanel")
|
accordianMode := gui.Config.GetUserConfig().GetBool("gui.expandFocusedSidePanel")
|
||||||
accordianBox := func(defaultBox *boxlayout.Box) *boxlayout.Box {
|
accordianBox := func(defaultBox *boxlayout.Box) *boxlayout.Box {
|
||||||
if accordianMode && defaultBox.ViewName == currentCyclableViewName {
|
if accordianMode && defaultBox.Window == currentWindow {
|
||||||
return &boxlayout.Box{
|
return &boxlayout.Box{
|
||||||
ViewName: defaultBox.ViewName,
|
Window: defaultBox.Window,
|
||||||
Weight: 2,
|
Weight: 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,13 +205,13 @@ func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
|
|||||||
|
|
||||||
return []*boxlayout.Box{
|
return []*boxlayout.Box{
|
||||||
{
|
{
|
||||||
ViewName: "status",
|
Window: "status",
|
||||||
Size: 3,
|
Size: 3,
|
||||||
},
|
},
|
||||||
accordianBox(&boxlayout.Box{ViewName: "files", Weight: 1}),
|
accordianBox(&boxlayout.Box{Window: "files", Weight: 1}),
|
||||||
accordianBox(&boxlayout.Box{ViewName: "branches", Weight: 1}),
|
accordianBox(&boxlayout.Box{Window: "branches", Weight: 1}),
|
||||||
accordianBox(&boxlayout.Box{ViewName: "commits", Weight: 1}),
|
accordianBox(&boxlayout.Box{Window: "commits", Weight: 1}),
|
||||||
accordianBox(&boxlayout.Box{ViewName: "stash", Size: 3}),
|
accordianBox(&boxlayout.Box{Window: "stash", Size: 3}),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
squashedHeight := 1
|
squashedHeight := 1
|
||||||
@ -219,16 +219,16 @@ func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
|
|||||||
squashedHeight = 3
|
squashedHeight = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
squashedSidePanelBox := func(viewName string) *boxlayout.Box {
|
squashedSidePanelBox := func(window string) *boxlayout.Box {
|
||||||
if viewName == currentCyclableViewName {
|
if window == currentWindow {
|
||||||
return &boxlayout.Box{
|
return &boxlayout.Box{
|
||||||
ViewName: viewName,
|
Window: window,
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return &boxlayout.Box{
|
return &boxlayout.Box{
|
||||||
ViewName: viewName,
|
Window: window,
|
||||||
Size: squashedHeight,
|
Size: squashedHeight,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,21 +243,14 @@ func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) currentCyclableViewName() string {
|
func (gui *Gui) currentSideWindowName() string {
|
||||||
// there is always a cyclable context in the context stack. We'll look from top to bottom
|
// there is always one and only one cyclable context in the context stack. We'll look from top to bottom
|
||||||
for idx := range gui.State.ContextStack {
|
for idx := range gui.State.ContextStack {
|
||||||
reversedIdx := len(gui.State.ContextStack) - 1 - idx
|
reversedIdx := len(gui.State.ContextStack) - 1 - idx
|
||||||
context := gui.State.ContextStack[reversedIdx]
|
context := gui.State.ContextStack[reversedIdx]
|
||||||
|
|
||||||
if context.GetKind() == SIDE_CONTEXT {
|
if context.GetKind() == SIDE_CONTEXT {
|
||||||
viewName := context.GetViewName()
|
return context.GetWindowName()
|
||||||
|
|
||||||
// unfortunate result of the fact that these are separate views, have to map explicitly
|
|
||||||
if viewName == "commitFiles" {
|
|
||||||
return "commits"
|
|
||||||
}
|
|
||||||
|
|
||||||
return viewName
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@ const (
|
|||||||
COLUMN
|
COLUMN
|
||||||
)
|
)
|
||||||
|
|
||||||
// to give a high-level explanation of what's going on here. We layout our views by arranging a bunch of boxes in the window.
|
// to give a high-level explanation of what's going on here. We layout our windows by arranging a bunch of boxes in the available space.
|
||||||
// If a box has children, it needs to specify how it wants to arrange those children: ROW or COLUMN.
|
// If a box has children, it needs to specify how it wants to arrange those children: ROW or COLUMN.
|
||||||
// If a box represents a view, you can put the view name in the viewName field.
|
// If a box represents a window, you can put the window name in the Window field.
|
||||||
// When determining how to divvy-up the available height (for row children) or width (for column children), we first
|
// When determining how to divvy-up the available height (for row children) or width (for column children), we first
|
||||||
// give the boxes with a static `size` the space that they want. Then we apportion
|
// give the boxes with a static `size` the space that they want. Then we apportion
|
||||||
// the remaining space based on the weights of the dynamic boxes (you can't define
|
// the remaining space based on the weights of the dynamic boxes (you can't define
|
||||||
@ -36,8 +36,8 @@ type Box struct {
|
|||||||
// function which takes the width and height assigned to the box and decides the layout of the children.
|
// function which takes the width and height assigned to the box and decides the layout of the children.
|
||||||
ConditionalChildren func(width int, height int) []*Box
|
ConditionalChildren func(width int, height int) []*Box
|
||||||
|
|
||||||
// ViewName refers to the name of the view this box represents, if there is one
|
// Window refers to the name of the window this box represents, if there is one
|
||||||
ViewName string
|
Window string
|
||||||
|
|
||||||
// static Size. If parent box's direction is ROW this refers to height, otherwise width
|
// static Size. If parent box's direction is ROW this refers to height, otherwise width
|
||||||
Size int
|
Size int
|
||||||
@ -47,13 +47,13 @@ type Box struct {
|
|||||||
Weight int
|
Weight int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ArrangeViews(root *Box, x0, y0, width, height int) map[string]Dimensions {
|
func ArrangeWindows(root *Box, x0, y0, width, height int) map[string]Dimensions {
|
||||||
children := root.getChildren(width, height)
|
children := root.getChildren(width, height)
|
||||||
if len(children) == 0 {
|
if len(children) == 0 {
|
||||||
// leaf node
|
// leaf node
|
||||||
if root.ViewName != "" {
|
if root.Window != "" {
|
||||||
dimensionsForView := Dimensions{X0: x0, Y0: y0, X1: x0 + width - 1, Y1: y0 + height - 1}
|
dimensionsForWindow := Dimensions{X0: x0, Y0: y0, X1: x0 + width - 1, Y1: y0 + height - 1}
|
||||||
return map[string]Dimensions{root.ViewName: dimensionsForView}
|
return map[string]Dimensions{root.Window: dimensionsForWindow}
|
||||||
}
|
}
|
||||||
return map[string]Dimensions{}
|
return map[string]Dimensions{}
|
||||||
}
|
}
|
||||||
@ -104,9 +104,9 @@ func ArrangeViews(root *Box, x0, y0, width, height int) map[string]Dimensions {
|
|||||||
|
|
||||||
var resultForChild map[string]Dimensions
|
var resultForChild map[string]Dimensions
|
||||||
if direction == COLUMN {
|
if direction == COLUMN {
|
||||||
resultForChild = ArrangeViews(child, x0+offset, y0, boxSize, height)
|
resultForChild = ArrangeWindows(child, x0+offset, y0, boxSize, height)
|
||||||
} else {
|
} else {
|
||||||
resultForChild = ArrangeViews(child, x0, y0+offset, width, boxSize)
|
resultForChild = ArrangeWindows(child, x0, y0+offset, width, boxSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = mergeDimensionMaps(result, resultForChild)
|
result = mergeDimensionMaps(result, resultForChild)
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestArrangeViews(t *testing.T) {
|
func TestArrangeWindows(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
root *Box
|
root *Box
|
||||||
@ -31,7 +31,7 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Box with static and dynamic panel",
|
"Box with static and dynamic panel",
|
||||||
&Box{Children: []*Box{{Size: 1, ViewName: "static"}, {Weight: 1, ViewName: "dynamic"}}},
|
&Box{Children: []*Box{{Size: 1, Window: "static"}, {Weight: 1, Window: "dynamic"}}},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
@ -49,7 +49,7 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Box with static and two dynamic panels",
|
"Box with static and two dynamic panels",
|
||||||
&Box{Children: []*Box{{Size: 1, ViewName: "static"}, {Weight: 1, ViewName: "dynamic1"}, {Weight: 2, ViewName: "dynamic2"}}},
|
&Box{Children: []*Box{{Size: 1, Window: "static"}, {Weight: 1, Window: "dynamic1"}, {Weight: 2, Window: "dynamic2"}}},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
@ -68,7 +68,7 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Box with COLUMN direction",
|
"Box with COLUMN direction",
|
||||||
&Box{Direction: COLUMN, Children: []*Box{{Size: 1, ViewName: "static"}, {Weight: 1, ViewName: "dynamic1"}, {Weight: 2, ViewName: "dynamic2"}}},
|
&Box{Direction: COLUMN, Children: []*Box{{Size: 1, Window: "static"}, {Weight: 1, Window: "dynamic1"}, {Weight: 2, Window: "dynamic2"}}},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
@ -93,7 +93,7 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
return ROW
|
return ROW
|
||||||
}
|
}
|
||||||
}, Children: []*Box{{Weight: 1, ViewName: "dynamic1"}, {Weight: 1, ViewName: "dynamic2"}}},
|
}, Children: []*Box{{Weight: 1, Window: "dynamic1"}, {Weight: 1, Window: "dynamic2"}}},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
4,
|
4,
|
||||||
@ -117,7 +117,7 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
return ROW
|
return ROW
|
||||||
}
|
}
|
||||||
}, Children: []*Box{{Weight: 1, ViewName: "dynamic1"}, {Weight: 1, ViewName: "dynamic2"}}},
|
}, Children: []*Box{{Weight: 1, Window: "dynamic1"}, {Weight: 1, Window: "dynamic2"}}},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
5,
|
5,
|
||||||
@ -137,9 +137,9 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
"Box with conditional children where box is wide",
|
"Box with conditional children where box is wide",
|
||||||
&Box{ConditionalChildren: func(width int, height int) []*Box {
|
&Box{ConditionalChildren: func(width int, height int) []*Box {
|
||||||
if width > 4 {
|
if width > 4 {
|
||||||
return []*Box{{ViewName: "wide", Weight: 1}}
|
return []*Box{{Window: "wide", Weight: 1}}
|
||||||
} else {
|
} else {
|
||||||
return []*Box{{ViewName: "narrow", Weight: 1}}
|
return []*Box{{Window: "narrow", Weight: 1}}
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
0,
|
0,
|
||||||
@ -160,9 +160,9 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
"Box with conditional children where box is narrow",
|
"Box with conditional children where box is narrow",
|
||||||
&Box{ConditionalChildren: func(width int, height int) []*Box {
|
&Box{ConditionalChildren: func(width int, height int) []*Box {
|
||||||
if width > 4 {
|
if width > 4 {
|
||||||
return []*Box{{ViewName: "wide", Weight: 1}}
|
return []*Box{{Window: "wide", Weight: 1}}
|
||||||
} else {
|
} else {
|
||||||
return []*Box{{ViewName: "narrow", Weight: 1}}
|
return []*Box{{Window: "narrow", Weight: 1}}
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
0,
|
0,
|
||||||
@ -183,7 +183,7 @@ func TestArrangeViews(t *testing.T) {
|
|||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
s.test(ArrangeViews(s.root, s.x0, s.y0, s.width, s.height))
|
s.test(ArrangeWindows(s.root, s.x0, s.y0, s.width, s.height))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||||
@ -80,12 +81,14 @@ func (gui *Gui) refreshCommitFilesView() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := gui.GitCommand.GetCommitFiles(gui.State.Panels.CommitFiles.refName, gui.GitCommand.PatchManager)
|
files, err := gui.GitCommand.GetFilesInRef(gui.State.Panels.CommitFiles.refName, gui.State.Panels.CommitFiles.isStash, gui.GitCommand.PatchManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.surfaceError(err)
|
return gui.surfaceError(err)
|
||||||
}
|
}
|
||||||
gui.State.CommitFiles = files
|
gui.State.CommitFiles = files
|
||||||
|
|
||||||
|
gui.Log.Warn(spew.Sdump(files))
|
||||||
|
|
||||||
return gui.postRefreshUpdate(gui.Contexts.CommitFiles.Context)
|
return gui.postRefreshUpdate(gui.Contexts.CommitFiles.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,3 +214,23 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
|
|||||||
|
|
||||||
return enterTheFile(selectedLineIdx)
|
return enterTheFile(selectedLineIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) switchToCommitFilesContext(refName string, isStash bool, context Context, windowName string) error {
|
||||||
|
// sometimes the commitFiles view is already shown in another window, so we need to ensure that window
|
||||||
|
// no longer considers the commitFiles view as its main view.
|
||||||
|
|
||||||
|
window := gui.getWindowForViewName("commitFiles")
|
||||||
|
gui.State.WindowViewNameMap[window] = window
|
||||||
|
|
||||||
|
gui.State.Panels.CommitFiles.SelectedLineIdx = 0
|
||||||
|
gui.State.Panels.CommitFiles.refName = refName
|
||||||
|
gui.State.Panels.CommitFiles.isStash = isStash
|
||||||
|
gui.Contexts.CommitFiles.Context.SetParentContext(context)
|
||||||
|
gui.Contexts.CommitFiles.Context.SetWindowName(windowName)
|
||||||
|
|
||||||
|
if err := gui.refreshCommitFilesView(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui.switchContext(gui.Contexts.CommitFiles.Context)
|
||||||
|
}
|
||||||
|
@ -505,14 +505,7 @@ func (gui *Gui) handleViewCommitFiles() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.State.Panels.CommitFiles.refName = commit.Sha
|
return gui.switchToCommitFilesContext(commit.Sha, false, gui.Contexts.BranchCommits.Context, "commits")
|
||||||
gui.Contexts.CommitFiles.Context.SetParentContext(gui.Contexts.BranchCommits.Context)
|
|
||||||
|
|
||||||
if err := gui.refreshCommitFilesView(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return gui.switchContext(gui.Contexts.CommitFiles.Context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) hasCommit(commits []*commands.Commit, target string) (int, bool) {
|
func (gui *Gui) hasCommit(commits []*commands.Commit, target string) (int, bool) {
|
||||||
|
@ -41,6 +41,8 @@ type Context interface {
|
|||||||
HandleRender() error
|
HandleRender() error
|
||||||
GetKind() int
|
GetKind() int
|
||||||
GetViewName() string
|
GetViewName() string
|
||||||
|
GetWindowName() string
|
||||||
|
SetWindowName(string)
|
||||||
GetKey() string
|
GetKey() string
|
||||||
GetSelectedItemId() string
|
GetSelectedItemId() string
|
||||||
SetParentContext(Context)
|
SetParentContext(Context)
|
||||||
@ -56,6 +58,15 @@ type BasicContext struct {
|
|||||||
ViewName string
|
ViewName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c BasicContext) SetWindowName(windowName string) {
|
||||||
|
panic("can't set window name on basic context")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c BasicContext) GetWindowName() string {
|
||||||
|
// TODO: fix this up
|
||||||
|
return c.GetViewName()
|
||||||
|
}
|
||||||
|
|
||||||
func (c BasicContext) SetParentContext(Context) {
|
func (c BasicContext) SetParentContext(Context) {
|
||||||
panic("can't set parent context on basic context")
|
panic("can't set parent context on basic context")
|
||||||
}
|
}
|
||||||
@ -433,6 +444,7 @@ func (gui *Gui) activateContext(c Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure that any other window for which this view was active is now set to the default for that window.
|
||||||
gui.setViewAsActiveForWindow(viewName)
|
gui.setViewAsActiveForWindow(viewName)
|
||||||
|
|
||||||
if viewName == "main" {
|
if viewName == "main" {
|
||||||
|
@ -188,6 +188,7 @@ type commitFilesPanelState struct {
|
|||||||
// this is the SHA of the commit or the stash index of the stash.
|
// this is the SHA of the commit or the stash index of the stash.
|
||||||
// Not sure if ref is actually the right word here
|
// Not sure if ref is actually the right word here
|
||||||
refName string
|
refName string
|
||||||
|
isStash bool // true if we're dealing with a stash entry rather than a commit
|
||||||
}
|
}
|
||||||
|
|
||||||
type panelStates struct {
|
type panelStates struct {
|
||||||
|
@ -818,6 +818,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
Handler: gui.handleCreateReflogResetMenu,
|
Handler: gui.handleCreateReflogResetMenu,
|
||||||
Description: gui.Tr.SLocalize("viewResetOptions"),
|
Description: gui.Tr.SLocalize("viewResetOptions"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ViewName: "stash",
|
||||||
|
Key: gui.getKey("universal.goInto"),
|
||||||
|
Handler: gui.wrappedHandler(gui.handleViewStashFiles),
|
||||||
|
Description: gui.Tr.SLocalize("viewStashFiles"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ViewName: "stash",
|
ViewName: "stash",
|
||||||
Key: gui.getKey("universal.select"),
|
Key: gui.getKey("universal.select"),
|
||||||
|
@ -50,7 +50,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
informationStr := gui.informationStr()
|
informationStr := gui.informationStr()
|
||||||
appStatus := gui.statusManager.getStatusString()
|
appStatus := gui.statusManager.getStatusString()
|
||||||
|
|
||||||
viewDimensions := gui.getViewDimensions(informationStr, appStatus)
|
viewDimensions := gui.getWindowDimensions(informationStr, appStatus)
|
||||||
|
|
||||||
_, _ = g.SetViewOnBottom("limit")
|
_, _ = g.SetViewOnBottom("limit")
|
||||||
_ = g.DeleteView("limit")
|
_ = g.DeleteView("limit")
|
||||||
@ -152,7 +152,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
branchesView.ContainsList = true
|
branchesView.ContainsList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
commitFilesView, err := setViewFromDimensions("commitFiles", "commits", true)
|
commitFilesView, err := setViewFromDimensions("commitFiles", gui.Contexts.CommitFiles.Context.GetWindowName(), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != "unknown view" {
|
if err.Error() != "unknown view" {
|
||||||
return err
|
return err
|
||||||
|
@ -20,12 +20,28 @@ type ListContext struct {
|
|||||||
RendersToMainView bool
|
RendersToMainView bool
|
||||||
Kind int
|
Kind int
|
||||||
ParentContext Context
|
ParentContext Context
|
||||||
|
WindowName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListItem interface {
|
type ListItem interface {
|
||||||
ID() string
|
ID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lc *ListContext) SetWindowName(windowName string) {
|
||||||
|
lc.WindowName = windowName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *ListContext) GetWindowName() string {
|
||||||
|
windowName := lc.WindowName
|
||||||
|
|
||||||
|
if windowName != "" {
|
||||||
|
return windowName
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: actually set this for everything so we don't default to the view name
|
||||||
|
return lc.ViewName
|
||||||
|
}
|
||||||
|
|
||||||
func (lc *ListContext) SetParentContext(c Context) {
|
func (lc *ListContext) SetParentContext(c Context) {
|
||||||
lc.ParentContext = c
|
lc.ParentContext = c
|
||||||
}
|
}
|
||||||
@ -371,6 +387,7 @@ func (gui *Gui) stashListContext() *ListContext {
|
|||||||
func (gui *Gui) commitFilesListContext() *ListContext {
|
func (gui *Gui) commitFilesListContext() *ListContext {
|
||||||
return &ListContext{
|
return &ListContext{
|
||||||
ViewName: "commitFiles",
|
ViewName: "commitFiles",
|
||||||
|
WindowName: "commits",
|
||||||
ContextKey: COMMIT_FILES_CONTEXT_KEY,
|
ContextKey: COMMIT_FILES_CONTEXT_KEY,
|
||||||
GetItemsLength: func() int { return len(gui.State.CommitFiles) },
|
GetItemsLength: func() int { return len(gui.State.CommitFiles) },
|
||||||
GetPanelState: func() IListPanelState { return gui.State.Panels.CommitFiles },
|
GetPanelState: func() IListPanelState { return gui.State.Panels.CommitFiles },
|
||||||
|
@ -119,12 +119,5 @@ func (gui *Gui) handleViewReflogCommitFiles() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.State.Panels.CommitFiles.refName = commit.Sha
|
return gui.switchToCommitFilesContext(commit.Sha, false, gui.Contexts.ReflogCommits.Context, "commits")
|
||||||
gui.Contexts.CommitFiles.Context.SetParentContext(gui.Contexts.ReflogCommits.Context)
|
|
||||||
|
|
||||||
if err := gui.refreshCommitFilesView(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return gui.switchContext(gui.Contexts.CommitFiles.Context)
|
|
||||||
}
|
}
|
||||||
|
@ -128,3 +128,12 @@ func (gui *Gui) handleStashSave(stashFunc func(message string) error) error {
|
|||||||
return gui.refreshSidePanels(refreshOptions{scope: []int{STASH, FILES}})
|
return gui.refreshSidePanels(refreshOptions{scope: []int{STASH, FILES}})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleViewStashFiles() error {
|
||||||
|
stashEntry := gui.getSelectedStashEntry()
|
||||||
|
if stashEntry == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui.switchToCommitFilesContext(stashEntry.RefName(), true, gui.Contexts.Stash.Context, "stash")
|
||||||
|
}
|
||||||
|
@ -16,9 +16,8 @@ func (gui *Gui) getViewNameForWindow(window string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getWindowForViewName(viewName string) string {
|
func (gui *Gui) getWindowForViewName(viewName string) string {
|
||||||
// should soft-code this
|
|
||||||
if viewName == "commitFiles" {
|
if viewName == "commitFiles" {
|
||||||
return "commits"
|
return gui.Contexts.CommitFiles.Context.GetWindowName()
|
||||||
}
|
}
|
||||||
|
|
||||||
return viewName
|
return viewName
|
||||||
|
@ -1167,6 +1167,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
|||||||
}, &i18n.Message{
|
}, &i18n.Message{
|
||||||
ID: "createNewBranchFromCommit",
|
ID: "createNewBranchFromCommit",
|
||||||
Other: "create new branch off of commit",
|
Other: "create new branch off of commit",
|
||||||
|
}, &i18n.Message{
|
||||||
|
ID: "viewStashFiles",
|
||||||
|
Other: "view stash entry's files",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user