Skip to content

Commit 839582d

Browse files
Brandon Hclaude
andcommitted
feat: add CLI category creation and TUI entry editing
- Add `category add <name> [description]` CLI command for dynamic category creation - Add TUI entry editing with 'e' key - edit IP, hostnames, comment, and category - Implement AddCategory method in hosts parser with validation - Add comprehensive test coverage for new features - Update documentation (README.md, EXAMPLES.md, CLAUDE.md) with new functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent dd407dd commit 839582d

File tree

9 files changed

+1027
-7
lines changed

9 files changed

+1027
-7
lines changed

CLAUDE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,23 @@ func newCmd() *cobra.Command {
135135
4. Document in README.md
136136

137137
### Adding New Categories
138+
139+
**For programmatic categories (constants):**
138140
1. Add constant to `internal/hosts/types.go`
139141
2. Update default config in `internal/config/config.go`
140142
3. Document in user documentation
141143

144+
**For dynamic categories (CLI and TUI):**
145+
Categories can now be created dynamically using:
146+
- **CLI**: `hosts-manager category add <name> [description]`
147+
- **TUI**: Press 'c' in the main view to create categories interactively
148+
149+
**Implementation details:**
150+
- `AddCategory()` method in `internal/hosts/parser.go` handles category creation
151+
- Categories are validated using `validateCategoryName()` function
152+
- Empty categories are not written to hosts file (only categories with entries persist)
153+
- Both CLI and TUI support category creation with optional descriptions
154+
142155
### Platform-Specific Code
143156
Use the platform abstraction:
144157
```go
@@ -173,6 +186,11 @@ type model struct {
173186
moveCategoryCursor int // Move entry: target category cursor
174187
createCategoryName string // Create category: name field
175188
createCategoryDescription string // Create category: description field
189+
editEntryIndex int // Edit entry: index of entry being edited
190+
editIP string // Edit entry: IP field
191+
editHostnames string // Edit entry: hostnames field
192+
editComment string // Edit entry: comment field
193+
editCategory string // Edit entry: category field
176194
}
177195
```
178196

@@ -181,6 +199,7 @@ type model struct {
181199
- **viewSearch**: Real-time search and filtering
182200
- **viewHelp**: Help and keybinding information
183201
- **viewAdd**: Add new entry form with multi-field input
202+
- **viewEdit**: Edit existing entry with all fields (IP, hostnames, comment, category)
184203
- **viewMove**: Move entry between categories with guided selection
185204
- **viewCreateCategory**: Create new custom category with name/description
186205

@@ -191,6 +210,7 @@ case "up", "k": // Navigate up
191210
case "down", "j": // Navigate down
192211
case " ": // Toggle entry enabled/disabled
193212
case "a": // Add new entry
213+
case "e": // Edit selected entry
194214
case "d": // Delete selected entry
195215
case "m": // Move entry to different category
196216
case "c": // Create new category

EXAMPLES.md

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,24 @@ sudo hosts-manager add 172.17.0.4 elasticsearch.docker --category development
8787
sudo hosts-manager add 192.168.65.2 app.docker --category development --comment "Docker Desktop VM"
8888
```
8989

90+
### Creating Custom Categories
91+
92+
```bash
93+
# Create a custom category for specific projects
94+
sudo hosts-manager category add microservices "Microservices development environment"
95+
96+
# Create categories for different client projects
97+
sudo hosts-manager category add client-alpha "Client Alpha project hosts"
98+
sudo hosts-manager category add client-beta "Client Beta project hosts"
99+
100+
# Create environment-specific categories
101+
sudo hosts-manager category add testing "Integration testing environment"
102+
sudo hosts-manager category add demo "Demo environment for presentations"
103+
104+
# Verify categories were created
105+
hosts-manager category list
106+
```
107+
90108
### Switching Between Environments
91109

92110
```bash
@@ -296,12 +314,37 @@ Press Enter to create category
296314
# Recommended workflow for bulk changes
297315
hosts-manager tui
298316
# 1. Search for entries: /development
299-
# 2. Toggle multiple entries with space
300-
# 3. Add new entries with 'a'
301-
# 4. Move entries between categories with 'm'
302-
# 5. Create custom categories with 'c'
303-
# 6. Save all changes with 's'
304-
# 7. Confirm save message appears
317+
# 2. Navigate with arrow keys or j/k
318+
# 3. Toggle multiple entries with space
319+
# 4. Edit existing entries with 'e'
320+
# 5. Add new entries with 'a'
321+
# 6. Move entries between categories with 'm'
322+
# 7. Create custom categories with 'c'
323+
# 8. Save all changes with 's'
324+
# 9. Confirm save message appears
325+
```
326+
327+
**TUI Advanced Workflows:**
328+
329+
```bash
330+
# Edit existing entries
331+
hosts-manager tui
332+
# 1. Find the entry you want to edit
333+
# 2. Press 'e' to enter edit mode
334+
# 3. Use Tab/Shift+Tab to navigate between fields:
335+
# - IP Address
336+
# - Hostnames (space separated)
337+
# - Comment (optional)
338+
# - Category
339+
# 4. Press Enter to save changes
340+
# 5. Press Esc to cancel
341+
342+
# Bulk category management
343+
hosts-manager tui
344+
# 1. Create new categories with 'c'
345+
# 2. Select entries and move them with 'm'
346+
# 3. Use search ('/') to filter entries
347+
# 4. Save all changes with 's'
305348
```
306349

307350
## Advanced Use Cases

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ hosts-manager restore hosts.backup.2023-12-07T10-30-45
183183
hosts-manager category list
184184
```
185185

186+
#### Add New Category
187+
```bash
188+
# Add category with name only
189+
hosts-manager category add testing
190+
191+
# Add category with name and description
192+
hosts-manager category add testing "Testing environment hosts"
193+
```
194+
186195
#### Enable/Disable Category
187196
```bash
188197
hosts-manager category enable development
@@ -236,6 +245,7 @@ hosts-manager tui
236245
- `↑/↓` or `k/j` - Navigate entries
237246
- `space` - Toggle entry enabled/disabled
238247
- `a` - Add new entry
248+
- `e` - Edit selected entry
239249
- `d` - Delete entry
240250
- `m` - Move entry to different category
241251
- `c` - Create new category
@@ -245,7 +255,8 @@ hosts-manager tui
245255
- `?` - Help
246256
- `q` - Quit
247257

248-
**New TUI Features:**
258+
**Advanced TUI Features:**
259+
- **Edit entries**: Use `e` to edit the selected entry's IP, hostnames, comment, and category
249260
- **Move entries**: Use `m` to move selected entry to a different category with guided interface
250261
- **Create categories**: Use `c` to create new custom categories with name and description
251262

cmd/hosts-manager/commands.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ func categoryCmd() *cobra.Command {
353353
}
354354

355355
cmd.AddCommand(categoryListCmd())
356+
cmd.AddCommand(categoryAddCmd())
356357
cmd.AddCommand(categoryEnableCmd())
357358
cmd.AddCommand(categoryDisableCmd())
358359

@@ -392,6 +393,68 @@ func categoryListCmd() *cobra.Command {
392393
return cmd
393394
}
394395

396+
func categoryAddCmd() *cobra.Command {
397+
cmd := &cobra.Command{
398+
Use: "add <name> [description]",
399+
Short: "Add a new category",
400+
Args: cobra.RangeArgs(1, 2),
401+
RunE: func(cmd *cobra.Command, args []string) error {
402+
p := platform.New()
403+
if err := p.ElevateIfNeeded(); err != nil {
404+
return err
405+
}
406+
407+
parser := hosts.NewParser(p.GetHostsFilePath())
408+
hostsFile, err := parser.Parse()
409+
if err != nil {
410+
return fmt.Errorf("failed to parse hosts file: %w", err)
411+
}
412+
413+
categoryName := args[0]
414+
description := ""
415+
if len(args) > 1 {
416+
description = args[1]
417+
}
418+
419+
backupMgr := backup.NewManager(cfg)
420+
if cfg.General.AutoBackup {
421+
if _, err := backupMgr.CreateBackup(); err != nil {
422+
return fmt.Errorf("failed to create backup: %w", err)
423+
}
424+
if verbose {
425+
fmt.Println("Backup created successfully")
426+
}
427+
}
428+
429+
if dryRun {
430+
fmt.Printf("Would add category: %s", categoryName)
431+
if description != "" {
432+
fmt.Printf(" - %s", description)
433+
}
434+
fmt.Println()
435+
return nil
436+
}
437+
438+
if err := hostsFile.AddCategory(categoryName, description); err != nil {
439+
return fmt.Errorf("failed to add category: %w", err)
440+
}
441+
442+
if err := hostsFile.Write(p.GetHostsFilePath()); err != nil {
443+
return fmt.Errorf("failed to write hosts file: %w", err)
444+
}
445+
446+
fmt.Printf("Added category: %s", categoryName)
447+
if description != "" {
448+
fmt.Printf(" - %s", description)
449+
}
450+
fmt.Println()
451+
return nil
452+
},
453+
}
454+
455+
return cmd
456+
}
457+
395458
func categoryEnableCmd() *cobra.Command {
396459
cmd := &cobra.Command{
397460
Use: "enable <category>",

0 commit comments

Comments
 (0)