1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-10 23:57:43 +02:00

Only avoid the blank line at end of view if view is not editable

For editable views it is important to actually show the blank line so that we
can put the cursor there for typing.

This fixes problems with adding blank lines at the end of longer commit
messages.
This commit is contained in:
Stefan Haller 2025-01-18 20:03:57 +01:00
parent fe429c6184
commit 20d0b4316d
4 changed files with 59 additions and 11 deletions

View File

@ -56,8 +56,8 @@ func (self *ConfirmationHelper) DeactivateConfirmationPrompt() {
self.clearConfirmationViewKeyBindings() self.clearConfirmationViewKeyBindings()
} }
func getMessageHeight(wrap bool, message string, width int) int { func getMessageHeight(wrap bool, editable bool, message string, width int) int {
wrappedLines, _, _ := utils.WrapViewLinesToWidth(wrap, message, width) wrappedLines, _, _ := utils.WrapViewLinesToWidth(wrap, editable, message, width)
return len(wrappedLines) return len(wrappedLines)
} }
@ -265,7 +265,7 @@ func (self *ConfirmationHelper) resizeMenu(parentPopupContext types.Context) {
if selectedItem != nil { if selectedItem != nil {
tooltip = self.TooltipForMenuItem(selectedItem) tooltip = self.TooltipForMenuItem(selectedItem)
} }
tooltipHeight := getMessageHeight(true, tooltip, contentWidth) + 2 // plus 2 for the frame tooltipHeight := getMessageHeight(true, false, tooltip, contentWidth) + 2 // plus 2 for the frame
_, _ = self.c.GocuiGui().SetView(self.c.Views().Tooltip.Name(), x0, tooltipTop, x1, tooltipTop+tooltipHeight-1, 0) _, _ = self.c.GocuiGui().SetView(self.c.Views().Tooltip.Name(), x0, tooltipTop, x1, tooltipTop+tooltipHeight-1, 0)
} }
@ -276,7 +276,7 @@ func (self *ConfirmationHelper) layoutMenuPrompt(contentWidth int) int {
var promptLines []string var promptLines []string
prompt := self.c.Contexts().Menu.GetPrompt() prompt := self.c.Contexts().Menu.GetPrompt()
if len(prompt) > 0 { if len(prompt) > 0 {
promptLines, _, _ = utils.WrapViewLinesToWidth(true, prompt, contentWidth) promptLines, _, _ = utils.WrapViewLinesToWidth(true, false, prompt, contentWidth)
promptLines = append(promptLines, "") promptLines = append(promptLines, "")
} }
self.c.Contexts().Menu.SetPromptLines(promptLines) self.c.Contexts().Menu.SetPromptLines(promptLines)
@ -307,11 +307,12 @@ func (self *ConfirmationHelper) resizeConfirmationPanel(parentPopupContext types
contentWidth := panelWidth - 2 // minus 2 for the frame contentWidth := panelWidth - 2 // minus 2 for the frame
prompt := self.c.Views().Confirmation.Buffer() prompt := self.c.Views().Confirmation.Buffer()
wrap := true wrap := true
if self.c.Views().Confirmation.Editable { editable := self.c.Views().Confirmation.Editable
if editable {
prompt = self.c.Views().Confirmation.TextArea.GetContent() prompt = self.c.Views().Confirmation.TextArea.GetContent()
wrap = false wrap = false
} }
panelHeight := getMessageHeight(wrap, prompt, contentWidth) + suggestionsViewHeight panelHeight := getMessageHeight(wrap, editable, prompt, contentWidth) + suggestionsViewHeight
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext) x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
confirmationViewBottom := y1 - suggestionsViewHeight confirmationViewBottom := y1 - suggestionsViewHeight
_, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0) _, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
@ -324,7 +325,7 @@ func (self *ConfirmationHelper) ResizeCommitMessagePanels(parentPopupContext typ
panelWidth := self.getPopupPanelWidth() panelWidth := self.getPopupPanelWidth()
content := self.c.Views().CommitDescription.TextArea.GetContent() content := self.c.Views().CommitDescription.TextArea.GetContent()
summaryViewHeight := 3 summaryViewHeight := 3
panelHeight := getMessageHeight(false, content, panelWidth) panelHeight := getMessageHeight(false, true, content, panelWidth)
minHeight := 7 minHeight := 7
if panelHeight < minHeight { if panelHeight < minHeight {
panelHeight = minHeight panelHeight = minHeight

View File

@ -323,6 +323,6 @@ func (s *State) CalculateOrigin(currentOrigin int, bufferHeight int, numLines in
func wrapPatchLines(diff string, view *gocui.View) ([]int, []int) { func wrapPatchLines(diff string, view *gocui.View) ([]int, []int) {
_, viewLineIndices, patchLineIndices := utils.WrapViewLinesToWidth( _, viewLineIndices, patchLineIndices := utils.WrapViewLinesToWidth(
view.Wrap, strings.TrimSuffix(diff, "\n"), view.InnerWidth()) view.Wrap, view.Editable, strings.TrimSuffix(diff, "\n"), view.InnerWidth())
return viewLineIndices, patchLineIndices return viewLineIndices, patchLineIndices
} }

View File

@ -109,8 +109,10 @@ func ScanLinesAndTruncateWhenLongerThanBuffer(maxBufferSize int) func(data []byt
// - the line indices of the original lines, indexed by the wrapped line indices // - the line indices of the original lines, indexed by the wrapped line indices
// If wrap is false, the text is returned as is. // If wrap is false, the text is returned as is.
// This code needs to behave the same as `gocui.lineWrap` does. // This code needs to behave the same as `gocui.lineWrap` does.
func WrapViewLinesToWidth(wrap bool, text string, width int) ([]string, []int, []int) { func WrapViewLinesToWidth(wrap bool, editable bool, text string, width int) ([]string, []int, []int) {
text = strings.TrimSuffix(text, "\n") if !editable {
text = strings.TrimSuffix(text, "\n")
}
lines := strings.Split(text, "\n") lines := strings.Split(text, "\n")
if !wrap { if !wrap {
indices := make([]int, len(lines)) indices := make([]int, len(lines))

View File

@ -170,6 +170,7 @@ func TestWrapViewLinesToWidth(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
wrap bool wrap bool
editable bool
text string text string
width int width int
expectedWrappedLines []string expectedWrappedLines []string
@ -378,10 +379,53 @@ func TestWrapViewLinesToWidth(t *testing.T) {
expectedWrappedLinesIndices: []int{0, 2, 6}, expectedWrappedLinesIndices: []int{0, 2, 6},
expectedOriginalLinesIndices: []int{0, 0, 1, 1, 1, 1, 2, 2}, expectedOriginalLinesIndices: []int{0, 0, 1, 1, 1, 1, 2, 2},
}, },
{
name: "Avoid blank line at end if not editable",
wrap: true,
editable: false,
text: "First\nSecond\nThird\n",
width: 10,
expectedWrappedLines: []string{
"First",
"Second",
"Third",
},
expectedWrappedLinesIndices: []int{0, 1, 2},
expectedOriginalLinesIndices: []int{0, 1, 2},
},
{
name: "Avoid blank line at end if not editable",
wrap: true,
editable: false,
text: "First\nSecond\nThird\n",
width: 10,
expectedWrappedLines: []string{
"First",
"Second",
"Third",
},
expectedWrappedLinesIndices: []int{0, 1, 2},
expectedOriginalLinesIndices: []int{0, 1, 2},
},
{
name: "Keep blank line at end if editable",
wrap: true,
editable: true,
text: "First\nSecond\nThird\n",
width: 10,
expectedWrappedLines: []string{
"First",
"Second",
"Third",
"",
},
expectedWrappedLinesIndices: []int{0, 1, 2, 3},
expectedOriginalLinesIndices: []int{0, 1, 2, 3},
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
wrappedLines, wrappedLinesIndices, originalLinesIndices := WrapViewLinesToWidth(tt.wrap, tt.text, tt.width) wrappedLines, wrappedLinesIndices, originalLinesIndices := WrapViewLinesToWidth(tt.wrap, tt.editable, tt.text, tt.width)
assert.Equal(t, tt.expectedWrappedLines, wrappedLines) assert.Equal(t, tt.expectedWrappedLines, wrappedLines)
if tt.expectedWrappedLinesIndices != nil { if tt.expectedWrappedLinesIndices != nil {
assert.Equal(t, tt.expectedWrappedLinesIndices, wrappedLinesIndices) assert.Equal(t, tt.expectedWrappedLinesIndices, wrappedLinesIndices)
@ -394,6 +438,7 @@ func TestWrapViewLinesToWidth(t *testing.T) {
view := gocui.NewView("", 0, 0, tt.width+1, 1000, gocui.OutputNormal) view := gocui.NewView("", 0, 0, tt.width+1, 1000, gocui.OutputNormal)
assert.Equal(t, tt.width, view.InnerWidth()) assert.Equal(t, tt.width, view.InnerWidth())
view.Wrap = tt.wrap view.Wrap = tt.wrap
view.Editable = tt.editable
view.SetContent(tt.text) view.SetContent(tt.text)
assert.Equal(t, wrappedLines, view.ViewBufferLines()) assert.Equal(t, wrappedLines, view.ViewBufferLines())
}) })