Skip to content

Commit 617fa46

Browse files
committed
♻️ refactor(cmd,config,docs): fix golangci-lint issues and improve code quality
Lint fixes (CI): - version.go: replace len(test) == 0 with test == "" (emptyStringTest) - config.go: reduce cyclomatic complexity (17 → 5) via extraction * Extract checkVersionFlag() helper * Extract defineFlags() helper * Extract mergeConfigs() helper * Main Load() now has clear 3-step flow Documentation: - Add comprehensive shell config examples (bash/zsh/fish) - Use collapsible sections for better readability - Include reload commands for each shell All tests passing, lint clean ✅
1 parent 08930bd commit 617fa46

File tree

3 files changed

+83
-42
lines changed

3 files changed

+83
-42
lines changed

README.md

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,52 @@ If you have Go 1.21+ installed:
107107
go install github.com/anIcedAntFA/gohome/cmd/gohome@latest
108108
```
109109

110-
> ⚠️ **Note:** When using production releases (installed via curl or binary download), ensure `/usr/local/bin` comes **before** `$GOPATH/bin` in your `$PATH` to avoid conflicts with dev builds.
110+
> ⚠️ **Path Configuration:** When using production releases (installed via curl or binary download), ensure `/usr/local/bin` comes **before** `$GOPATH/bin` in your `$PATH` to avoid conflicts with dev builds.
111+
>
112+
> **Shell Configuration Examples:**
113+
>
114+
> <details>
115+
> <summary><strong>Bash</strong> (~/.bashrc or ~/.bash_profile)</summary>
116+
>
117+
> ```bash
118+
> # Go environment
119+
> export GOPATH=$HOME/go
120+
> export PATH=$PATH:$GOPATH/bin # Append GOPATH/bin (lower priority)
121+
> ```
122+
> </details>
123+
>
124+
> <details>
125+
> <summary><strong>Zsh</strong> (~/.zshrc)</summary>
126+
>
127+
> ```zsh
128+
> # Go environment
129+
> export GOPATH=$HOME/go
130+
> export PATH=$PATH:$GOPATH/bin # Append GOPATH/bin (lower priority)
131+
> ```
132+
> </details>
133+
>
134+
> <details>
135+
> <summary><strong>Fish</strong> (~/.config/fish/config.fish)</summary>
111136
>
112-
> **Fish shell users:**
113137
> ```fish
114-
> # Correct order - system bins have priority
115-
> set -gx PATH $PATH $HOME/go/bin
138+
> # Go environment
139+
> set -gx GOPATH $HOME/go
140+
> set -gx PATH $PATH $GOPATH/bin # Append GOPATH/bin (lower priority)
141+
> # Or use fish_add_path for better management:
142+
> # fish_add_path -aP $GOPATH/bin
143+
> ```
144+
> </details>
145+
>
146+
> After updating your shell config, reload it:
147+
> ```bash
148+
> # Bash
149+
> source ~/.bashrc
150+
>
151+
> # Zsh
152+
> source ~/.zshrc
153+
>
154+
> # Fish
155+
> source ~/.config/fish/config.fish
116156
> ```
117157
118158
### Download Binary

internal/config/config.go

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,43 @@ func (c *AppConfig) SaveToFile() error {
176176
// It merges defaults from config file with CLI arguments.
177177
func Load() *AppConfig {
178178
// Check for version flag early (before flag parsing)
179+
checkVersionFlag()
180+
181+
// A. Load defaults from file first (if exists)
182+
fileCfg := loadConfigFromFile()
183+
184+
cfg := &AppConfig{}
185+
186+
// B. Define all flags
187+
defineFlags(cfg)
188+
189+
flag.Usage = printUsage
190+
flag.Parse()
191+
192+
// Track which flags were explicitly set by user
193+
userSetFlags := make(map[string]bool)
194+
flag.Visit(func(f *flag.Flag) {
195+
userSetFlags[f.Name] = true
196+
})
197+
198+
// C. Merge file config with CLI flags
199+
mergeConfigs(cfg, &fileCfg, userSetFlags)
200+
201+
return cfg
202+
}
203+
204+
// checkVersionFlag handles early version flag detection.
205+
func checkVersionFlag() {
179206
for _, arg := range os.Args[1:] {
180207
if arg == "--version" || arg == "-v" {
181208
fmt.Println(getVersion())
182209
os.Exit(0)
183210
}
184211
}
212+
}
185213

186-
// A. Load defaults from file first (if exists)
187-
fileCfg := loadConfigFromFile()
188-
189-
cfg := &AppConfig{}
190-
191-
// B. Define flags
214+
// defineFlags sets up all command-line flags.
215+
func defineFlags(cfg *AppConfig) {
192216
flag.IntVar(&cfg.Hours, "hours", 0, "")
193217
flag.IntVar(&cfg.Hours, "H", 0, "")
194218

@@ -232,57 +256,36 @@ func Load() *AppConfig {
232256

233257
// Add flag for user to save config
234258
flag.BoolVar(&cfg.SaveConfig, "save", false, "Save current arguments as default configuration")
259+
}
235260

236-
flag.Usage = printUsage
237-
flag.Parse()
238-
239-
// Track which flags were explicitly set by user
240-
userSetFlags := make(map[string]bool)
241-
flag.Visit(func(f *flag.Flag) {
242-
userSetFlags[f.Name] = true
243-
})
244-
245-
// --- A. Handle time period group (mutual exclusion) ---
246-
// Logic: If user sets ANY time flag -> ignore all time values from file.
247-
// If user sets NO time flags -> use all time values from file.
248-
249-
isTimeSetByUser := checkTimeFlags(userSetFlags)
250-
251-
if !isTimeSetByUser {
252-
// User didn't specify any time flags, load from file
261+
// mergeConfigs merges file configuration with CLI flags based on user-set flags.
262+
func mergeConfigs(cfg, fileCfg *AppConfig, userSetFlags map[string]bool) {
263+
// Handle time period group (mutual exclusion)
264+
// If user sets ANY time flag -> ignore all time values from file
265+
if !checkTimeFlags(userSetFlags) {
253266
cfg.Hours = fileCfg.Hours
254267
cfg.Days = fileCfg.Days
255268
cfg.Weeks = fileCfg.Weeks
256269
cfg.Months = fileCfg.Months
257270
cfg.Years = fileCfg.Years
258271
cfg.Today = fileCfg.Today
259272
}
260-
// Otherwise: User has specified time flags (e.g., -d 5).
261-
// Since flag defaults are 0/false, cfg.Today is false and cfg.Weeks is 0.
262-
// Only cfg.Days is 5. Logic is correct!
263-
264-
// --- B. Handle other independent flags ---
265-
// Logic: If user didn't set a flag, use value from file (if available)
266273

274+
// Handle other independent flags
267275
if !isSet(userSetFlags, "path", "p") && fileCfg.Path != "" {
268276
cfg.Path = fileCfg.Path
269277
}
270278
if !isSet(userSetFlags, "author", "a") && fileCfg.Author != "" {
271279
cfg.Author = fileCfg.Author
272280
}
273-
// For output format, need careful check since CLI default is "text"
274-
// If user didn't specify format flag, prioritize file value
275281
if !isSet(userSetFlags, "format", "f") && fileCfg.OutputFmt != "" {
276282
cfg.OutputFmt = fileCfg.OutputFmt
277283
}
278-
// Same logic for preset/style
279284
if !isSet(userSetFlags, "style", "s") && fileCfg.Preset != "" {
280285
cfg.Preset = fileCfg.Preset
281286
}
282287

283-
// Boolean flags (Icon/Scope)
284-
// Note: with booleans, if file is true and user wants to disable, user must override (but bool flags rarely support --flag=false easily).
285-
// Simplest approach for Phase 1: If user didn't touch the flag, use value from file.
288+
// Boolean flags
286289
if !isSet(userSetFlags, "icon", "i") {
287290
cfg.ShowIcon = fileCfg.ShowIcon
288291
}
@@ -296,8 +299,6 @@ func Load() *AppConfig {
296299
if len(fileCfg.Tasks) > 0 {
297300
cfg.Tasks = fileCfg.Tasks
298301
}
299-
300-
return cfg
301302
}
302303

303304
// checkTimeFlags checks if user has set any time-related flag.

internal/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func isSemanticVersion(v string) bool {
116116

117117
// Must start with digit and contain a dot (e.g., 1.0.1, not just "1")
118118
// This distinguishes semantic versions from plain commit hashes
119-
if len(test) == 0 || test[0] < '0' || test[0] > '9' {
119+
if test == "" || test[0] < '0' || test[0] > '9' {
120120
return false
121121
}
122122

0 commit comments

Comments
 (0)