diff --git a/commands/core/lookup.go b/commands/core/lookup.go index a7eb941..52d045b 100644 --- a/commands/core/lookup.go +++ b/commands/core/lookup.go @@ -1,6 +1,8 @@ package core import ( + "maps" + "slices" "strings" "sync" @@ -24,9 +26,7 @@ func GetAliasesCopy() map[string]string { shellAliasesMu.RLock() defer shellAliasesMu.RUnlock() cp := make(map[string]string, len(ShellAliases)) - for k, v := range ShellAliases { - cp[k] = v - } + maps.Copy(cp, ShellAliases) return cp } @@ -123,11 +123,8 @@ func Lookup(input string) []Suggestion { for _, sub := range currentSubs { match := sub.Name == tok if !match { - for _, a := range sub.Aliases { - if a == tok { - match = true - break - } + if slices.Contains(sub.Aliases, tok) { + match = true } } @@ -209,8 +206,8 @@ func Lookup(input string) []Suggestion { suggested = "\"" + suggested + "\"" } - // if the suggestion is a full path that includes - // words already in the command line (multi-word support), we replace + // if the suggestion is a full path that includes + // words already in the command line (multi-word support), we replace // the entire argument part by using prefix only finalCmd := "" if len(tokens) > depth+1 && strings.HasPrefix(g.Cmd, tokens[depth]) { diff --git a/commands/fs/zoxide.go b/commands/fs/zoxide.go index 2e86b83..8149366 100644 --- a/commands/fs/zoxide.go +++ b/commands/fs/zoxide.go @@ -51,10 +51,7 @@ func ZoxideGenerator() core.GeneratorFunc { home, _ := os.UserHomeDir() if fullQuery == "" { - limit := 20 - if len(dirs) < limit { - limit = len(dirs) - } + limit := min(len(dirs), 20) for i := 0; i < limit; i++ { path := dirs[i] display := strings.Replace(path, home, "~", 1) diff --git a/commands/git/git.go b/commands/git/git.go index c169789..f03416a 100644 --- a/commands/git/git.go +++ b/commands/git/git.go @@ -34,7 +34,7 @@ func GitCommitGenerator(tokens []string, _ string, _ string) []core.Suggestion { } var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" { continue diff --git a/commands/ops/docker.go b/commands/ops/docker.go index abb36d7..7da1c2f 100644 --- a/commands/ops/docker.go +++ b/commands/ops/docker.go @@ -22,7 +22,7 @@ func dockerContainerGenerator(tokens []string, _ string, _ string) []core.Sugges } var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" { continue @@ -45,7 +45,7 @@ func dockerRunningContainerGenerator(tokens []string, _ string, _ string) []core } var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" { continue @@ -69,7 +69,7 @@ func dockerImageGenerator(tokens []string, _ string, _ string) []core.Suggestion seen := make(map[string]bool) var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" || line == ":" || seen[line] { continue diff --git a/commands/pkginstaller/pkgmgr.go b/commands/pkginstaller/pkgmgr.go index ee773e7..bed9ff9 100644 --- a/commands/pkginstaller/pkgmgr.go +++ b/commands/pkginstaller/pkgmgr.go @@ -34,7 +34,7 @@ func installedPackageGenerator(pm string) core.GeneratorFunc { } var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" { continue diff --git a/commands/python/pip.go b/commands/python/pip.go index 931427f..e901091 100644 --- a/commands/python/pip.go +++ b/commands/python/pip.go @@ -25,7 +25,7 @@ func pipPackageGenerator(tokens []string, _ string, _ string) []core.Suggestion } var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" { continue diff --git a/commands/runner/justfile.go b/commands/runner/justfile.go index c248d11..9182c42 100644 --- a/commands/runner/justfile.go +++ b/commands/runner/justfile.go @@ -34,10 +34,10 @@ func init() { lastComment := "" for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) - + // Handle comments - if strings.HasPrefix(line, "#") { - lastComment = strings.TrimSpace(strings.TrimPrefix(line, "#")) + if after, ok := strings.CutPrefix(line, "#"); ok { + lastComment = strings.TrimSpace(after) continue } @@ -55,7 +55,7 @@ func init() { seen[recipe] = true cmd := recipe - + desc := "just recipe" if lastComment != "" { desc = lastComment diff --git a/commands/sys/ps.go b/commands/sys/ps.go index 090717b..88ef065 100644 --- a/commands/sys/ps.go +++ b/commands/sys/ps.go @@ -22,7 +22,7 @@ func processGenerator(tokens []string, _ string, _ string) []core.Suggestion { seen := make(map[string]bool) var results []core.Suggestion - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSpace(line) if line == "" { continue diff --git a/integration/history.go b/integration/history.go index 7501e99..b27f7b1 100644 --- a/integration/history.go +++ b/integration/history.go @@ -95,8 +95,8 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error } } } else if shellName == "fish" { - if strings.HasPrefix(line, "- cmd: ") { - cmd = strings.TrimPrefix(line, "- cmd: ") + if after, ok := strings.CutPrefix(line, "- cmd: "); ok { + cmd = after } else { continue } @@ -128,10 +128,7 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error if query == "" { var results []HistResult - limit := 100 - if len(historyCache) < limit { - limit = len(historyCache) - } + limit := min(len(historyCache), 100) for i := 0; i < limit; i++ { cmd := historyCache[i] @@ -251,11 +248,11 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error if tI != tJ { return tI < tJ } - + if tI == 4 && results[i].FuzzyScore != results[j].FuzzyScore { return results[i].FuzzyScore > results[j].FuzzyScore } - + return results[i].ID > results[j].ID }) diff --git a/integration/overlay.go b/integration/overlay.go index b1820b6..8d31268 100644 --- a/integration/overlay.go +++ b/integration/overlay.go @@ -72,10 +72,7 @@ func ComputeCursorCol(data []byte) int { col = 0 } case 'G': - col = getParam(0, 1) - 1 - if col < 0 { - col = 0 - } + col = max(getParam(0, 1)-1, 0) } i = j + 1 continue @@ -313,7 +310,6 @@ func (o *Overlay) SetHistoryList(items []core.Suggestion, startAtBottom bool) st return "" } - func fixedWidth(s string, width int) string { if width <= 0 { return "" @@ -365,10 +361,7 @@ func (o *Overlay) RenderGhostText(buffer string, userNavigated bool) string { } ghostWidth := lipgloss.Width(ghostText) - padLen := o.LastGhostLen - ghostWidth - if padLen < 0 { - padLen = 0 - } + padLen := max(o.LastGhostLen-ghostWidth, 0) if o.LastGhostLen > 0 { padLen += 4 } @@ -410,10 +403,7 @@ func renderMatchedTitle(title, typed string, selected bool, w int) string { typedRunes := []rune(typed) displayRunes := []rune(display) - matchLen := len(typedRunes) - if matchLen > len(displayRunes) { - matchLen = len(displayRunes) - } + matchLen := min(len(typedRunes), len(displayRunes)) return match.Render(string(displayRunes[:matchLen])) + base.Render(string(displayRunes[matchLen:])) } @@ -453,10 +443,7 @@ func (o *Overlay) draw() string { s.WriteString("\0337") - windowSize := maxItems - if len(o.Items) < windowSize { - windowSize = len(o.Items) - } + windowSize := min(len(o.Items), maxItems) scrolloffUp := 1 if windowSize <= 3 { @@ -598,10 +585,7 @@ func (o *Overlay) draw() string { } tag := boxStyle.Render(" alias ") tw := lipgloss.Width(tag) - rem := descW - tw - 1 - if rem < 0 { - rem = 0 - } + rem := max(descW-tw-1, 0) desc = tag + bg.Render(" ") + bg.Foreground(descColor).Render(fixedWidth(it.Desc, rem)) case "history": boxStyle := lipgloss.NewStyle().Background(lipgloss.Color("#1a2d36")).Foreground(lipgloss.Color("#61ffca")) @@ -610,10 +594,7 @@ func (o *Overlay) draw() string { } tag := boxStyle.Render(" history ") tw := lipgloss.Width(tag) - rem := descW - tw - if rem < 0 { - rem = 0 - } + rem := max(descW-tw, 0) desc = tag + bg.Render(strings.Repeat(" ", rem)) case "system": boxStyle := lipgloss.NewStyle().Background(lipgloss.Color("#1e1d28")).Foreground(lipgloss.Color("#a277ff")) @@ -622,10 +603,7 @@ func (o *Overlay) draw() string { } tag := boxStyle.Render(" system ") tw := lipgloss.Width(tag) - rem := descW - tw - if rem < 0 { - rem = 0 - } + rem := max(descW-tw, 0) desc = tag + bg.Render(strings.Repeat(" ", rem)) default: desc = bg.Foreground(descColor).Render(fixedWidth(it.Desc, descW)) @@ -698,7 +676,7 @@ func (o *Overlay) Clear() string { s.WriteString("\033[?7l") s.WriteString("\0337") - for i := 0; i < maxItems+2; i++ { + for i := range maxItems + 2 { s.WriteString("\0338") fmt.Fprintf(&s, "\033[%dB", i+1) s.WriteString("\r\033[2K") @@ -736,7 +714,7 @@ func (o *Overlay) ClearAndDisable() string { s.WriteString("\0337") - for i := 0; i < maxItems+2; i++ { + for i := range maxItems + 2 { s.WriteString("\0338") fmt.Fprintf(&s, "\033[%dB", i+1) s.WriteString("\r\033[2K") diff --git a/integration/shell/adapter.go b/integration/shell/adapter.go index 8294993..3acf4b0 100644 --- a/integration/shell/adapter.go +++ b/integration/shell/adapter.go @@ -102,8 +102,8 @@ func ScanPosixAliases(files []string) map[string]string { func ParseAliases(data string) map[string]string { aliases := make(map[string]string) - lines := strings.Split(data, "\n") - for _, line := range lines { + lines := strings.SplitSeq(data, "\n") + for line := range lines { line = strings.TrimSpace(line) if !strings.HasPrefix(line, "alias ") { continue @@ -115,12 +115,12 @@ func ParseAliases(data string) map[string]string { pairs := SplitAliasTokens(body) for _, pair := range pairs { - eqIdx := strings.IndexByte(pair, '=') - if eqIdx < 0 { + before, after, ok := strings.Cut(pair, "=") + if !ok { continue } - key := strings.TrimSpace(pair[:eqIdx]) - val := strings.Trim(strings.TrimSpace(pair[eqIdx+1:]), `"'`) + key := strings.TrimSpace(before) + val := strings.Trim(strings.TrimSpace(after), `"'`) if key != "" && val != "" { aliases[key] = val } diff --git a/root/wrapper.go b/root/wrapper.go index 75883b3..f692ac0 100644 --- a/root/wrapper.go +++ b/root/wrapper.go @@ -170,7 +170,7 @@ func runWrapper() { out, errCmd := exec.CommandContext(ctx, "lsof", "-p", fmt.Sprintf("%d", c.Process.Pid), "-a", "-d", "cwd", "-F", "n").Output() cancel() if errCmd == nil { - for _, line := range strings.Split(string(out), "\n") { + for line := range strings.SplitSeq(string(out), "\n") { if strings.HasPrefix(line, "n") { cwd = strings.TrimSpace(line[1:]) linkErr = nil @@ -191,8 +191,8 @@ func runWrapper() { if logDir, pathErr := config.CachePath(); pathErr == nil { argsFile := filepath.Join(logDir, "reload-args") if data, readErr := os.ReadFile(argsFile); readErr == nil { - lines := strings.Split(string(data), "\n") - for _, line := range lines { + lines := strings.SplitSeq(string(data), "\n") + for line := range lines { trimmed := strings.TrimSpace(line) if trimmed != "" { execArgs = append(execArgs, trimmed) @@ -560,10 +560,7 @@ func runWrapper() { activeModeMu.RUnlock() results := MergeResults("", currentMode) if len(results) > 0 { - limit := 100 - if len(results) < limit { - limit = len(results) - } + limit := min(len(results), 100) var historyList []core.Suggestion if inputSlice[i+2] == 'A' { diff --git a/tests/dev/git_test.go b/tests/dev/git_test.go index 69a4e01..c6f199d 100644 --- a/tests/dev/git_test.go +++ b/tests/dev/git_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "github.com/versenilvis/iris/commands/core" _ "github.com/versenilvis/iris/commands" + "github.com/versenilvis/iris/commands/core" ) // setupGitRepo creates a real git repo in a temp dir with: @@ -188,7 +188,6 @@ func TestGitSuggestions(t *testing.T) { } }) - t.Run("branch with slash is suggested correctly", func(t *testing.T) { res := core.Lookup("git checkout ") found := false @@ -204,13 +203,14 @@ func TestGitSuggestions(t *testing.T) { t.Run("remote branches suggested for push", func(t *testing.T) { res := core.Lookup("git push origin ") - cmdStr := "" + var cmdStr strings.Builder for _, r := range res { - cmdStr += r.Cmd + " " + cmdStr.WriteString(r.Cmd) + cmdStr.WriteByte(' ') } // should have at least dev or main from branch list - if !strings.Contains(cmdStr, "dev") && !strings.Contains(cmdStr, "main") { - t.Errorf("git push origin should suggest local branches, got: %s", cmdStr) + if !strings.Contains(cmdStr.String(), "dev") && !strings.Contains(cmdStr.String(), "main") { + t.Errorf("git push origin should suggest local branches, got: %s", cmdStr.String()) } }) @@ -226,8 +226,8 @@ func TestGitSuggestions(t *testing.T) { res := core.Lookup("git checkout ") for _, r := range res { // the suggestion should not contain the active branch as a standalone word - parts := strings.Fields(r.Cmd) - for _, p := range parts { + parts := strings.FieldsSeq(r.Cmd) + for p := range parts { if p == activeBranch { t.Errorf("git checkout should not suggest active branch '%s', got: %s", activeBranch, r.Cmd) } @@ -365,8 +365,8 @@ func TestGitSuggestions(t *testing.T) { res := core.Lookup("git -c core.pager=cat checkout ") for _, r := range res { - parts := strings.Fields(r.Cmd) - for _, p := range parts { + parts := strings.FieldsSeq(r.Cmd) + for p := range parts { if p == activeBranch { t.Errorf("git -c core.pager=cat checkout should not suggest active branch '%s', got: %s", activeBranch, r.Cmd) } diff --git a/tests/dev/npm_ssh_test.go b/tests/dev/npm_ssh_test.go index 98d4b6b..b07979d 100644 --- a/tests/dev/npm_ssh_test.go +++ b/tests/dev/npm_ssh_test.go @@ -7,9 +7,9 @@ import ( "strings" "testing" + _ "github.com/versenilvis/iris/commands" "github.com/versenilvis/iris/commands/core" "github.com/versenilvis/iris/commands/js" - _ "github.com/versenilvis/iris/commands" ) func TestNpmScriptGenerator(t *testing.T) { @@ -20,11 +20,11 @@ func TestNpmScriptGenerator(t *testing.T) { pkg := map[string]any{ "name": "test-app", "scripts": map[string]string{ - "dev": "vite", - "build": "vite build", - "test": "vitest", - "lint": "eslint .", - "preview": "vite preview", + "dev": "vite", + "build": "vite build", + "test": "vitest", + "lint": "eslint .", + "preview": "vite preview", "typecheck": "tsc --noEmit", }, } @@ -173,7 +173,7 @@ func sshHostGeneratorFromPath(configPath string) []core.Suggestion { _ = scanner data, _ := os.ReadFile(configPath) - for _, line := range strings.Split(string(data), "\n") { + for line := range strings.SplitSeq(string(data), "\n") { line = strings.TrimSpace(line) if !strings.HasPrefix(strings.ToLower(line), "host ") { continue