diff --git a/internal/adapters/ui/server_list.go b/internal/adapters/ui/server_list.go index 1a58d39..f904e1d 100644 --- a/internal/adapters/ui/server_list.go +++ b/internal/adapters/ui/server_list.go @@ -17,6 +17,7 @@ package ui import ( "github.com/Adembc/lazyssh/internal/core/domain" "github.com/gdamore/tcell/v2" + "github.com/mattn/go-runewidth" "github.com/rivo/tview" ) @@ -71,8 +72,17 @@ func (sl *ServerList) UpdateServers(servers []domain.Server) { sl.servers = servers sl.List.Clear() + // Calculate the maximum alias width for alignment + maxAliasWidth := 0 + for _, s := range servers { + width := runewidth.StringWidth(s.Alias) + if width > maxAliasWidth { + maxAliasWidth = width + } + } + for i := range servers { - primary, secondary := formatServerLine(servers[i]) + primary, secondary := formatServerLine(servers[i], maxAliasWidth) idx := i sl.List.AddItem(primary, secondary, 0, func() { if sl.onSelection != nil { diff --git a/internal/adapters/ui/utils.go b/internal/adapters/ui/utils.go index 0b49ad8..2af8aff 100644 --- a/internal/adapters/ui/utils.go +++ b/internal/adapters/ui/utils.go @@ -81,7 +81,7 @@ func pinnedIcon(pinnedAt time.Time) string { return "📌" // pinned } -func formatServerLine(s domain.Server) (primary, secondary string) { +func formatServerLine(s domain.Server, maxAliasWidth int) (primary, secondary string) { icon := cellPad(pinnedIcon(s.PinnedAt), 2) // forwarding column after Host/IP fGlyph := "" @@ -93,8 +93,15 @@ func formatServerLine(s domain.Server) (primary, secondary string) { if isFwd { fCol = "[#A0FFA0]" + fCol + "[-]" } + // Calculate the actual display width of the alias + aliasWidth := runewidth.StringWidth(s.Alias) + // Pad the alias to match maxAliasWidth + paddedAlias := s.Alias + if aliasWidth < maxAliasWidth { + paddedAlias = s.Alias + strings.Repeat(" ", maxAliasWidth-aliasWidth) + } // Use a consistent color for alias; host/IP fixed width; then forwarding column - primary = fmt.Sprintf("%s [white::b]%-12s[-] [#AAAAAA]%-18s[-] %s [#888888]Last SSH: %s[-] %s", icon, s.Alias, s.Host, fCol, humanizeDuration(s.LastSeen), renderTagBadgesForList(s.Tags)) + primary = fmt.Sprintf("%s [white::b]%s[-] [#AAAAAA]%-18s[-] %s [#888888]Last SSH: %-8s[-] %s", icon, paddedAlias, s.Host, fCol, humanizeDuration(s.LastSeen), renderTagBadgesForList(s.Tags)) secondary = "" return }