Compare commits

...

5 commits

Author SHA1 Message Date
Carlos Alexandro Becker
30efab4f46
test: update
Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
2025-10-21 09:56:51 -03:00
Carlos Alexandro Becker
00893dd2b8
Merge remote-tracking branch 'origin/master' into fang
Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
2025-10-21 09:28:31 -03:00
Carlos Alexandro Becker
7ec9d79229
fix: use context in http calls 2025-06-30 08:38:28 -03:00
Carlos Alexandro Becker
45cacb4b31
fix: use ctx
Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
2025-06-30 08:24:29 -03:00
Carlos Alexandro Becker
3dba1d73f6
feat: use fang 2025-06-23 15:48:23 -03:00
9 changed files with 89 additions and 91 deletions

View file

@ -1,6 +1,7 @@
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
@ -11,7 +12,7 @@ import (
)
// findGitHubREADME tries to find the correct README filename in a repository using GitHub API.
func findGitHubREADME(u *url.URL) (*source, error) {
func findGitHubREADME(ctx context.Context, u *url.URL) (*source, error) {
owner, repo, ok := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
if !ok {
return nil, fmt.Errorf("invalid url: %s", u.String())
@ -23,12 +24,15 @@ func findGitHubREADME(u *url.URL) (*source, error) {
apiURL := fmt.Sprintf("https://api.%s/repos/%s/%s/readme", u.Hostname(), owner, repo)
//nolint:bodyclose
// it is closed on the caller
res, err := http.Get(apiURL) //nolint: gosec,noctx
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil)
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
defer res.Body.Close() //nolint:errcheck
body, err := io.ReadAll(res.Body)
if err != nil {
@ -41,9 +45,12 @@ func findGitHubREADME(u *url.URL) (*source, error) {
}
if res.StatusCode == http.StatusOK {
//nolint:bodyclose
// it is closed on the caller
resp, err := http.Get(result.DownloadURL) //nolint: noctx
// consumer of the source is responsible for closing the ReadCloser.
req, err := http.NewRequestWithContext(ctx, http.MethodGet, result.DownloadURL, nil)
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}

View file

@ -1,6 +1,7 @@
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
@ -11,7 +12,7 @@ import (
)
// findGitLabREADME tries to find the correct README filename in a repository using GitLab API.
func findGitLabREADME(u *url.URL) (*source, error) {
func findGitLabREADME(ctx context.Context, u *url.URL) (*source, error) {
owner, repo, ok := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
if !ok {
return nil, fmt.Errorf("invalid url: %s", u.String())
@ -25,12 +26,15 @@ func findGitLabREADME(u *url.URL) (*source, error) {
apiURL := fmt.Sprintf("https://%s/api/v4/projects/%s", u.Hostname(), projectPath)
//nolint:bodyclose
// it is closed on the caller
res, err := http.Get(apiURL) //nolint: gosec,noctx
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil)
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
defer res.Body.Close() //nolint:errcheck
body, err := io.ReadAll(res.Body)
if err != nil {
@ -45,9 +49,12 @@ func findGitLabREADME(u *url.URL) (*source, error) {
readmeRawURL := strings.ReplaceAll(result.ReadmeURL, "blob", "raw")
if res.StatusCode == http.StatusOK {
//nolint:bodyclose
// it is closed on the caller
resp, err := http.Get(readmeRawURL) //nolint: gosec,noctx
// consumer of the source is responsible for closing the ReadCloser.
req, err := http.NewRequestWithContext(ctx, http.MethodGet, readmeRawURL, nil)
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}

19
go.mod
View file

@ -1,14 +1,13 @@
module github.com/charmbracelet/glow/v2
go 1.24.0
toolchain go1.24.1
go 1.24.2
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/fang v0.4.3
github.com/charmbracelet/glamour v0.10.0
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
github.com/charmbracelet/log v0.4.2
@ -19,9 +18,7 @@ require (
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/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.1
@ -35,11 +32,16 @@ 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/colorprofile v0.3.2 // indirect
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea // indirect
github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef // indirect
github.com/charmbracelet/x/ansi v0.10.1 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444 // indirect
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/charmbracelet/x/termios v0.1.1 // indirect
github.com/charmbracelet/x/windows v0.2.2 // 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
@ -47,14 +49,16 @@ require (
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // 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/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-cobra v1.3.0 // indirect
github.com/muesli/mango-pflag v0.1.0 // indirect
github.com/muesli/roff v0.1.0 // 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
@ -71,5 +75,6 @@ require (
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/sync v0.17.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)

22
go.sum
View file

@ -18,26 +18,38 @@ github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u
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/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
github.com/charmbracelet/fang v0.4.3 h1:qXeMxnL4H6mSKBUhDefHu8NfikFbP/MBNTfqTrXvzmY=
github.com/charmbracelet/fang v0.4.3/go.mod h1:wHJKQYO5ReYsxx+yZl+skDtrlKO/4LLEQ6EXsdHhRhg=
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/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea h1:g1HfUgSMvye8mgecMD1mPscpt+pzJoDEiSA+p2QXzdQ=
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea/go.mod h1:ngHerf1JLJXBrDXdphn5gFrBPriCL437uwukd5c93pM=
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/ultraviolet v0.0.0-20250915111650-81d4262876ef h1:VrWaUi2LXYLjfjCHowdSOEc6dQ9Ro14KY7Bw4IWd19M=
github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef/go.mod h1:AThRsQH1t+dfyOKIwXRoJBniYFQUkUpQq4paheHMc2o=
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/charmtone v0.0.0-20250603201427-c31516f43444 h1:IJDiTgVE56gkAGfq0lBEloWgkXMk4hl/bmuPoicI4R0=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0=
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/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
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=
@ -75,8 +87,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
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/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
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=
@ -157,6 +169,8 @@ golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuh
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
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.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=

50
main.go
View file

@ -2,6 +2,7 @@
package main
import (
"context"
"errors"
"fmt"
"io"
@ -14,6 +15,7 @@ import (
"strings"
"github.com/caarlos0/env/v11"
"github.com/charmbracelet/fang"
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/glamour/styles"
"github.com/charmbracelet/glow/v2/ui"
@ -44,13 +46,9 @@ var (
mouse bool
rootCmd = &cobra.Command{
Use: "glow [SOURCE|DIR]",
Short: "Render markdown on the CLI, with pizzazz!",
Long: paragraph(
fmt.Sprintf("\nRender markdown on the CLI, %s!", keyword("with pizzazz")),
),
SilenceErrors: false,
SilenceUsage: true,
Use: "glow [SOURCE|DIR]",
Short: "Render markdown on the CLI, with pizzazz!",
Long: fmt.Sprintf("Render markdown on the CLI, %s!", keyword("with pizzazz")),
TraverseChildren: true,
Args: cobra.MaximumNArgs(1),
ValidArgsFunction: func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
@ -70,14 +68,14 @@ type source struct {
}
// sourceFromArg parses an argument and creates a readable source for it.
func sourceFromArg(arg string) (*source, error) {
func sourceFromArg(ctx context.Context, arg string) (*source, error) {
// from stdin
if arg == "-" {
return &source{reader: os.Stdin}, nil
}
// a GitHub or GitLab URL (even without the protocol):
src, err := readmeURL(arg)
src, err := readmeURL(ctx, arg)
if src != nil && err == nil {
// if there's an error, try next methods...
return src, nil
@ -90,7 +88,11 @@ func sourceFromArg(arg string) (*source, error) {
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
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
@ -233,7 +235,7 @@ func execute(cmd *cobra.Command, args []string) error {
switch len(args) {
// TUI running on cwd
case 0:
return runTUI("", "")
return runTUI(cmd.Context(), "", "")
// TUI with possible dir argument
case 1:
@ -243,7 +245,7 @@ func execute(cmd *cobra.Command, args []string) error {
if err == nil && info.IsDir() {
p, err := filepath.Abs(args[0])
if err == nil {
return runTUI(p, "")
return runTUI(cmd.Context(), p, "")
}
}
fallthrough
@ -262,7 +264,7 @@ func execute(cmd *cobra.Command, args []string) error {
func executeArg(cmd *cobra.Command, arg string, w io.Writer) error {
// create an io.Reader from the markdown source in cli-args
src, err := sourceFromArg(arg)
src, err := sourceFromArg(cmd.Context(), arg)
if err != nil {
return err
}
@ -320,7 +322,7 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
}
pa := strings.Split(pagerCmd, " ")
c := exec.Command(pa[0], pa[1:]...) //nolint:gosec
c := exec.CommandContext(cmd.Context(), pa[0], pa[1:]...) //nolint:gosec
c.Stdin = strings.NewReader(out)
c.Stdout = os.Stdout
if err := c.Run(); err != nil {
@ -332,7 +334,7 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
if !isURL(src.URL) {
path = src.URL
}
return runTUI(path, content)
return runTUI(cmd.Context(), path, content)
default:
if _, err = fmt.Fprint(w, out); err != nil {
return fmt.Errorf("unable to write to writer: %w", err)
@ -341,7 +343,7 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
}
}
func runTUI(path string, content string) error {
func runTUI(ctx context.Context, path string, content string) error {
// Read environment to get debugging stuff
cfg, err := env.ParseAs[ui.Config]()
if err != nil {
@ -361,7 +363,7 @@ func runTUI(path string, content string) error {
cfg.PreserveNewLines = preserveNewLines
// Run Bubble Tea program
if _, err := ui.NewProgram(cfg, content).Run(); err != nil {
if _, err := ui.NewProgram(ctx, cfg, content).Run(); err != nil {
return fmt.Errorf("unable to run tui program: %w", err)
}
@ -374,7 +376,7 @@ func main() {
fmt.Println(err)
os.Exit(1)
}
if err := rootCmd.Execute(); err != nil {
if err := fang.Execute(context.Background(), rootCmd); err != nil {
_ = closer()
os.Exit(1)
}
@ -383,16 +385,6 @@ func main() {
func init() {
tryLoadConfigFromDefaultPlaces()
if len(CommitSHA) >= 7 {
vt := rootCmd.VersionTemplate()
rootCmd.SetVersionTemplate(vt[:len(vt)-1] + " (" + CommitSHA[0:7] + ")\n")
}
if Version == "" {
Version = "unknown (built from source)"
}
rootCmd.Version = Version
rootCmd.InitDefaultCompletionCmd()
// "Glow Classic" cli arguments
rootCmd.PersistentFlags().StringVar(&configFile, "config", "", fmt.Sprintf("config file (default %s)", viper.GetViper().ConfigFileUsed()))
rootCmd.Flags().BoolVarP(&pager, "pager", "p", false, "display with pager")
@ -420,7 +412,7 @@ func init() {
viper.SetDefault("width", 0)
viper.SetDefault("all", true)
rootCmd.AddCommand(configCmd, manCmd)
rootCmd.AddCommand(configCmd)
}
func tryLoadConfigFromDefaultPlaces() {

View file

@ -1,29 +0,0 @@
package main
import (
"fmt"
"os"
mcobra "github.com/muesli/mango-cobra"
"github.com/muesli/roff"
"github.com/spf13/cobra"
)
var manCmd = &cobra.Command{
Use: "man",
Short: "Generates manpages",
SilenceUsage: true,
DisableFlagsInUseLine: true,
Hidden: true,
Args: cobra.NoArgs,
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)
}
if _, err := fmt.Fprint(os.Stdout, manPage.Build(roff.NewDocument())); err != nil {
return fmt.Errorf("unable to build man page: %w", err)
}
return nil
},
}

View file

@ -2,6 +2,7 @@
package ui
import (
"context"
"fmt"
"os"
"path/filepath"
@ -30,7 +31,7 @@ var (
)
// NewProgram returns a new Tea program.
func NewProgram(cfg Config, content string) *tea.Program {
func NewProgram(ctx context.Context, cfg Config, content string) *tea.Program {
log.Debug(
"Starting glow",
"high_perf_pager",
@ -40,7 +41,7 @@ func NewProgram(cfg Config, content string) *tea.Program {
)
config = cfg
opts := []tea.ProgramOption{tea.WithAltScreen()}
opts := []tea.ProgramOption{tea.WithAltScreen(), tea.WithContext(ctx)}
if cfg.EnableMouse {
opts = append(opts, tea.WithMouseCellMotion())
}

11
url.go
View file

@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"net/url"
"strings"
@ -26,16 +27,16 @@ func init() {
})
}
func readmeURL(path string) (*source, error) {
func readmeURL(ctx context.Context, path string) (*source, error) {
switch {
case strings.HasPrefix(path, protoGithub):
if u := githubReadmeURL(path); u != nil {
return readmeURL(u.String())
return readmeURL(ctx, u.String())
}
return nil, nil
case strings.HasPrefix(path, protoGitlab):
if u := gitlabReadmeURL(path); u != nil {
return readmeURL(u.String())
return readmeURL(ctx, u.String())
}
return nil, nil
}
@ -50,9 +51,9 @@ func readmeURL(path string) (*source, error) {
switch {
case u.Hostname() == githubURL.Hostname():
return findGitHubREADME(u)
return findGitHubREADME(ctx, u)
case u.Hostname() == gitlabURL.Hostname():
return findGitLabREADME(u)
return findGitLabREADME(ctx, u)
}
return nil, nil

View file

@ -15,7 +15,7 @@ func TestURLParser(t *testing.T) {
} {
t.Run(path, func(t *testing.T) {
t.Skip("test uses network, sometimes fails for no reason")
got, err := readmeURL(path)
got, err := readmeURL(t.Context(), path)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}