mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-19 22:33:16 +02:00
Add menu prompt
This makes it possible to add a prompt to a menu. It will be shown above the menu items, separated from them by a blank line.
This commit is contained in:
parent
dbc21af3b1
commit
7e92dbfd3d
@ -50,6 +50,8 @@ func NewMenuContext(
|
|||||||
type MenuViewModel struct {
|
type MenuViewModel struct {
|
||||||
c *ContextCommon
|
c *ContextCommon
|
||||||
menuItems []*types.MenuItem
|
menuItems []*types.MenuItem
|
||||||
|
prompt string
|
||||||
|
promptLines []string
|
||||||
columnAlignment []utils.Alignment
|
columnAlignment []utils.Alignment
|
||||||
*FilteredListViewModel[*types.MenuItem]
|
*FilteredListViewModel[*types.MenuItem]
|
||||||
}
|
}
|
||||||
@ -73,6 +75,23 @@ func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem, columnAlignment
|
|||||||
self.columnAlignment = columnAlignment
|
self.columnAlignment = columnAlignment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *MenuViewModel) GetPrompt() string {
|
||||||
|
return self.prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *MenuViewModel) SetPrompt(prompt string) {
|
||||||
|
self.prompt = prompt
|
||||||
|
self.promptLines = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *MenuViewModel) GetPromptLines() []string {
|
||||||
|
return self.promptLines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *MenuViewModel) SetPromptLines(promptLines []string) {
|
||||||
|
self.promptLines = promptLines
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: move into presentation package
|
// TODO: move into presentation package
|
||||||
func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
||||||
menuItems := self.FilteredListViewModel.GetItems()
|
menuItems := self.FilteredListViewModel.GetItems()
|
||||||
@ -94,14 +113,22 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *MenuViewModel) GetNonModelItems() []*NonModelItem {
|
func (self *MenuViewModel) GetNonModelItems() []*NonModelItem {
|
||||||
|
result := []*NonModelItem{}
|
||||||
|
result = append(result, lo.Map(self.promptLines, func(line string, _ int) *NonModelItem {
|
||||||
|
return &NonModelItem{
|
||||||
|
Index: 0,
|
||||||
|
Column: 0,
|
||||||
|
Content: line,
|
||||||
|
}
|
||||||
|
})...)
|
||||||
|
|
||||||
// Don't display section headers when we are filtering, and the filter mode
|
// Don't display section headers when we are filtering, and the filter mode
|
||||||
// is fuzzy. The reason is that filtering changes the order of the items
|
// is fuzzy. The reason is that filtering changes the order of the items
|
||||||
// (they are sorted by best match), so all the sections would be messed up.
|
// (they are sorted by best match), so all the sections would be messed up.
|
||||||
if self.FilteredListViewModel.IsFiltering() && self.c.UserConfig.Gui.UseFuzzySearch() {
|
if self.FilteredListViewModel.IsFiltering() && self.c.UserConfig.Gui.UseFuzzySearch() {
|
||||||
return []*NonModelItem{}
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
result := []*NonModelItem{}
|
|
||||||
menuItems := self.FilteredListViewModel.GetItems()
|
menuItems := self.FilteredListViewModel.GetItems()
|
||||||
var prevSection *types.MenuSection = nil
|
var prevSection *types.MenuSection = nil
|
||||||
for i, menuItem := range menuItems {
|
for i, menuItem := range menuItems {
|
||||||
|
@ -373,7 +373,9 @@ func (self *ConfirmationHelper) resizeMenu() {
|
|||||||
itemCount := self.c.Contexts().Menu.UnfilteredLen()
|
itemCount := self.c.Contexts().Menu.UnfilteredLen()
|
||||||
offset := 3
|
offset := 3
|
||||||
panelWidth := self.getPopupPanelWidth()
|
panelWidth := self.getPopupPanelWidth()
|
||||||
x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset)
|
contentWidth := panelWidth - 2 // minus 2 for the frame
|
||||||
|
promptLinesCount := self.layoutMenuPrompt(contentWidth)
|
||||||
|
x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset+promptLinesCount)
|
||||||
menuBottom := y1 - offset
|
menuBottom := y1 - offset
|
||||||
_, _ = self.c.GocuiGui().SetView(self.c.Views().Menu.Name(), x0, y0, x1, menuBottom, 0)
|
_, _ = self.c.GocuiGui().SetView(self.c.Views().Menu.Name(), x0, y0, x1, menuBottom, 0)
|
||||||
|
|
||||||
@ -383,11 +385,39 @@ func (self *ConfirmationHelper) resizeMenu() {
|
|||||||
if selectedItem != nil {
|
if selectedItem != nil {
|
||||||
tooltip = self.TooltipForMenuItem(selectedItem)
|
tooltip = self.TooltipForMenuItem(selectedItem)
|
||||||
}
|
}
|
||||||
contentWidth := panelWidth - 2 // minus 2 for the frame
|
|
||||||
tooltipHeight := getMessageHeight(true, tooltip, contentWidth) + 2 // plus 2 for the frame
|
tooltipHeight := getMessageHeight(true, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wraps the lines of the menu prompt to the available width and rerenders the
|
||||||
|
// menu if neeeded. Returns the number of lines the prompt takes up.
|
||||||
|
func (self *ConfirmationHelper) layoutMenuPrompt(contentWidth int) int {
|
||||||
|
oldPromptLines := self.c.Contexts().Menu.GetPromptLines()
|
||||||
|
var promptLines []string
|
||||||
|
prompt := self.c.Contexts().Menu.GetPrompt()
|
||||||
|
if len(prompt) > 0 {
|
||||||
|
promptLines = wrapMessageToWidth(true, prompt, contentWidth)
|
||||||
|
promptLines = append(promptLines, "")
|
||||||
|
}
|
||||||
|
self.c.Contexts().Menu.SetPromptLines(promptLines)
|
||||||
|
if len(oldPromptLines) != len(promptLines) {
|
||||||
|
// The number of lines in the prompt has changed; this happens either
|
||||||
|
// because we're now showing a menu that has a prompt, and the previous
|
||||||
|
// menu didn't (or vice versa), or because the user is resizing the
|
||||||
|
// terminal window while a menu with a prompt is open.
|
||||||
|
|
||||||
|
// We need to rerender to give the menu context a chance to update its
|
||||||
|
// non-model items, and reinitialize the data it uses for converting
|
||||||
|
// between view index and model index.
|
||||||
|
_ = self.c.Contexts().Menu.HandleRender()
|
||||||
|
|
||||||
|
// Then we need to refocus to ensure the cursor is in the right place in
|
||||||
|
// the view.
|
||||||
|
_ = self.c.Contexts().Menu.HandleFocus(types.OnFocusOpts{})
|
||||||
|
}
|
||||||
|
return len(promptLines)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *ConfirmationHelper) resizeConfirmationPanel() {
|
func (self *ConfirmationHelper) resizeConfirmationPanel() {
|
||||||
suggestionsViewHeight := 0
|
suggestionsViewHeight := 0
|
||||||
if self.c.Views().Suggestions.Visible {
|
if self.c.Views().Suggestions.Visible {
|
||||||
|
@ -42,6 +42,7 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gui.State.Contexts.Menu.SetMenuItems(opts.Items, opts.ColumnAlignment)
|
gui.State.Contexts.Menu.SetMenuItems(opts.Items, opts.ColumnAlignment)
|
||||||
|
gui.State.Contexts.Menu.SetPrompt(opts.Prompt)
|
||||||
gui.State.Contexts.Menu.SetSelection(0)
|
gui.State.Contexts.Menu.SetSelection(0)
|
||||||
|
|
||||||
gui.Views.Menu.Title = opts.Title
|
gui.Views.Menu.Title = opts.Title
|
||||||
|
@ -159,6 +159,7 @@ const (
|
|||||||
|
|
||||||
type CreateMenuOptions struct {
|
type CreateMenuOptions struct {
|
||||||
Title string
|
Title string
|
||||||
|
Prompt string // a message that will be displayed above the menu options
|
||||||
Items []*MenuItem
|
Items []*MenuItem
|
||||||
HideCancel bool
|
HideCancel bool
|
||||||
ColumnAlignment []utils.Alignment
|
ColumnAlignment []utils.Alignment
|
||||||
|
Loading…
x
Reference in New Issue
Block a user