mirror of
https://github.com/charmbracelet/glow.git
synced 2026-08-09 09:49:09 +02:00
Compare commits
73 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5cb757278 |
||
|
|
53788271b3 | ||
|
|
f57087499b |
||
|
|
1130f2d89f |
||
|
|
fac0fb456d |
||
|
|
752de97c5a |
||
|
|
7903cdbc5f |
||
|
|
a861530349 |
||
|
|
ba37804fd5 |
||
|
|
dbf59aafa9 |
||
|
|
07d4e1de3f |
||
|
|
e9840f0735 |
||
|
|
283d20b83c |
||
|
|
36bf1711bf |
||
|
|
f9ec6882c1 |
||
|
|
1afeed4c56 |
||
|
|
677fcb3eee | ||
|
|
a440b3319b |
||
|
|
1c32d1377c |
||
|
|
963219b96e |
||
|
|
901b99931e |
||
|
|
9432fd920c |
||
|
|
deaa57fe00 |
||
|
|
e61f329428 |
||
|
|
bf0a9b4d3d |
||
|
|
e010ed866e |
||
|
|
0e76788a6a |
||
|
|
66b389ef17 |
||
|
|
18a739c091 |
||
|
|
9240ab4625 |
||
|
|
a6ed0f2430 |
||
|
|
3079ce20b9 |
||
|
|
bcd1296ce5 |
||
|
|
e54618ef13 |
||
|
|
d37e988787 |
||
|
|
e83c6edf93 |
||
|
|
e23f237fb7 | ||
|
|
ee27edd3b1 | ||
|
|
5b2dfddcda |
||
|
|
0880dea1be |
||
|
|
ef85822a00 |
||
|
|
cdeceb9a7f |
||
|
|
366e9a0d65 |
||
|
|
76e08e7dce |
||
|
|
e60e83c6aa |
||
|
|
bb9fcb439b |
||
|
|
6303d0b784 |
||
|
|
d6b9ddf345 |
||
|
|
470fa3d718 |
||
|
|
2c0e4d878a |
||
|
|
d2e04adbfe |
||
|
|
c84a03bbfd |
||
|
|
e8049d79f2 |
||
|
|
41d70ee83b | ||
|
|
0a6732f089 | ||
|
|
230dbc79b2 | ||
|
|
81c64fdd2d | ||
|
|
c48ee3d98c | ||
|
|
23f9873f6a | ||
|
|
05872a506a |
||
|
|
50a763ef94 |
||
|
|
4d59a973a7 |
||
|
|
d54666ddf7 |
||
|
|
0b668e1593 |
||
|
|
6558aaab69 |
||
|
|
85668a6a21 |
||
|
|
411cdb142f |
||
|
|
6cd480d68d |
||
|
|
652010599b |
||
|
|
eeb0fdd06f |
||
|
|
f88a901caa |
||
|
|
7dc4b9c87f |
||
|
|
2da054e802 |
28 changed files with 404 additions and 265 deletions
18
.editorconfig
Normal file
18
.editorconfig
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# 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
|
||||
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
|
@ -1 +0,0 @@
|
|||
* @charmbracelet/everyone
|
||||
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
|
|
@ -13,6 +13,14 @@ 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: "/"
|
||||
|
|
@ -26,6 +34,10 @@ updates:
|
|||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
groups:
|
||||
all:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
|
|
@ -37,5 +49,9 @@ updates:
|
|||
labels:
|
||||
- "dependencies"
|
||||
commit-message:
|
||||
prefix: "feat"
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
groups:
|
||||
all:
|
||||
patterns:
|
||||
- "*"
|
||||
|
|
|
|||
4
.github/workflows/coverage.yml
vendored
4
.github/workflows/coverage.yml
vendored
|
|
@ -8,10 +8,10 @@ jobs:
|
|||
GO111MODULE: "on"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
|
|
|
|||
13
.github/workflows/lint-sync.yml
vendored
Normal file
13
.github/workflows/lint-sync.yml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
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
|
||||
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
|
|
@ -8,9 +8,9 @@ jobs:
|
|||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6.5.0
|
||||
uses: golangci/golangci-lint-action@v9.2.0
|
||||
with:
|
||||
# Optional: golangci-lint command line arguments.
|
||||
args: --issues-exit-code=0
|
||||
|
|
|
|||
|
|
@ -1,33 +1,44 @@
|
|||
version: "2"
|
||||
run:
|
||||
tests: false
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0001
|
||||
- EXC0005
|
||||
- EXC0011
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- dupl
|
||||
- exhaustive
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gomoddirectives
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ includes:
|
|||
|
||||
variables:
|
||||
description: "Render markdown on the CLI, with pizzazz!"
|
||||
github_url: "https://github.com/charmbracelet/soft-serve"
|
||||
github_url: "https://github.com/charmbracelet/glow"
|
||||
maintainer: "Christian Muehlhaeuser <muesli@charm.sh>"
|
||||
brew_commit_author_name: "Christian Muehlhaeuser"
|
||||
brew_commit_author_email: "muesli@charm.sh"
|
||||
|
|
|
|||
17
Makefile
17
Makefile
|
|
@ -1,17 +0,0 @@
|
|||
# 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
|
||||
37
README.md
37
README.md
|
|
@ -30,39 +30,64 @@ 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
|
||||
|
|
@ -82,7 +107,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@latest
|
||||
go install github.com/charmbracelet/glow/v2@latest
|
||||
```
|
||||
|
||||
### Build (requires Go 1.21+)
|
||||
|
|
@ -184,8 +209,18 @@ 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!
|
||||
|
|
|
|||
23
Taskfile.yaml
Normal file
23
Taskfile.yaml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# 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]
|
||||
|
|
@ -39,13 +39,13 @@ var configCmd = &cobra.Command{
|
|||
|
||||
c, err := editor.Cmd("Glow", configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to set config file: %w", err)
|
||||
}
|
||||
c.Stdin = os.Stdin
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
if err := c.Run(); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to run command: %w", 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 {
|
||||
if err := os.MkdirAll(filepath.Dir(configFile), 0o755); err != nil { //nolint:gosec
|
||||
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 err
|
||||
return fmt.Errorf("unable create directory: %w", err)
|
||||
}
|
||||
|
||||
f, err := os.Create(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to create config file: %w", err)
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
if _, err := f.WriteString(defaultConfig); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to write config file: %w", err)
|
||||
}
|
||||
} else if err != nil { // some other error occurred
|
||||
return err
|
||||
return fmt.Errorf("unable to stat config file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
16
github.go
16
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
|
||||
res, err := http.Get(apiURL) //nolint: gosec,noctx
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to get url: %w", err)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to read http response body: %w", err)
|
||||
}
|
||||
|
||||
var result readme
|
||||
if err := json.Unmarshal(body, &result); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to parse json: %w", err)
|
||||
}
|
||||
|
||||
if res.StatusCode == http.StatusOK {
|
||||
// nolint:bodyclose
|
||||
//nolint:bodyclose
|
||||
// it is closed on the caller
|
||||
resp, err := http.Get(result.DownloadURL)
|
||||
resp, err := http.Get(result.DownloadURL) //nolint: noctx
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to get url: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
|
|
|
|||
18
gitlab.go
18
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
|
||||
res, err := http.Get(apiURL) //nolint: gosec,noctx
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to get url: %w", err)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to read http response body: %w", err)
|
||||
}
|
||||
|
||||
var result readme
|
||||
if err := json.Unmarshal(body, &result); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to parse json: %w", err)
|
||||
}
|
||||
|
||||
readmeRawURL := strings.Replace(result.ReadmeURL, "blob", "raw", -1)
|
||||
readmeRawURL := strings.ReplaceAll(result.ReadmeURL, "blob", "raw")
|
||||
|
||||
if res.StatusCode == http.StatusOK {
|
||||
// nolint:bodyclose
|
||||
//nolint:bodyclose
|
||||
// it is closed on the caller
|
||||
resp, err := http.Get(readmeRawURL) // nolint: gosec
|
||||
resp, err := http.Get(readmeRawURL) //nolint: gosec,noctx
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to get url: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
|
|
|
|||
70
go.mod
70
go.mod
|
|
@ -1,75 +1,75 @@
|
|||
module github.com/charmbracelet/glow/v2
|
||||
|
||||
go 1.23.6
|
||||
go 1.25.12
|
||||
|
||||
toolchain go1.26.5
|
||||
|
||||
require (
|
||||
github.com/atotto/clipboard v0.1.4
|
||||
github.com/caarlos0/env/v11 v11.3.1
|
||||
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/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/x/editor v0.1.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/fsnotify/fsnotify v1.8.0
|
||||
github.com/mattn/go-runewidth v0.0.16
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/mattn/go-runewidth v0.0.19
|
||||
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.2.0
|
||||
github.com/muesli/mango-cobra v1.3.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.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
|
||||
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
|
||||
)
|
||||
|
||||
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/x/ansi v0.8.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/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.1.0 // indirect
|
||||
github.com/muesli/mango v0.2.0 // indirect
|
||||
github.com/muesli/mango-pflag v0.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // 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.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/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/subosito/gotenv v1.6.0 // 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
|
||||
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
|
||||
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/net v0.53.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
|
||||
)
|
||||
|
|
|
|||
160
go.sum
160
go.sum
|
|
@ -14,29 +14,36 @@ 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.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/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/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-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/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/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=
|
||||
|
|
@ -45,16 +52,18 @@ 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.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
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/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
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/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/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=
|
||||
|
|
@ -70,21 +79,17 @@ 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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
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/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=
|
||||
|
|
@ -93,10 +98,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.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 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-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=
|
||||
|
|
@ -105,79 +110,68 @@ 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.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
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/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.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
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/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.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/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
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.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/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/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.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/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
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.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=
|
||||
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=
|
||||
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.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/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
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.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=
|
||||
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=
|
||||
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=
|
||||
|
|
|
|||
11
log.go
11
log.go
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -12,7 +13,7 @@ import (
|
|||
func getLogFilePath() (string, error) {
|
||||
dir, err := gap.NewScope(gap.User, "glow").CacheDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("unable to get cache dir: %w", err)
|
||||
}
|
||||
return filepath.Join(dir, "glow.log"), nil
|
||||
}
|
||||
|
|
@ -24,14 +25,14 @@ func setupLog() (func() error, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(logFile), 0o755); err != nil {
|
||||
if err := os.MkdirAll(filepath.Dir(logFile), 0o755); err != nil { //nolint:gosec
|
||||
// log disabled
|
||||
return func() error { return nil }, nil
|
||||
return func() error { return nil }, nil //nolint:nilerr
|
||||
}
|
||||
f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
|
||||
f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644) //nolint:gosec
|
||||
if err != nil {
|
||||
// log disabled
|
||||
return func() error { return nil }, nil
|
||||
return func() error { return nil }, nil //nolint:nilerr
|
||||
}
|
||||
log.SetOutput(f)
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
|
|
|||
69
main.go
69
main.go
|
|
@ -1,3 +1,4 @@
|
|||
// Package main provides the entry point for the Glow CLI application.
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
@ -12,6 +13,8 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"mvdan.cc/sh/v3/shell"
|
||||
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/charmbracelet/glamour"
|
||||
"github.com/charmbracelet/glamour/styles"
|
||||
|
|
@ -83,15 +86,15 @@ func sourceFromArg(arg string) (*source, error) {
|
|||
}
|
||||
|
||||
// HTTP(S) URLs:
|
||||
if u, err := url.ParseRequestURI(arg); err == nil && strings.Contains(arg, "://") {
|
||||
if u, err := url.ParseRequestURI(arg); err == nil && strings.Contains(arg, "://") { //nolint:nestif
|
||||
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:bodyclose
|
||||
resp, err := http.Get(u.String()) //nolint: noctx,bodyclose
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to get url: %w", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("HTTP status %d", resp.StatusCode)
|
||||
|
|
@ -106,7 +109,7 @@ func sourceFromArg(arg string) (*source, error) {
|
|||
arg = "."
|
||||
}
|
||||
st, err := os.Stat(arg)
|
||||
if err == nil && st.IsDir() {
|
||||
if err == nil && st.IsDir() { //nolint:nestif
|
||||
var src *source
|
||||
_ = filepath.Walk(arg, func(path string, _ os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
|
@ -136,10 +139,15 @@ func sourceFromArg(arg string) (*source, error) {
|
|||
return nil, errors.New("missing markdown source")
|
||||
}
|
||||
|
||||
// a file:
|
||||
r, err := os.Open(arg)
|
||||
u, _ := filepath.Abs(arg)
|
||||
return &source{r, u}, err
|
||||
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
|
||||
}
|
||||
|
||||
// validateStyle checks if the style is a default style, if not, checks that
|
||||
|
|
@ -148,9 +156,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 err
|
||||
return fmt.Errorf("unable to stat file: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -164,9 +172,10 @@ 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("glow: cannot use both pager and tui")
|
||||
return errors.New("cannot use both pager and tui")
|
||||
}
|
||||
|
||||
// validate the glamour style
|
||||
|
|
@ -183,11 +192,11 @@ func validateOptions(cmd *cobra.Command) error {
|
|||
}
|
||||
|
||||
// Detect terminal width
|
||||
if !cmd.Flags().Changed("width") {
|
||||
if !cmd.Flags().Changed("width") { //nolint:nestif
|
||||
if isTerminal && width == 0 {
|
||||
w, _, err := term.GetSize(int(os.Stdout.Fd()))
|
||||
if err == nil {
|
||||
width = uint(w)
|
||||
width = uint(w) //nolint:gosec
|
||||
}
|
||||
|
||||
if width > 120 {
|
||||
|
|
@ -204,7 +213,7 @@ func validateOptions(cmd *cobra.Command) error {
|
|||
func stdinIsPipe() (bool, error) {
|
||||
stat, err := os.Stdin.Stat()
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, fmt.Errorf("unable to open file: %w", err)
|
||||
}
|
||||
if stat.Mode()&os.ModeCharDevice == 0 || stat.Size() > 0 {
|
||||
return true, nil
|
||||
|
|
@ -266,7 +275,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 err
|
||||
return fmt.Errorf("unable to read from reader: %w", err)
|
||||
}
|
||||
|
||||
b = utils.RemoveFrontmatter(b)
|
||||
|
|
@ -285,12 +294,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)),
|
||||
glamour.WithWordWrap(int(width)), //nolint:gosec
|
||||
glamour.WithBaseURL(baseURL),
|
||||
glamour.WithPreservedNewLines(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to create renderer: %w", err)
|
||||
}
|
||||
|
||||
content := string(b)
|
||||
|
|
@ -301,7 +310,7 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
|
|||
|
||||
out, err := r.Render(content)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to render markdown: %w", err)
|
||||
}
|
||||
|
||||
// display
|
||||
|
|
@ -312,16 +321,28 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
|
|||
pagerCmd = "less -r"
|
||||
}
|
||||
|
||||
pa := strings.Split(pagerCmd, " ")
|
||||
c := exec.Command(pa[0], pa[1:]...) // nolint:gosec
|
||||
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
|
||||
c.Stdin = strings.NewReader(out)
|
||||
c.Stdout = os.Stdout
|
||||
return c.Run()
|
||||
if err := c.Run(); err != nil {
|
||||
return fmt.Errorf("unable to run command: %w", err)
|
||||
}
|
||||
return nil
|
||||
case tui || cmd.Flags().Changed("tui"):
|
||||
return runTUI(src.URL, content)
|
||||
path := ""
|
||||
if !isURL(src.URL) {
|
||||
path = src.URL
|
||||
}
|
||||
return runTUI(path, content)
|
||||
default:
|
||||
_, err = fmt.Fprint(w, out)
|
||||
return err
|
||||
if _, err = fmt.Fprint(w, out); err != nil {
|
||||
return fmt.Errorf("unable to write to writer: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +367,7 @@ func runTUI(path string, content string) error {
|
|||
|
||||
// Run Bubble Tea program
|
||||
if _, err := ui.NewProgram(cfg, content).Run(); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to run tui program: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ var manCmd = &cobra.Command{
|
|||
RunE: func(*cobra.Command, []string) error {
|
||||
manPage, err := mcobra.NewManPage(1, rootCmd)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to instantiate man page: %w", err)
|
||||
}
|
||||
_, err = fmt.Fprint(os.Stdout, manPage.Build(roff.NewDocument()))
|
||||
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
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.OpenAtLine(uint(lineno)))
|
||||
cmd, err := editor.Cmd("Glow", path, editor.LineNumber(uint(lineno))) //nolint:gosec
|
||||
if err != nil {
|
||||
return func() tea.Msg { return cb(err) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
"unicode"
|
||||
|
|
@ -48,7 +49,10 @@ 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)
|
||||
return out, err
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error normalizing: %w", err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Return the time in a human-readable format relative to the current time.
|
||||
|
|
|
|||
55
ui/pager.go
55
ui/pager.go
|
|
@ -3,7 +3,6 @@ package ui
|
|||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -151,7 +150,7 @@ type pagerStatusMessage struct {
|
|||
}
|
||||
|
||||
// Perform stuff that needs to happen after a successful markdown stash. Note
|
||||
// that the the returned command should be sent back the through the pager
|
||||
// that 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
|
||||
|
|
@ -204,6 +203,18 @@ 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() {
|
||||
|
|
@ -318,7 +329,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) {
|
|||
} else {
|
||||
note = m.currentDocument.Note
|
||||
}
|
||||
note = truncate.StringWithTail(" "+note+" ", uint(max(0,
|
||||
note = truncate.StringWithTail(" "+note+" ", uint(max(0, //nolint:gosec
|
||||
m.common.width-
|
||||
ansi.PrintableRuneWidth(logo)-
|
||||
ansi.PrintableRuneWidth(scrollPercent)-
|
||||
|
|
@ -416,7 +427,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))
|
||||
width := max(0, min(int(m.common.cfg.GlamourMaxWidth), m.viewport.Width)) //nolint:gosec
|
||||
if isCode {
|
||||
width = 0
|
||||
}
|
||||
|
|
@ -431,7 +442,7 @@ func glamourRender(m pagerModel, markdown string) (string, error) {
|
|||
}
|
||||
r, err := glamour.NewTermRenderer(options...)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("error creating glamour renderer: %w", err)
|
||||
}
|
||||
|
||||
if isCode {
|
||||
|
|
@ -440,7 +451,7 @@ func glamourRender(m pagerModel, markdown string) (string, error) {
|
|||
|
||||
out, err := r.Render(markdown)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("error rendering markdown: %w", err)
|
||||
}
|
||||
|
||||
if isCode {
|
||||
|
|
@ -477,44 +488,48 @@ func (m *pagerModel) initWatcher() {
|
|||
}
|
||||
|
||||
func (m *pagerModel) watchFile() tea.Msg {
|
||||
path := m.relFilePath()
|
||||
dir := m.localDir()
|
||||
|
||||
if err := m.watcher.Add(path); err != nil {
|
||||
log.Error("error adding file to fsnotify watcher", "error", err)
|
||||
if err := m.watcher.Add(dir); err != nil {
|
||||
log.Error("error adding dir to fsnotify watcher", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Info("fsnotify watching file", "file", path)
|
||||
log.Info("fsnotify watching dir", "dir", dir)
|
||||
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-m.watcher.Events:
|
||||
if !ok || !event.Has(fsnotify.Write) {
|
||||
if !ok || event.Name != m.currentDocument.localPath {
|
||||
continue
|
||||
}
|
||||
log.Debug("fsnotify event", "file", path, "event", event.Op)
|
||||
|
||||
if !event.Has(fsnotify.Write) && !event.Has(fsnotify.Create) {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debug("fsnotify event", "file", event.Name, "event", event.Op)
|
||||
return reloadMsg{}
|
||||
case err, ok := <-m.watcher.Errors:
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
log.Debug("fsnotify error", "file", path, "error", err)
|
||||
log.Debug("fsnotify error", "dir", dir, "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *pagerModel) unwatchFile() {
|
||||
path := m.relFilePath()
|
||||
dir := m.localDir()
|
||||
|
||||
err := m.watcher.Remove(path)
|
||||
err := m.watcher.Remove(dir)
|
||||
if err == nil {
|
||||
log.Debug("fsnotify file unwatched", "file", path)
|
||||
log.Debug("fsnotify dir unwatched", "dir", dir)
|
||||
} else {
|
||||
log.Error("fsnotify fail to unwatch file", "file", path, "error", err)
|
||||
log.Error("fsnotify fail to unwatch dir", "dir", dir, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *pagerModel) relFilePath() string {
|
||||
wd, _ := os.Getwd()
|
||||
return stripAbsolutePath(m.currentDocument.localPath, wd)
|
||||
func (m *pagerModel) localDir() string {
|
||||
return filepath.Dir(m.currentDocument.localPath)
|
||||
}
|
||||
|
|
|
|||
14
ui/stash.go
14
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 {
|
||||
switch s.status { //nolint:exhaustive
|
||||
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 {
|
||||
switch m.viewState { //nolint:exhaustive
|
||||
case stashStateReady:
|
||||
cmds = append(cmds, m.handleDocumentBrowsing(msg))
|
||||
case stashStateShowingError:
|
||||
|
|
@ -518,6 +518,12 @@ 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
|
||||
|
|
@ -596,7 +602,7 @@ func (m *stashModel) handleFiltering(msg tea.Msg) tea.Cmd {
|
|||
var cmds []tea.Cmd
|
||||
|
||||
// Handle keys
|
||||
if msg, ok := msg.(tea.KeyMsg); ok {
|
||||
if msg, ok := msg.(tea.KeyMsg); ok { //nolint:nestif
|
||||
switch msg.String() {
|
||||
case keyEsc:
|
||||
// Cancel filtering
|
||||
|
|
@ -690,7 +696,7 @@ func (m stashModel) view() string {
|
|||
logoOrFilter += " " + m.statusMessage.String()
|
||||
}
|
||||
}
|
||||
logoOrFilter = truncate.StringWithTail(logoOrFilter, uint(m.common.width-1), ellipsis)
|
||||
logoOrFilter = truncate.StringWithTail(logoOrFilter, uint(m.common.width-1), ellipsis) //nolint:gosec
|
||||
|
||||
help, helpHeight := m.helpView()
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,11 @@ func (m stashModel) helpView() (string, int) {
|
|||
}
|
||||
|
||||
appHelp = append(appHelp, "r", "refresh")
|
||||
appHelp = append(appHelp, "e", "edit")
|
||||
|
||||
if numDocs > 0 {
|
||||
appHelp = append(appHelp, "e", "edit")
|
||||
}
|
||||
|
||||
appHelp = append(appHelp, "q", "quit")
|
||||
|
||||
// Detailed help
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const (
|
|||
|
||||
func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
|
||||
var (
|
||||
truncateTo = uint(m.common.width - stashViewHorizontalPadding*2)
|
||||
truncateTo = uint(m.common.width - stashViewHorizontalPadding*2) //nolint:gosec
|
||||
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 {
|
||||
if isSelected && !isFiltering || singleFilteredItem { //nolint:nestif
|
||||
// Selected item
|
||||
if m.statusMessage == stashingStatusMessage {
|
||||
gutter = greenFg(verticalLine)
|
||||
|
|
|
|||
21
ui/ui.go
21
ui/ui.go
|
|
@ -1,3 +1,4 @@
|
|||
// Package ui provides the main UI for the glow application.
|
||||
package ui
|
||||
|
||||
import (
|
||||
|
|
@ -120,7 +121,7 @@ func (m *model) unloadDocument() []tea.Cmd {
|
|||
|
||||
var batch []tea.Cmd
|
||||
if m.pager.viewport.HighPerformanceRendering {
|
||||
batch = append(batch, tea.ClearScrollArea)
|
||||
batch = append(batch, tea.ClearScrollArea) //nolint:staticcheck
|
||||
}
|
||||
|
||||
if !m.stash.shouldSpin() {
|
||||
|
|
@ -234,7 +235,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
case "q":
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch m.state {
|
||||
switch m.state { //nolint:exhaustive
|
||||
case stateShowStash:
|
||||
// pass through all keys if we're editing the filter
|
||||
if m.stash.filterState == filtering {
|
||||
|
|
@ -328,7 +329,7 @@ func (m model) View() string {
|
|||
return errorView(m.fatalErr, true)
|
||||
}
|
||||
|
||||
switch m.state {
|
||||
switch m.state { //nolint:exhaustive
|
||||
case stateShowDocument:
|
||||
return m.pager.View()
|
||||
default:
|
||||
|
|
@ -449,17 +450,3 @@ 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
|
||||
}
|
||||
|
|
|
|||
8
url.go
8
url.go
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
|
|
@ -44,7 +45,7 @@ func readmeURL(path string) (*source, error) {
|
|||
}
|
||||
u, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("unable to parse url: %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
|
|
@ -78,3 +79,8 @@ 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, "://")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// Package utils provides utility functions.
|
||||
package utils
|
||||
|
||||
import (
|
||||
|
|
@ -30,7 +31,7 @@ func detectFrontmatter(c []byte) []int {
|
|||
return []int{-1, -1}
|
||||
}
|
||||
|
||||
// Expands tilde and all environment variables from the given path.
|
||||
// ExpandPath expands tilde and all environment variables from the given path.
|
||||
func ExpandPath(path string) string {
|
||||
s, err := homedir.Expand(path)
|
||||
if err == nil {
|
||||
|
|
@ -68,13 +69,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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue