Skip to content

Commit b171241

Browse files
committed
start on gist view
1 parent f7c4a0c commit b171241

File tree

5 files changed

+201
-0
lines changed

5 files changed

+201
-0
lines changed

pkg/cmd/gist/gist.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package gist
33
import (
44
gistCreateCmd "github.com/cli/cli/pkg/cmd/gist/create"
55
gistListCmd "github.com/cli/cli/pkg/cmd/gist/list"
6+
gistViewCmd "github.com/cli/cli/pkg/cmd/gist/view"
67
"github.com/cli/cli/pkg/cmdutil"
78
"github.com/spf13/cobra"
89
)
@@ -16,6 +17,7 @@ func NewCmdGist(f *cmdutil.Factory) *cobra.Command {
1617

1718
cmd.AddCommand(gistCreateCmd.NewCmdCreate(f, nil))
1819
cmd.AddCommand(gistListCmd.NewCmdList(f, nil))
20+
cmd.AddCommand(gistViewCmd.NewCmdView(f, nil))
1921

2022
return cmd
2123
}

pkg/cmd/gist/list/list_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,5 @@ func TestNewCmdList(t *testing.T) {
8282
})
8383
}
8484
}
85+
86+
// TODO execution tests

pkg/cmd/gist/view/http.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package view
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/cli/cli/api"
8+
)
9+
10+
type GistFile struct {
11+
Filename string
12+
Type string
13+
Language string
14+
Content string
15+
}
16+
17+
type Gist struct {
18+
Description string
19+
Files map[string]GistFile
20+
}
21+
22+
func getGist(client *http.Client, hostname, gistID string) (*Gist, error) {
23+
gist := Gist{}
24+
path := fmt.Sprintf("gists/%s", gistID)
25+
26+
apiClient := api.NewClientFromHTTP(client)
27+
err := apiClient.REST(hostname, "GET", path, nil, &gist)
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
return &gist, nil
33+
}

pkg/cmd/gist/view/view.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package view
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
"strings"
8+
9+
"github.com/cli/cli/internal/ghinstance"
10+
"github.com/cli/cli/pkg/cmdutil"
11+
"github.com/cli/cli/pkg/iostreams"
12+
"github.com/cli/cli/utils"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
type ViewOptions struct {
17+
IO *iostreams.IOStreams
18+
HttpClient func() (*http.Client, error)
19+
20+
Selector string
21+
Raw bool
22+
}
23+
24+
func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Command {
25+
opts := &ViewOptions{
26+
IO: f.IOStreams,
27+
HttpClient: f.HttpClient,
28+
}
29+
30+
cmd := &cobra.Command{
31+
Use: "view {<gist id> | <gist url>}",
32+
Short: "View a gist",
33+
Args: cobra.ExactArgs(1),
34+
RunE: func(cmd *cobra.Command, args []string) error {
35+
opts.Selector = args[0]
36+
37+
if !opts.IO.IsStdoutTTY() {
38+
opts.Raw = true
39+
}
40+
41+
if runF != nil {
42+
return runF(opts)
43+
}
44+
return viewRun(opts)
45+
},
46+
}
47+
48+
cmd.Flags().BoolVarP(&opts.Raw, "raw", "r", false, "do not try and render markdown")
49+
50+
return cmd
51+
}
52+
53+
func viewRun(opts *ViewOptions) error {
54+
gistID := opts.Selector
55+
56+
u, err := url.Parse(opts.Selector)
57+
if err == nil {
58+
if strings.HasPrefix(u.Path, "/") {
59+
gistID = u.Path[1:]
60+
}
61+
}
62+
63+
client, err := opts.HttpClient()
64+
if err != nil {
65+
return err
66+
}
67+
68+
gist, err := getGist(client, ghinstance.OverridableDefault(), gistID)
69+
if err != nil {
70+
return err
71+
}
72+
73+
cs := opts.IO.ColorScheme()
74+
if gist.Description != "" {
75+
fmt.Fprintf(opts.IO.ErrOut, "%s\n", cs.Bold(gist.Description))
76+
}
77+
78+
for filename, gistFile := range gist.Files {
79+
fmt.Fprintf(opts.IO.ErrOut, "%s\n", cs.Gray(filename))
80+
fmt.Fprintln(opts.IO.ErrOut)
81+
content := gistFile.Content
82+
if strings.Contains(gistFile.Type, "markdown") && !opts.Raw {
83+
rendered, err := utils.RenderMarkdown(gistFile.Content)
84+
if err == nil {
85+
content = rendered
86+
}
87+
}
88+
fmt.Fprintf(opts.IO.Out, "%s\n", content)
89+
fmt.Fprintln(opts.IO.Out)
90+
}
91+
92+
// TODO print gist files, possibly with rendered markdown
93+
return nil
94+
}

pkg/cmd/gist/view/view_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package view
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/cli/cli/pkg/cmdutil"
8+
"github.com/cli/cli/pkg/iostreams"
9+
"github.com/google/shlex"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestNewCmdView(t *testing.T) {
14+
tests := []struct {
15+
name string
16+
cli string
17+
wants ViewOptions
18+
tty bool
19+
}{
20+
{
21+
name: "tty no arguments",
22+
tty: true,
23+
cli: "123",
24+
wants: ViewOptions{
25+
Raw: false,
26+
Selector: "123",
27+
},
28+
},
29+
{
30+
name: "nontty no arguments",
31+
cli: "123",
32+
wants: ViewOptions{
33+
Raw: true,
34+
Selector: "123",
35+
},
36+
},
37+
}
38+
39+
for _, tt := range tests {
40+
t.Run(tt.name, func(t *testing.T) {
41+
io, _, _, _ := iostreams.Test()
42+
io.SetStdoutTTY(tt.tty)
43+
44+
f := &cmdutil.Factory{
45+
IOStreams: io,
46+
}
47+
48+
argv, err := shlex.Split(tt.cli)
49+
assert.NoError(t, err)
50+
51+
var gotOpts *ViewOptions
52+
cmd := NewCmdView(f, func(opts *ViewOptions) error {
53+
gotOpts = opts
54+
return nil
55+
})
56+
cmd.SetArgs(argv)
57+
cmd.SetIn(&bytes.Buffer{})
58+
cmd.SetOut(&bytes.Buffer{})
59+
cmd.SetErr(&bytes.Buffer{})
60+
61+
_, err = cmd.ExecuteC()
62+
assert.NoError(t, err)
63+
64+
assert.Equal(t, tt.wants.Raw, gotOpts.Raw)
65+
assert.Equal(t, tt.wants.Selector, gotOpts.Selector)
66+
})
67+
}
68+
}
69+
70+
// TODO execution tests

0 commit comments

Comments
 (0)