X Tutup
Skip to content

Commit f7c4a0c

Browse files
committed
gh gist list
1 parent b34fe81 commit f7c4a0c

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

pkg/cmd/gist/gist.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package gist
22

33
import (
44
gistCreateCmd "github.com/cli/cli/pkg/cmd/gist/create"
5+
gistListCmd "github.com/cli/cli/pkg/cmd/gist/list"
56
"github.com/cli/cli/pkg/cmdutil"
67
"github.com/spf13/cobra"
78
)
@@ -14,6 +15,7 @@ func NewCmdGist(f *cmdutil.Factory) *cobra.Command {
1415
}
1516

1617
cmd.AddCommand(gistCreateCmd.NewCmdCreate(f, nil))
18+
cmd.AddCommand(gistListCmd.NewCmdList(f, nil))
1719

1820
return cmd
1921
}

pkg/cmd/gist/list/http.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package list
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
"sort"
8+
"time"
9+
10+
"github.com/cli/cli/api"
11+
)
12+
13+
type Gist struct {
14+
Description string `json:"description"`
15+
HTMLURL string `json:"html_url"`
16+
UpdatedAt time.Time `json:"updated_at"`
17+
Public bool
18+
}
19+
20+
func listGists(client *http.Client, hostname string, limit int, visibility string) ([]Gist, error) {
21+
result := []Gist{}
22+
23+
query := url.Values{}
24+
if visibility == "all" {
25+
query.Add("per_page", fmt.Sprintf("%d", limit))
26+
} else {
27+
query.Add("per_page", "100")
28+
}
29+
30+
apiClient := api.NewClientFromHTTP(client)
31+
err := apiClient.REST(hostname, "GET", "gists?"+query.Encode(), nil, &result)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
gists := []Gist{}
37+
38+
for _, gist := range result {
39+
if len(gists) == limit {
40+
break
41+
}
42+
if visibility == "all" || (visibility == "private" && !gist.Public) || (visibility == "public" && gist.Public) {
43+
gists = append(gists, gist)
44+
}
45+
}
46+
47+
sort.SliceStable(gists, func(i, j int) bool {
48+
return gists[i].UpdatedAt.After(gists[j].UpdatedAt)
49+
})
50+
51+
return gists, nil
52+
}

pkg/cmd/gist/list/list.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package list
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/cli/cli/internal/ghinstance"
8+
"github.com/cli/cli/pkg/cmdutil"
9+
"github.com/cli/cli/pkg/iostreams"
10+
"github.com/cli/cli/utils"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
type ListOptions struct {
15+
IO *iostreams.IOStreams
16+
HttpClient func() (*http.Client, error)
17+
18+
Limit int
19+
Visibility string // all, secret, public
20+
}
21+
22+
func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
23+
opts := &ListOptions{
24+
IO: f.IOStreams,
25+
HttpClient: f.HttpClient,
26+
}
27+
28+
cmd := &cobra.Command{
29+
Use: "list",
30+
Short: "List your gists",
31+
Args: cobra.NoArgs,
32+
RunE: func(cmd *cobra.Command, args []string) error {
33+
if opts.Limit < 1 {
34+
return &cmdutil.FlagError{Err: fmt.Errorf("invalid limit: %v", opts.Limit)}
35+
}
36+
37+
pub := cmd.Flags().Changed("public")
38+
priv := cmd.Flags().Changed("private")
39+
40+
opts.Visibility = "all"
41+
if pub && !priv {
42+
opts.Visibility = "public"
43+
} else if priv && !pub {
44+
opts.Visibility = "private"
45+
}
46+
47+
if runF != nil {
48+
return runF(opts)
49+
}
50+
51+
return listRun(opts)
52+
},
53+
}
54+
55+
cmd.Flags().IntVarP(&opts.Limit, "limit", "L", 10, "Maximum number of gists to fetch")
56+
cmd.Flags().Bool("public", false, "Show only public gists")
57+
cmd.Flags().Bool("private", false, "Show only private gists")
58+
59+
return cmd
60+
}
61+
62+
func listRun(opts *ListOptions) error {
63+
client, err := opts.HttpClient()
64+
if err != nil {
65+
return err
66+
}
67+
68+
gists, err := listGists(client, ghinstance.OverridableDefault(), opts.Limit, opts.Visibility)
69+
if err != nil {
70+
return err
71+
}
72+
73+
cs := opts.IO.ColorScheme()
74+
75+
tp := utils.NewTablePrinter(opts.IO)
76+
77+
for _, gist := range gists {
78+
// TODO i was getting confusing results with table printer's truncation
79+
description := gist.Description
80+
if len(description) > 40 {
81+
description = description[0:37] + "..."
82+
}
83+
84+
tp.AddField(description, nil, cs.Bold)
85+
tp.AddField(gist.HTMLURL, nil, nil)
86+
tp.EndRow()
87+
}
88+
89+
return tp.Render()
90+
}

pkg/cmd/gist/list/list_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package list
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/cli/cli/pkg/cmdutil"
8+
"github.com/google/shlex"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestNewCmdList(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
cli string
16+
wants ListOptions
17+
}{
18+
{
19+
name: "no arguments",
20+
cli: "",
21+
wants: ListOptions{
22+
Limit: 10,
23+
Visibility: "all",
24+
},
25+
},
26+
{
27+
name: "public",
28+
cli: "--public",
29+
wants: ListOptions{
30+
Limit: 10,
31+
Visibility: "public",
32+
},
33+
},
34+
{
35+
name: "private",
36+
cli: "--private",
37+
wants: ListOptions{
38+
Limit: 10,
39+
Visibility: "private",
40+
},
41+
},
42+
{
43+
name: "public and private",
44+
cli: "--private --public",
45+
wants: ListOptions{
46+
Limit: 10,
47+
Visibility: "all",
48+
},
49+
},
50+
{
51+
name: "limit",
52+
cli: "--limit 30",
53+
wants: ListOptions{
54+
Limit: 30,
55+
Visibility: "all",
56+
},
57+
},
58+
}
59+
60+
for _, tt := range tests {
61+
t.Run(tt.name, func(t *testing.T) {
62+
f := &cmdutil.Factory{}
63+
64+
argv, err := shlex.Split(tt.cli)
65+
assert.NoError(t, err)
66+
67+
var gotOpts *ListOptions
68+
cmd := NewCmdList(f, func(opts *ListOptions) error {
69+
gotOpts = opts
70+
return nil
71+
})
72+
cmd.SetArgs(argv)
73+
cmd.SetIn(&bytes.Buffer{})
74+
cmd.SetOut(&bytes.Buffer{})
75+
cmd.SetErr(&bytes.Buffer{})
76+
77+
_, err = cmd.ExecuteC()
78+
assert.NoError(t, err)
79+
80+
assert.Equal(t, tt.wants.Visibility, gotOpts.Visibility)
81+
assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
82+
})
83+
}
84+
}

0 commit comments

Comments
 (0)
X Tutup