diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 5de2df8..0000000 --- a/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# https://editorconfig.org/ - -root = true - -[*] -charset = utf-8 -insert_final_newline = true -trim_trailing_whitespace = true -indent_style = space -indent_size = 2 - -[*.go] -indent_style = tab -indent_size = 8 - -[*.golden] -insert_final_newline = false -trim_trailing_whitespace = false diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..3c190d7 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @charmbracelet/everyone diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d944991..cbc9aa4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,14 +13,6 @@ updates: commit-message: prefix: "chore" include: "scope" - groups: - all: - patterns: - - "*" - ignore: - - dependency-name: github.com/charmbracelet/bubbletea/v2 - versions: - - v2.0.0-beta1 - package-ecosystem: "github-actions" directory: "/" @@ -34,10 +26,6 @@ updates: commit-message: prefix: "chore" include: "scope" - groups: - all: - patterns: - - "*" - package-ecosystem: "docker" directory: "/" @@ -49,9 +37,5 @@ updates: labels: - "dependencies" commit-message: - prefix: "chore" + prefix: "feat" include: "scope" - groups: - all: - patterns: - - "*" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7fbd40b..f82e3d0 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -8,10 +8,10 @@ jobs: GO111MODULE: "on" steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v6 + uses: actions/setup-go@v5 with: go-version: stable diff --git a/.github/workflows/lint-sync.yml b/.github/workflows/lint-sync.yml deleted file mode 100644 index 43f380f..0000000 --- a/.github/workflows/lint-sync.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: lint-sync -on: - schedule: - - cron: "0 0 * * 0" # every sunday at midnight - workflow_dispatch: - -permissions: - contents: write - pull-requests: write - -jobs: - lint: - uses: charmbracelet/meta/.github/workflows/lint-sync.yml@main diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1e21125..6a2418e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,9 +8,9 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v9.2.0 + uses: golangci/golangci-lint-action@v6.5.0 with: # Optional: golangci-lint command line arguments. args: --issues-exit-code=0 diff --git a/.golangci.yml b/.golangci.yml index 929cb0a..911a28b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,44 +1,33 @@ -version: "2" run: tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + linters: enable: - bodyclose - - exhaustive + - dupl - goconst - godot - - gomoddirectives + - godox + - gofumpt + - goimports - goprintffuncname - gosec - misspell - - nakedret - - nestif - - nilerr - - noctx - - nolintlint - prealloc - revive - rowserrcheck - sqlclosecheck - - tparallel - unconvert - unparam - whitespace - - wrapcheck - exclusions: - rules: - - text: '(slog|log)\.\w+' - linters: - - noctx - generated: lax - presets: - - common-false-positives -issues: - max-issues-per-linter: 0 - max-same-issues: 0 -formatters: - enable: - - gofumpt - - goimports - exclusions: - generated: lax diff --git a/.goreleaser.yml b/.goreleaser.yml index 0c539b7..22bd6e5 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -8,7 +8,7 @@ includes: variables: description: "Render markdown on the CLI, with pizzazz!" - github_url: "https://github.com/charmbracelet/glow" + github_url: "https://github.com/charmbracelet/soft-serve" maintainer: "Christian Muehlhaeuser " brew_commit_author_name: "Christian Muehlhaeuser" brew_commit_author_email: "muesli@charm.sh" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4985f56 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +# This Makefile is just for development purposes + +.PHONY: default clean glow run log + +default: glow + +clean: + rm -f ./glow + +glow: + go build + +run: clean glow + ./glow + +log: + tail -f ~/.cache/glow/glow.log diff --git a/README.md b/README.md index cf3bb15..1e2b202 100644 --- a/README.md +++ b/README.md @@ -30,64 +30,39 @@ Git repository. ```bash # macOS or Linux brew install glow -``` -```bash # macOS (with MacPorts) sudo port install glow -``` -```bash # Arch Linux (btw) pacman -S glow -``` -```bash # Void Linux xbps-install -S glow -``` -```bash # Nix shell nix-shell -p glow --command glow -``` -```bash # FreeBSD pkg install glow -``` -```bash # Solus eopkg install glow -``` -```bash # Windows (with Chocolatey, Scoop, or Winget) choco install glow scoop install glow winget install charmbracelet.glow -``` -```bash # Android (with termux) pkg install glow -``` -```bash -# Ubuntu (Snapcraft) -sudo snap install glow -``` - -```bash # Debian/Ubuntu sudo mkdir -p /etc/apt/keyrings curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list sudo apt update && sudo apt install glow -``` -```bash # Fedora/RHEL echo '[charm] name=Charm @@ -107,7 +82,7 @@ packages. ARM builds are also available for macOS, Linux, FreeBSD and OpenBSD. Or just install it with `go`: ```bash -go install github.com/charmbracelet/glow/v2@latest +go install github.com/charmbracelet/glow@latest ``` ### Build (requires Go 1.21+) @@ -209,18 +184,8 @@ pager: true width: 80 # show all files, including hidden and ignored. all: false -# show line numbers (TUI-mode only) -showLineNumbers: false -# preserve newlines in the output -preserveNewLines: false ``` -## Contributing - -See [contributing][contribute]. - -[contribute]: https://github.com/charmbracelet/glow/contribute - ## Feedback We’d love to hear your thoughts on this project. Feel free to drop us a note! diff --git a/Taskfile.yaml b/Taskfile.yaml deleted file mode 100644 index 6d8c844..0000000 --- a/Taskfile.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# https://taskfile.dev - -version: '3' - -tasks: - lint: - desc: Run base linters - cmds: - - golangci-lint run - - test: - desc: Run tests - cmds: - - go test ./... {{.CLI_ARGS}} - - log: - desc: Watch for glow logs - aliases: [tail] - cmds: - - cmd: tail -f ~/Library/Caches/glow/glow.log - platforms: [darwin] - - cmd: tail -f ~/.cache/glow/glow.log - platforms: [linux, windows] diff --git a/config_cmd.go b/config_cmd.go index 390a1db..7147ab8 100644 --- a/config_cmd.go +++ b/config_cmd.go @@ -39,13 +39,13 @@ var configCmd = &cobra.Command{ c, err := editor.Cmd("Glow", configFile) if err != nil { - return fmt.Errorf("unable to set config file: %w", err) + return err } c.Stdin = os.Stdin c.Stdout = os.Stdout c.Stderr = os.Stderr if err := c.Run(); err != nil { - return fmt.Errorf("unable to run command: %w", err) + return err } fmt.Println("Wrote config file to:", configFile) @@ -56,7 +56,7 @@ var configCmd = &cobra.Command{ func ensureConfigFile() error { if configFile == "" { configFile = viper.GetViper().ConfigFileUsed() - if err := os.MkdirAll(filepath.Dir(configFile), 0o755); err != nil { //nolint:gosec + if err := os.MkdirAll(filepath.Dir(configFile), 0o755); err != nil { return fmt.Errorf("could not write configuration file: %w", err) } } @@ -69,20 +69,20 @@ func ensureConfigFile() error { // File doesn't exist yet, create all necessary directories and // write the default config file if err := os.MkdirAll(filepath.Dir(configFile), 0o700); err != nil { - return fmt.Errorf("unable create directory: %w", err) + return err } f, err := os.Create(configFile) if err != nil { - return fmt.Errorf("unable to create config file: %w", err) + return err } defer func() { _ = f.Close() }() if _, err := f.WriteString(defaultConfig); err != nil { - return fmt.Errorf("unable to write config file: %w", err) + return err } } else if err != nil { // some other error occurred - return fmt.Errorf("unable to stat config file: %w", err) + return err } return nil } diff --git a/github.go b/github.go index fe862e3..6b169fa 100644 --- a/github.go +++ b/github.go @@ -23,29 +23,29 @@ func findGitHubREADME(u *url.URL) (*source, error) { apiURL := fmt.Sprintf("https://api.%s/repos/%s/%s/readme", u.Hostname(), owner, repo) - //nolint:bodyclose + // nolint:bodyclose // it is closed on the caller - res, err := http.Get(apiURL) //nolint: gosec,noctx + res, err := http.Get(apiURL) // nolint: gosec if err != nil { - return nil, fmt.Errorf("unable to get url: %w", err) + return nil, err } body, err := io.ReadAll(res.Body) if err != nil { - return nil, fmt.Errorf("unable to read http response body: %w", err) + return nil, err } var result readme if err := json.Unmarshal(body, &result); err != nil { - return nil, fmt.Errorf("unable to parse json: %w", err) + return nil, err } if res.StatusCode == http.StatusOK { - //nolint:bodyclose + // nolint:bodyclose // it is closed on the caller - resp, err := http.Get(result.DownloadURL) //nolint: noctx + resp, err := http.Get(result.DownloadURL) if err != nil { - return nil, fmt.Errorf("unable to get url: %w", err) + return nil, err } if resp.StatusCode == http.StatusOK { diff --git a/gitlab.go b/gitlab.go index 68256be..05e1239 100644 --- a/gitlab.go +++ b/gitlab.go @@ -25,31 +25,31 @@ func findGitLabREADME(u *url.URL) (*source, error) { apiURL := fmt.Sprintf("https://%s/api/v4/projects/%s", u.Hostname(), projectPath) - //nolint:bodyclose + // nolint:bodyclose // it is closed on the caller - res, err := http.Get(apiURL) //nolint: gosec,noctx + res, err := http.Get(apiURL) // nolint: gosec if err != nil { - return nil, fmt.Errorf("unable to get url: %w", err) + return nil, err } body, err := io.ReadAll(res.Body) if err != nil { - return nil, fmt.Errorf("unable to read http response body: %w", err) + return nil, err } var result readme if err := json.Unmarshal(body, &result); err != nil { - return nil, fmt.Errorf("unable to parse json: %w", err) + return nil, err } - readmeRawURL := strings.ReplaceAll(result.ReadmeURL, "blob", "raw") + readmeRawURL := strings.Replace(result.ReadmeURL, "blob", "raw", -1) if res.StatusCode == http.StatusOK { - //nolint:bodyclose + // nolint:bodyclose // it is closed on the caller - resp, err := http.Get(readmeRawURL) //nolint: gosec,noctx + resp, err := http.Get(readmeRawURL) // nolint: gosec if err != nil { - return nil, fmt.Errorf("unable to get url: %w", err) + return nil, err } if resp.StatusCode == http.StatusOK { diff --git a/go.mod b/go.mod index 6e05b0d..6f20913 100644 --- a/go.mod +++ b/go.mod @@ -1,75 +1,75 @@ module github.com/charmbracelet/glow/v2 -go 1.25.12 - -toolchain go1.26.5 +go 1.23.6 require ( github.com/atotto/clipboard v0.1.4 github.com/caarlos0/env/v11 v11.3.1 - github.com/charmbracelet/bubbles v0.21.0 - github.com/charmbracelet/bubbletea v1.3.10 - github.com/charmbracelet/glamour v0.10.0 - github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 - github.com/charmbracelet/log v0.4.2 + github.com/charmbracelet/bubbles v0.20.0 + github.com/charmbracelet/bubbletea v1.3.3 + github.com/charmbracelet/glamour v0.8.0 + github.com/charmbracelet/lipgloss v1.0.0 + github.com/charmbracelet/log v0.4.0 github.com/charmbracelet/x/editor v0.1.0 github.com/dustin/go-humanize v1.0.1 - github.com/fsnotify/fsnotify v1.9.0 - github.com/mattn/go-runewidth v0.0.19 + github.com/fsnotify/fsnotify v1.8.0 + github.com/mattn/go-runewidth v0.0.16 github.com/mitchellh/go-homedir v1.1.0 github.com/muesli/gitcha v0.3.0 github.com/muesli/go-app-paths v0.2.2 - github.com/muesli/mango-cobra v1.3.0 + github.com/muesli/mango-cobra v1.2.0 github.com/muesli/reflow v0.3.0 github.com/muesli/roff v0.1.0 github.com/muesli/termenv v0.16.0 github.com/sahilm/fuzzy v0.1.1 - github.com/spf13/cobra v1.10.2 - github.com/spf13/viper v1.21.0 - golang.org/x/sys v0.43.0 - golang.org/x/term v0.42.0 - golang.org/x/text v0.39.0 - mvdan.cc/sh/v3 v3.13.1 + github.com/spf13/cobra v1.9.1 + github.com/spf13/viper v1.19.0 + golang.org/x/sys v0.30.0 + golang.org/x/term v0.29.0 + golang.org/x/text v0.22.0 ) require ( github.com/alecthomas/chroma/v2 v2.14.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect - github.com/charmbracelet/x/ansi v0.10.1 // indirect - github.com/charmbracelet/x/cellbuf v0.0.13 // indirect - github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/clipperhouse/uax29/v2 v2.2.0 // indirect github.com/dlclark/regexp2 v1.11.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/gorilla/css v1.0.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/mango v0.2.0 // indirect + github.com/muesli/mango v0.1.0 // indirect github.com/muesli/mango-pflag v0.1.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect - github.com/spf13/afero v1.15.0 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/pflag v1.0.10 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.6 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/yuin/goldmark v1.7.17 // indirect - github.com/yuin/goldmark-emoji v1.0.5 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect + github.com/yuin/goldmark v1.7.4 // indirect + github.com/yuin/goldmark-emoji v1.0.3 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.11.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0ccd7cd..b191e36 100644 --- a/go.sum +++ b/go.sum @@ -14,36 +14,29 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA= github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= -github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= -github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= -github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= -github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= -github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY= -github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk= -github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= -github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA= -github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig= -github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw= -github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= -github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= -github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= -github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= +github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= +github.com/charmbracelet/bubbletea v1.3.3 h1:WpU6fCY0J2vDWM3zfS3vIDi/ULq3SYphZhkAGGvmEUY= +github.com/charmbracelet/bubbletea v1.3.3/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo= +github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs= +github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw= +github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= +github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo= +github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM= +github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= github.com/charmbracelet/x/editor v0.1.0 h1:p69/dpvlwRTs9uYiPeAWruwsHqTFzHhTvQOd/WVSX98= github.com/charmbracelet/x/editor v0.1.0/go.mod h1:oivrEbcP/AYt/Hpvk5pwDXXrQ933gQS6UzL6fxqAGSA= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= -github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI= -github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU= +github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= +github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY= -github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -52,18 +45,16 @@ github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6 github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -79,17 +70,21 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= -github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -98,10 +93,10 @@ github.com/muesli/gitcha v0.3.0 h1:+PJkVKrDXVB0VgRn/yVx2CqSVSDGMSepzvohsCrPYtQ= github.com/muesli/gitcha v0.3.0/go.mod h1:vX3jFL+XcEUq1uY74RCjLSZfAV+ZuvLg70/NGPdXn84= github.com/muesli/go-app-paths v0.2.2 h1:NqG4EEZwNIhBq/pREgfBmgDmt3h1Smr1MjZiXbpZUnI= github.com/muesli/go-app-paths v0.2.2/go.mod h1:SxS3Umca63pcFcLtbjVb+J0oD7cl4ixQWoBKhGEtEho= -github.com/muesli/mango v0.2.0 h1:iNNc0c5VLQ6fsMgAqGQofByNUBH2Q2nEbD6TaI+5yyQ= -github.com/muesli/mango v0.2.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4= -github.com/muesli/mango-cobra v1.3.0 h1:vQy5GvPg3ndOSpduxutqFoINhWk3vD5K2dXo5E8pqec= -github.com/muesli/mango-cobra v1.3.0/go.mod h1:Cj1ZrBu3806Qw7UjxnAUgE+7tllUBj1NCLQDwwGx19E= +github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI= +github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4= +github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg= +github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg= github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= @@ -110,68 +105,79 @@ github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ= -github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= -github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= -github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= -github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= -github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= -github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark v1.7.17 h1:p36OVWwRb246iHxA/U4p8OPEpOTESm4n+g+8t0EE5uA= -github.com/yuin/goldmark v1.7.17/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk= -github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= +github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= +github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuhGX/+R1ZpfJ4/ia80JM= golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= -golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= -golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -mvdan.cc/sh/v3 v3.13.1 h1:DP3TfgZhDkT7lerUdnp6PTGKyxxzz6T+cOlY/xEvfWk= -mvdan.cc/sh/v3 v3.13.1/go.mod h1:lXJ8SexMvEVcHCoDvAGLZgFJ9Wsm2sulmoNEXGhYZD0= diff --git a/log.go b/log.go index a864a71..531feac 100644 --- a/log.go +++ b/log.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "io" "os" "path/filepath" @@ -13,7 +12,7 @@ import ( func getLogFilePath() (string, error) { dir, err := gap.NewScope(gap.User, "glow").CacheDir() if err != nil { - return "", fmt.Errorf("unable to get cache dir: %w", err) + return "", err } return filepath.Join(dir, "glow.log"), nil } @@ -25,14 +24,14 @@ func setupLog() (func() error, error) { if err != nil { return nil, err } - if err := os.MkdirAll(filepath.Dir(logFile), 0o755); err != nil { //nolint:gosec + if err := os.MkdirAll(filepath.Dir(logFile), 0o755); err != nil { // log disabled - return func() error { return nil }, nil //nolint:nilerr + return func() error { return nil }, nil } - f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644) //nolint:gosec + f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644) if err != nil { // log disabled - return func() error { return nil }, nil //nolint:nilerr + return func() error { return nil }, nil } log.SetOutput(f) log.SetLevel(log.DebugLevel) diff --git a/main.go b/main.go index b31ca15..02209fa 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,3 @@ -// Package main provides the entry point for the Glow CLI application. package main import ( @@ -13,8 +12,6 @@ import ( "path/filepath" "strings" - "mvdan.cc/sh/v3/shell" - "github.com/caarlos0/env/v11" "github.com/charmbracelet/glamour" "github.com/charmbracelet/glamour/styles" @@ -86,15 +83,15 @@ func sourceFromArg(arg string) (*source, error) { } // HTTP(S) URLs: - if u, err := url.ParseRequestURI(arg); err == nil && strings.Contains(arg, "://") { //nolint:nestif + if u, err := url.ParseRequestURI(arg); err == nil && strings.Contains(arg, "://") { if u.Scheme != "" { if u.Scheme != "http" && u.Scheme != "https" { return nil, fmt.Errorf("%s is not a supported protocol", u.Scheme) } // consumer of the source is responsible for closing the ReadCloser. - resp, err := http.Get(u.String()) //nolint: noctx,bodyclose + resp, err := http.Get(u.String()) // nolint:bodyclose if err != nil { - return nil, fmt.Errorf("unable to get url: %w", err) + return nil, err } if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("HTTP status %d", resp.StatusCode) @@ -109,7 +106,7 @@ func sourceFromArg(arg string) (*source, error) { arg = "." } st, err := os.Stat(arg) - if err == nil && st.IsDir() { //nolint:nestif + if err == nil && st.IsDir() { var src *source _ = filepath.Walk(arg, func(path string, _ os.FileInfo, err error) error { if err != nil { @@ -139,15 +136,10 @@ func sourceFromArg(arg string) (*source, error) { return nil, errors.New("missing markdown source") } + // a file: r, err := os.Open(arg) - if err != nil { - return nil, fmt.Errorf("unable to open file: %w", err) - } - u, err := filepath.Abs(arg) - if err != nil { - return nil, fmt.Errorf("unable to get absolute path: %w", err) - } - return &source{r, u}, nil + u, _ := filepath.Abs(arg) + return &source{r, u}, err } // validateStyle checks if the style is a default style, if not, checks that @@ -156,9 +148,9 @@ func validateStyle(style string) error { if style != "auto" && styles.DefaultStyles[style] == nil { style = utils.ExpandPath(style) if _, err := os.Stat(style); errors.Is(err, fs.ErrNotExist) { - return fmt.Errorf("specified style does not exist: %s", style) + return fmt.Errorf("Specified style does not exist: %s", style) } else if err != nil { - return fmt.Errorf("unable to stat file: %w", err) + return err } } return nil @@ -172,10 +164,9 @@ func validateOptions(cmd *cobra.Command) error { tui = viper.GetBool("tui") showAllFiles = viper.GetBool("all") preserveNewLines = viper.GetBool("preserveNewLines") - showLineNumbers = viper.GetBool("showLineNumbers") if pager && tui { - return errors.New("cannot use both pager and tui") + return errors.New("glow: cannot use both pager and tui") } // validate the glamour style @@ -192,11 +183,11 @@ func validateOptions(cmd *cobra.Command) error { } // Detect terminal width - if !cmd.Flags().Changed("width") { //nolint:nestif + if !cmd.Flags().Changed("width") { if isTerminal && width == 0 { w, _, err := term.GetSize(int(os.Stdout.Fd())) if err == nil { - width = uint(w) //nolint:gosec + width = uint(w) } if width > 120 { @@ -213,7 +204,7 @@ func validateOptions(cmd *cobra.Command) error { func stdinIsPipe() (bool, error) { stat, err := os.Stdin.Stat() if err != nil { - return false, fmt.Errorf("unable to open file: %w", err) + return false, err } if stat.Mode()&os.ModeCharDevice == 0 || stat.Size() > 0 { return true, nil @@ -275,7 +266,7 @@ func executeArg(cmd *cobra.Command, arg string, w io.Writer) error { func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error { b, err := io.ReadAll(src.reader) if err != nil { - return fmt.Errorf("unable to read from reader: %w", err) + return err } b = utils.RemoveFrontmatter(b) @@ -294,12 +285,12 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error { r, err := glamour.NewTermRenderer( glamour.WithColorProfile(lipgloss.ColorProfile()), utils.GlamourStyle(style, isCode), - glamour.WithWordWrap(int(width)), //nolint:gosec + glamour.WithWordWrap(int(width)), glamour.WithBaseURL(baseURL), glamour.WithPreservedNewLines(), ) if err != nil { - return fmt.Errorf("unable to create renderer: %w", err) + return err } content := string(b) @@ -310,7 +301,7 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error { out, err := r.Render(content) if err != nil { - return fmt.Errorf("unable to render markdown: %w", err) + return err } // display @@ -321,28 +312,16 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error { pagerCmd = "less -r" } - fields, err := shell.Fields(pagerCmd, os.Getenv) - if err != nil || len(fields) == 0 { - return fmt.Errorf("unable to parse PAGER command: %s", pagerCmd) - } - c := exec.Command(fields[0], fields[1:]...) //nolint:gosec + pa := strings.Split(pagerCmd, " ") + c := exec.Command(pa[0], pa[1:]...) // nolint:gosec c.Stdin = strings.NewReader(out) c.Stdout = os.Stdout - if err := c.Run(); err != nil { - return fmt.Errorf("unable to run command: %w", err) - } - return nil + return c.Run() case tui || cmd.Flags().Changed("tui"): - path := "" - if !isURL(src.URL) { - path = src.URL - } - return runTUI(path, content) + return runTUI(src.URL, content) default: - if _, err = fmt.Fprint(w, out); err != nil { - return fmt.Errorf("unable to write to writer: %w", err) - } - return nil + _, err = fmt.Fprint(w, out) + return err } } @@ -367,7 +346,7 @@ func runTUI(path string, content string) error { // Run Bubble Tea program if _, err := ui.NewProgram(cfg, content).Run(); err != nil { - return fmt.Errorf("unable to run tui program: %w", err) + return err } return nil diff --git a/man_cmd.go b/man_cmd.go index a179ef7..9aa5951 100644 --- a/man_cmd.go +++ b/man_cmd.go @@ -19,11 +19,9 @@ var manCmd = &cobra.Command{ RunE: func(*cobra.Command, []string) error { manPage, err := mcobra.NewManPage(1, rootCmd) if err != nil { - return fmt.Errorf("unable to instantiate man page: %w", err) + return err } - if _, err := fmt.Fprint(os.Stdout, manPage.Build(roff.NewDocument())); err != nil { - return fmt.Errorf("unable to build man page: %w", err) - } - return nil + _, err = fmt.Fprint(os.Stdout, manPage.Build(roff.NewDocument())) + return err }, } diff --git a/ui/editor.go b/ui/editor.go index a567c59..5eb2a06 100644 --- a/ui/editor.go +++ b/ui/editor.go @@ -11,7 +11,7 @@ func openEditor(path string, lineno int) tea.Cmd { cb := func(err error) tea.Msg { return editorFinishedMsg{err} } - cmd, err := editor.Cmd("Glow", path, editor.LineNumber(uint(lineno))) //nolint:gosec + cmd, err := editor.Cmd("Glow", path, editor.OpenAtLine(uint(lineno))) if err != nil { return func() tea.Msg { return cb(err) } } diff --git a/ui/markdown.go b/ui/markdown.go index c67b1dc..8bafad1 100644 --- a/ui/markdown.go +++ b/ui/markdown.go @@ -1,7 +1,6 @@ package ui import ( - "fmt" "math" "time" "unicode" @@ -49,10 +48,7 @@ func (m markdown) relativeTime() string { func normalize(in string) (string, error) { t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) out, _, err := transform.String(t, in) - if err != nil { - return "", fmt.Errorf("error normalizing: %w", err) - } - return out, nil + return out, err } // Return the time in a human-readable format relative to the current time. diff --git a/ui/pager.go b/ui/pager.go index 5c522e7..6d4209b 100644 --- a/ui/pager.go +++ b/ui/pager.go @@ -3,6 +3,7 @@ package ui import ( "fmt" "math" + "os" "path/filepath" "strings" "time" @@ -150,7 +151,7 @@ type pagerStatusMessage struct { } // Perform stuff that needs to happen after a successful markdown stash. Note -// that the returned command should be sent back the through the pager +// that the the returned command should be sent back the through the pager // update function. func (m *pagerModel) showStatusMessage(msg pagerStatusMessage) tea.Cmd { // Show a success message to the user @@ -203,18 +204,6 @@ func (m pagerModel) update(msg tea.Msg) (pagerModel, tea.Cmd) { cmds = append(cmds, viewport.Sync(m.viewport)) } - case "d": - m.viewport.HalfViewDown() - if m.viewport.HighPerformanceRendering { - cmds = append(cmds, viewport.Sync(m.viewport)) - } - - case "u": - m.viewport.HalfViewUp() - if m.viewport.HighPerformanceRendering { - cmds = append(cmds, viewport.Sync(m.viewport)) - } - case "e": lineno := int(math.RoundToEven(float64(m.viewport.TotalLineCount()) * m.viewport.ScrollPercent())) if m.viewport.AtTop() { @@ -329,7 +318,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) { } else { note = m.currentDocument.Note } - note = truncate.StringWithTail(" "+note+" ", uint(max(0, //nolint:gosec + note = truncate.StringWithTail(" "+note+" ", uint(max(0, m.common.width- ansi.PrintableRuneWidth(logo)- ansi.PrintableRuneWidth(scrollPercent)- @@ -427,7 +416,7 @@ func glamourRender(m pagerModel, markdown string) (string, error) { } isCode := !utils.IsMarkdownFile(m.currentDocument.Note) - width := max(0, min(int(m.common.cfg.GlamourMaxWidth), m.viewport.Width)) //nolint:gosec + width := max(0, min(int(m.common.cfg.GlamourMaxWidth), m.viewport.Width)) if isCode { width = 0 } @@ -442,7 +431,7 @@ func glamourRender(m pagerModel, markdown string) (string, error) { } r, err := glamour.NewTermRenderer(options...) if err != nil { - return "", fmt.Errorf("error creating glamour renderer: %w", err) + return "", err } if isCode { @@ -451,7 +440,7 @@ func glamourRender(m pagerModel, markdown string) (string, error) { out, err := r.Render(markdown) if err != nil { - return "", fmt.Errorf("error rendering markdown: %w", err) + return "", err } if isCode { @@ -488,48 +477,44 @@ func (m *pagerModel) initWatcher() { } func (m *pagerModel) watchFile() tea.Msg { - dir := m.localDir() + path := m.relFilePath() - if err := m.watcher.Add(dir); err != nil { - log.Error("error adding dir to fsnotify watcher", "error", err) + if err := m.watcher.Add(path); err != nil { + log.Error("error adding file to fsnotify watcher", "error", err) return nil } - log.Info("fsnotify watching dir", "dir", dir) + log.Info("fsnotify watching file", "file", path) for { select { case event, ok := <-m.watcher.Events: - if !ok || event.Name != m.currentDocument.localPath { + if !ok || !event.Has(fsnotify.Write) { continue } - - if !event.Has(fsnotify.Write) && !event.Has(fsnotify.Create) { - continue - } - - log.Debug("fsnotify event", "file", event.Name, "event", event.Op) + log.Debug("fsnotify event", "file", path, "event", event.Op) return reloadMsg{} case err, ok := <-m.watcher.Errors: if !ok { continue } - log.Debug("fsnotify error", "dir", dir, "error", err) + log.Debug("fsnotify error", "file", path, "error", err) } } } func (m *pagerModel) unwatchFile() { - dir := m.localDir() + path := m.relFilePath() - err := m.watcher.Remove(dir) + err := m.watcher.Remove(path) if err == nil { - log.Debug("fsnotify dir unwatched", "dir", dir) + log.Debug("fsnotify file unwatched", "file", path) } else { - log.Error("fsnotify fail to unwatch dir", "dir", dir, "error", err) + log.Error("fsnotify fail to unwatch file", "file", path, "error", err) } } -func (m *pagerModel) localDir() string { - return filepath.Dir(m.currentDocument.localPath) +func (m *pagerModel) relFilePath() string { + wd, _ := os.Getwd() + return stripAbsolutePath(m.currentDocument.localPath, wd) } diff --git a/ui/stash.go b/ui/stash.go index c3739b2..2021966 100644 --- a/ui/stash.go +++ b/ui/stash.go @@ -126,7 +126,7 @@ func initSections() { // String returns a styled version of the status message appropriate for the // given context. func (s statusMessage) String() string { - switch s.status { //nolint:exhaustive + switch s.status { case subtleStatusMessage: return dimGreenFg(s.message) case errorStatusMessage: @@ -444,7 +444,7 @@ func (m stashModel) update(msg tea.Msg) (stashModel, tea.Cmd) { } // Updates per the current state - switch m.viewState { //nolint:exhaustive + switch m.viewState { case stashStateReady: cmds = append(cmds, m.handleDocumentBrowsing(msg)) case stashStateShowingError: @@ -518,12 +518,6 @@ func (m *stashModel) handleDocumentBrowsing(msg tea.Msg) tea.Cmd { // Edit document in EDITOR case "e": md := m.selectedMarkdown() - - // In case no file is available - if md == nil { - return nil - } - return openEditor(md.localPath, 0) // Open document @@ -602,7 +596,7 @@ func (m *stashModel) handleFiltering(msg tea.Msg) tea.Cmd { var cmds []tea.Cmd // Handle keys - if msg, ok := msg.(tea.KeyMsg); ok { //nolint:nestif + if msg, ok := msg.(tea.KeyMsg); ok { switch msg.String() { case keyEsc: // Cancel filtering @@ -696,7 +690,7 @@ func (m stashModel) view() string { logoOrFilter += " " + m.statusMessage.String() } } - logoOrFilter = truncate.StringWithTail(logoOrFilter, uint(m.common.width-1), ellipsis) //nolint:gosec + logoOrFilter = truncate.StringWithTail(logoOrFilter, uint(m.common.width-1), ellipsis) help, helpHeight := m.helpView() diff --git a/ui/stashhelp.go b/ui/stashhelp.go index 6c0b474..01a0458 100644 --- a/ui/stashhelp.go +++ b/ui/stashhelp.go @@ -137,11 +137,7 @@ func (m stashModel) helpView() (string, int) { } appHelp = append(appHelp, "r", "refresh") - - if numDocs > 0 { - appHelp = append(appHelp, "e", "edit") - } - + appHelp = append(appHelp, "e", "edit") appHelp = append(appHelp, "q", "quit") // Detailed help diff --git a/ui/stashitem.go b/ui/stashitem.go index 0000928..26e8bb6 100644 --- a/ui/stashitem.go +++ b/ui/stashitem.go @@ -17,7 +17,7 @@ const ( func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) { var ( - truncateTo = uint(m.common.width - stashViewHorizontalPadding*2) //nolint:gosec + truncateTo = uint(m.common.width - stashViewHorizontalPadding*2) gutter string title = truncate.StringWithTail(md.Note, truncateTo, ellipsis) date = md.relativeTime() @@ -34,7 +34,7 @@ func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) { // If there are multiple items being filtered don't highlight a selected // item in the results. If we've filtered down to one item, however, // highlight that first item since pressing return will open it. - if isSelected && !isFiltering || singleFilteredItem { //nolint:nestif + if isSelected && !isFiltering || singleFilteredItem { // Selected item if m.statusMessage == stashingStatusMessage { gutter = greenFg(verticalLine) diff --git a/ui/ui.go b/ui/ui.go index 3537d3f..eeda361 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -1,4 +1,3 @@ -// Package ui provides the main UI for the glow application. package ui import ( @@ -121,7 +120,7 @@ func (m *model) unloadDocument() []tea.Cmd { var batch []tea.Cmd if m.pager.viewport.HighPerformanceRendering { - batch = append(batch, tea.ClearScrollArea) //nolint:staticcheck + batch = append(batch, tea.ClearScrollArea) } if !m.stash.shouldSpin() { @@ -235,7 +234,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "q": var cmd tea.Cmd - switch m.state { //nolint:exhaustive + switch m.state { case stateShowStash: // pass through all keys if we're editing the filter if m.stash.filterState == filtering { @@ -329,7 +328,7 @@ func (m model) View() string { return errorView(m.fatalErr, true) } - switch m.state { //nolint:exhaustive + switch m.state { case stateShowDocument: return m.pager.View() default: @@ -450,3 +449,17 @@ func indent(s string, n int) string { } return b.String() } + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/url.go b/url.go index f716681..43ca167 100644 --- a/url.go +++ b/url.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "net/url" "strings" "sync" @@ -45,7 +44,7 @@ func readmeURL(path string) (*source, error) { } u, err := url.Parse(path) if err != nil { - return nil, fmt.Errorf("unable to parse url: %w", err) + return nil, err } switch { @@ -79,8 +78,3 @@ func gitlabReadmeURL(path string) *url.URL { u, _ := url.Parse(gitlabURL.String()) return u.JoinPath(path) } - -func isURL(path string) bool { - _, err := url.ParseRequestURI(path) - return err == nil && strings.Contains(path, "://") -} diff --git a/utils/utils.go b/utils/utils.go index 9f33a1e..8240c36 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,4 +1,3 @@ -// Package utils provides utility functions. package utils import ( @@ -31,7 +30,7 @@ func detectFrontmatter(c []byte) []int { return []int{-1, -1} } -// ExpandPath expands tilde and all environment variables from the given path. +// Expands tilde and all environment variables from the given path. func ExpandPath(path string) string { s, err := homedir.Expand(path) if err == nil { @@ -69,13 +68,13 @@ func IsMarkdownFile(filename string) bool { return false } -// GlamourStyle returns a glamour.TermRendererOption based on the given style. func GlamourStyle(style string, isCode bool) glamour.TermRendererOption { if !isCode { if style == styles.AutoStyle { return glamour.WithAutoStyle() + } else { + return glamour.WithStylePath(style) } - return glamour.WithStylePath(style) } // If we are rendering a pure code block, we need to modify the style to