sshm/internal/ui/model.go
Gu1llaum-3 be3dcaa1cd fix: enable editing and management of hosts from included SSH config files
• Add SourceFile field to SSHHost struct to track config file origins
• Implement FindHostInAllConfigs() to locate hosts across all config files
• Fix "host not found" errors when editing/deleting hosts from included files
• Add GetAllConfigFiles() and GetAllConfigFilesFromBase() for config discovery
• Create UpdateSSHHostV2() and DeleteSSHHostV2() for cross-file operations
• Display config file source in edit and info forms for better visibility
• Add intelligent file selector for host addition when multiple configs exist
• Support -c parameter context with proper file resolution
• Exclude .backup files from Include directive processing
• Maintain backward compatibility with existing SSH config workflows

Resolves limitation where hosts from included config files could be viewed
but not edited, deleted, or properly managed through the interface.
2025-09-05 17:04:11 +02:00

118 lines
2.4 KiB
Go

package ui
import (
"sshm/internal/config"
"sshm/internal/history"
"github.com/charmbracelet/bubbles/table"
"github.com/charmbracelet/bubbles/textinput"
"github.com/charmbracelet/lipgloss"
)
// SortMode defines the available sorting modes
type SortMode int
const (
SortByName SortMode = iota
SortByLastUsed
)
func (s SortMode) String() string {
switch s {
case SortByName:
return "Name (A-Z)"
case SortByLastUsed:
return "Last Login"
default:
return "Name (A-Z)"
}
}
// ViewMode defines the current view state
type ViewMode int
const (
ViewList ViewMode = iota
ViewAdd
ViewEdit
ViewInfo
ViewPortForward
ViewHelp
ViewFileSelector
)
// PortForwardType defines the type of port forwarding
type PortForwardType int
const (
LocalForward PortForwardType = iota
RemoteForward
DynamicForward
)
func (p PortForwardType) String() string {
switch p {
case LocalForward:
return "Local (-L)"
case RemoteForward:
return "Remote (-R)"
case DynamicForward:
return "Dynamic (-D)"
default:
return "Local (-L)"
}
}
// Model represents the state of the user interface
type Model struct {
table table.Model
searchInput textinput.Model
hosts []config.SSHHost
filteredHosts []config.SSHHost
searchMode bool
deleteMode bool
deleteHost string
historyManager *history.HistoryManager
sortMode SortMode
configFile string // Path to the SSH config file
// View management
viewMode ViewMode
addForm *addFormModel
editForm *editFormModel
infoForm *infoFormModel
portForwardForm *portForwardModel
helpForm *helpModel
fileSelectorForm *fileSelectorModel
// Terminal size and styles
width int
height int
styles Styles
ready bool
}
// updateTableStyles updates the table header border color based on focus state
func (m *Model) updateTableStyles() {
s := table.DefaultStyles()
s.Selected = m.styles.Selected
if m.searchMode {
// When in search mode, use secondary color for table header
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color(SecondaryColor)).
BorderBottom(true).
Bold(false)
} else {
// When table is focused, use primary color for table header
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color(PrimaryColor)).
BorderBottom(true).
Bold(false)
}
m.table.SetStyles(s)
}