From 3c4d3920a352e101dbd32eee673bcc96c478c337 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 7 Sep 2026 19:00:07 +0200 Subject: [PATCH] fixup! Truncate the repo and branch names in the recent repos menu Count the branch icon towards the maximum width of the branch column, and pad the tooltip labels to the same width no matter which of them the tooltip shows, so that its values don't shift around as the selection moves from one entry to another. Co-authored-by: Claude Opus 5 (1M context) --- pkg/gui/controllers/helpers/repos_helper.go | 55 ++++++++++----------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/pkg/gui/controllers/helpers/repos_helper.go b/pkg/gui/controllers/helpers/repos_helper.go index ff2a1b546..19bdec135 100644 --- a/pkg/gui/controllers/helpers/repos_helper.go +++ b/pkg/gui/controllers/helpers/repos_helper.go @@ -109,41 +109,40 @@ func (self *ReposHelper) getCurrentBranch(path string) string { // width of its widest entry. const recentReposColumnMaxWidth = 30 -// Spells out the repo name and the branch name of a recent repos menu item, -// but only the ones that the menu shows in truncated form. -func (self *ReposHelper) recentRepoTooltip(repoName string, branchName string) string { - type field struct { - label string - value string - } - - fields := []field{} - if utils.StringWidth(repoName) > recentReposColumnMaxWidth { - fields = append(fields, field{self.c.Tr.RecentReposRepoLabel, repoName}) - } - if utils.StringWidth(branchName) > recentReposColumnMaxWidth { - fields = append(fields, field{self.c.Tr.RecentReposBranchLabel, branchName}) - } - - labelWidth := utils.MaxFn(fields, func(f field) int { return utils.StringWidth(f.label) }) - - return strings.Join(lo.Map(fields, func(f field, _ int) string { - return utils.WithPadding(f.label, labelWidth, utils.AlignLeft) + " " + f.value - }), "\n") -} - func (self *ReposHelper) recentRepoMenuItem(path string, branchName string) *types.MenuItem { repoName := filepath.Base(path) + displayedRepoName := utils.TruncateWithEllipsis(repoName, recentReposColumnMaxWidth) - displayedBranchName := utils.TruncateWithEllipsis(branchName, recentReposColumnMaxWidth) + // The icon is part of the column, so it counts towards the maximum width. + branchColumn := branchName if icons.IsIconEnabled() { - displayedBranchName = icons.BRANCH_ICON + " " + displayedBranchName + branchColumn = icons.BRANCH_ICON + " " + branchName + } + displayedBranchColumn := utils.TruncateWithEllipsis(branchColumn, recentReposColumnMaxWidth) + + // Spell out whatever the columns show in truncated form. The labels are + // padded to the same width no matter which of them appear, so that the + // tooltip doesn't shift around as the selection moves. + tooltipLines := []string{} + labelWidth := utils.MaxFn( + []string{self.c.Tr.RecentReposRepoLabel, self.c.Tr.RecentReposBranchLabel}, + utils.StringWidth) + addTooltipLine := func(label string, value string) { + tooltipLines = append(tooltipLines, + utils.WithPadding(label, labelWidth, utils.AlignLeft)+" "+value) + } + + if displayedRepoName != repoName { + addTooltipLine(self.c.Tr.RecentReposRepoLabel, repoName) + } + if displayedBranchColumn != branchColumn { + addTooltipLine(self.c.Tr.RecentReposBranchLabel, branchName) } return &types.MenuItem{ LabelColumns: []string{ - utils.TruncateWithEllipsis(repoName, recentReposColumnMaxWidth), - style.FgCyan.Sprint(displayedBranchName), + displayedRepoName, + style.FgCyan.Sprint(displayedBranchColumn), // The last segment of the path is already in the first column, so // showing the directory that contains the repo is enough to tell // repos with the same name apart. @@ -152,7 +151,7 @@ func (self *ReposHelper) recentRepoMenuItem(path string, branchName string) *typ // Filtering matches the full text, including the parts that the columns // above truncate or leave out. FilterColumns: []string{repoName, branchName, path}, - Tooltip: self.recentRepoTooltip(repoName, branchName), + Tooltip: strings.Join(tooltipLines, "\n"), OnPress: func() error { // Check before clearing the stack, so a refused switch doesn't // forget the submodule breadcrumb (which would leave escape