Documentation
¶
Overview ¶
Package gisty provides a similar functionality of `gh gist` command.
It aims to provide a simple and easy to use interface to interact with GitHub Gists in the Go applications.
- Note
In this package, the environment variable "GH_TOKEN" or "GITHUB_TOKEN" must be set to the "personal access token" of the GitHub API. (`gist` scope required)
For GitHub Enterprise users, the environment variable "GH_ENTERPRISE_TOKEN" or "GITHUB_ENTERPRISE_TOKEN" must also be set with the GitHub API "authentication token".
- Tips and info to implement Gisty commands
The basic of Gisty is the wrapper of the sub command `gist` of `gh` application which is a Cobra instance from the `cli/cli` package. Gisty object receives the command arguments and passes them to Cobra command.
Commands that are not supported by `gh`, `Stargazer` for example, are implemented via `api` sub command of `cli/cli`("github.com/cli/cli/v2/pkg/cmd/api"). This api package supports GitHub GraphQL API (v4) which supports more features than the REST API (v3) that `gh` uses.
- GraphQL API documentation: https://docs.github.com/en/graphql - GraphQL Explorer: https://docs.github.com/ja/graphql/overview/explorer
Index ¶
- Constants
- Variables
- func ChDir(path string) (string, error)
- func NewErr(msgs ...any) error
- func SanitizeGistID(gistID string) string
- func WrapIfErr(err error, msgs ...any) error
- type AltFunc
- type Author
- type Comment
- type CreateArgs
- type GistInfo
- type Gisty
- func (g *Gisty) Clone(args []string) error
- func (g *Gisty) Comments(gistID string) ([]Comment, error)
- func (g *Gisty) Create(args CreateArgs) (*url.URL, error)
- func (g *Gisty) Delete(gist string) error
- func (g *Gisty) List(args ListArgs) ([]GistInfo, error)
- func (g *Gisty) Read(gist string) (*shared.Gist, error)
- func (g *Gisty) Stargazer(gistID string) (int, error)
- func (g *Gisty) Update(args UpdateArgs) (msg string, err error)
- type ListArgs
- type UpdateArgs
Examples ¶
Constants ¶
const DummyID = "42f5f23053ab59ca480f480b8d01e1fd"
DummyID is the ID of the dummy gist used in the example of the test.
const MaxCommentDefault = 100
Variables ¶
var AppendErrPos = true
AppendErrPos is a flag to disable the file name and line number of the caller from the error message. If set to false, it will not be appended.
var DummyComment = Comment{ Author: Author{ AvatarURL: "https://avatars.githubusercontent.com/u/11840938?u=e915b35bd36abfdcbbaaa6fbe5ea0c6e8ee51e70&v=4", Login: "KEINOS", }, ID: "GC_lADOALStqtoAIDQyZjVmMjMwNTNhYjU5Y2E0ODBmNDgwYjhkMDFlMWZkzgBF6l4", AuthorAssociation: "OWNER", BodyRaw: "1st example comment @ 20230528.\r\n\r\n- This line was added by edit.", BodyHTML: "<p dir=\"auto\">1st example comment @ 20230528.</p>\n<ul dir=\"auto\">\n<li>This line was added by edit.</li>\n</ul>", BodyText: "1st example comment @ 20230528.\n\nThis line was added by edit.", CreatedAt: "2023-05-28T08:36:32Z", PublishedAt: "2023-05-28T08:36:32Z", LastEditedAt: "2023-05-28T08:44:10Z", IsMinimized: false, MinimizedReason: "", }
DummyComment is the dummy comment used in the example of the test.
Functions ¶
func ChDir ¶
ChDir changes the current working directory to the given path and returns the previous working directory.
It is the callers choice to change the working directory back to the previous working directory.
func NewErr ¶
NewErr returns a new error object with the given message appending the file name and line number of the caller.
It is a wrapper of errors.New() and errors.Errorf(). Which is the alternative of deprecated github.com/pkg/errors.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-gisty/gisty" ) func main() { if err := gisty.NewErr(); err == nil { fmt.Println("empty args returns nil") } // Note the output contains the file name and line number of the caller. if err := gisty.NewErr("simple error message"); err != nil { fmt.Println(err) } if err := gisty.NewErr("%v error message", "formatted"); err != nil { fmt.Println(err) } if err := gisty.NewErr("%v error message(s)", 3); err != nil { fmt.Println(err) } if err := gisty.NewErr(1, 2, 3); err != nil { fmt.Println(err) } }
Output: empty args returns nil simple error message (file: new_err_test.go, line: 21) formatted error message (file: new_err_test.go, line: 25) 3 error message(s) (file: new_err_test.go, line: 29) 1 2 3 (file: new_err_test.go, line: 33)
func SanitizeGistID ¶
SanitizeGistID removes non-alphanumeric characters from gistID.
func WrapIfErr ¶
WrapIfErr returns nil if err is nil.
Otherwise, it returns an error annotating err with a stack trace at the point WrapIfErr is called. The supplied message contains the file name and line number of the caller.
Note that if the "msgs" arg is more than one, the first arg is used as a format string and the rest are used as arguments.
E.g.
WrapIfErr(nil, "it wil do nothing") WrapIfErr(err) // returns err as is WrapIfErr(err, "failed to do something") // eq to errors.Wrap WrapIfErr(err, "failed to do %s", "something") // eq to errors.Wrapf
It is a wrapper of errors.Wrap() and errors.Wrapf(). Which is the alternative of deprecated github.com/pkg/errors.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-gisty/gisty" ) func main() { var err error // WrapIfErr returns nil if err is nil fmt.Println("err is nil:", gisty.WrapIfErr(err, "error at line 18")) // Cause err to be non-nil err = gisty.NewErr("error occurred at line 21") // Wrap with no additional message fmt.Println("err is non-nil:\n", gisty.WrapIfErr(err)) // Wrap with additional message fmt.Println("err is non-nil:\n", gisty.WrapIfErr(err, "wrapped at line 25")) }
Output: err is nil: <nil> err is non-nil: error occurred at line 21 (file: wrap_if_err_test.go, line: 21) err is non-nil: wrapped at line 25 (file: wrap_if_err_test.go, line: 25): error occurred at line 21 (file: wrap_if_err_test.go, line: 21)
Example (Disable_error_position) ¶
package main import ( "fmt" "github.com/KEINOS/go-gisty/gisty" ) func main() { // Backup and defer restore the original value of AppendErrPos oldAppendErrPos := gisty.AppendErrPos defer func() { gisty.AppendErrPos = oldAppendErrPos }() { gisty.AppendErrPos = false // Disable appending the error position err := gisty.NewErr("error occurred at line 45") fmt.Println(gisty.WrapIfErr(err, "wrapped at line 46")) } { gisty.AppendErrPos = true // Enable appending the error position (default) err := gisty.NewErr("error occurred at line 51") fmt.Println(gisty.WrapIfErr(err, "wrapped at line 52")) } }
Output: wrapped at line 46: error occurred at line 45 wrapped at line 52 (file: wrap_if_err_test.go, line: 52): error occurred at line 51 (file: wrap_if_err_test.go, line: 51)
Types ¶
type AltFunc ¶
type AltFunc struct { Clone func(*clone.CloneOptions) error Comments func(*api.ApiOptions) error Create func(*create.CreateOptions) error Delete func(*delete.DeleteOptions) error List func(*list.ListOptions) error Read func(*view.ViewOptions) error Stargazer func(*api.ApiOptions) error Update func(*sync.SyncOptions) error }
AltFunc is a set of alternative functions to be used in the commands.
Even though it is mostly used for dependency-injection purposes during testing, it can be used to overrride the default behavior of the commands.
type Comment ¶ added in v0.0.2
type Comment struct { Author Author `json:"author"` ID string `json:"id"` AuthorAssociation string `json:"authorAssociation"` BodyRaw string `json:"body"` BodyHTML string `json:"bodyHTML"` BodyText string `json:"bodyText"` CreatedAt string `json:"createdAt"` PublishedAt string `json:"publishedAt"` LastEditedAt string `json:"lastEditedAt"` MinimizedReason string `json:"minimizedReason"` IsMinimized bool `json:"isMinimized"` }
Comment is a struct for the comment node in the GraphQL response.
type CreateArgs ¶
type CreateArgs struct { // Description for this gist Description string // FilePaths to contain in this gist FilePaths []string // AsPublic indicates whether this gist should be public or secret. // By default, it is secret. AsPublic bool }
CreateArgs are the arguments for the Create function.
type GistInfo ¶
type GistInfo struct { UpdatedAt time.Time // UpdatedAt is the time when the gist was last updated. GistID string // GistID is the ID of the gist. Description string // Description is the description of the gist. Files int // Files is the number of files in the gist. IsPublic bool // IsPublic is true if the gist is public. }
GistInfo holds information about a gist.
func NewGistInfo ¶
NewGistInfo creates a new GistInfo instance from the given input.
The input line must be tab-separated and have the following format:
[gistID]\t[description]\t[n] <file|files>\t<public|secret>\t[updatedAt] e.g. `1234567890abcdef my gist 2 files public 2018-01-01T00:00:00Z`
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-gisty/gisty" ) func main() { // "line" is one of the lines returned by the `gist list` command as an // example. Each line is tab separated and must contain the following // information in that order: // 1. Gist ID // 2. Description // 3. Number of files // 4. Public or private // 5. Updated at (RFC3339/ISO-8601 format) line := "7101f542be23e5048198e2a27c3cfda8 Title of gist item1 1 file public 2022-09-18T18:56:10Z" // NewGistInfo parses the line and returns a GistInfo object. item, err := gisty.NewGistInfo(line) if err != nil { log.Fatal(err) } // Print the parsed information. fmt.Printf("%T: %v\n", item.GistID, item.GistID) fmt.Printf("%T: %v\n", item.Description, item.Description) fmt.Printf("%T: %v\n", item.IsPublic, item.IsPublic) fmt.Printf("%T: %v\n", item.UpdatedAt, item.UpdatedAt) }
Output: string: 7101f542be23e5048198e2a27c3cfda8 string: Title of gist item1 bool: true time.Time: 2022-09-18 18:56:10 +0000 UTC
type Gisty ¶
type Gisty struct { // AltFunctions is a set of alternative functions to be used in the // commands. If nil is set, the default function is used. AltFunctions AltFunc // Factory holds the I/O streams, http client, and other common // dependencies to request GitHub API. Factory *cmdutil.Factory // Stdin is the standard input stream which each command reads from. Stdin *bytes.Buffer // Stdout is the standard output stream which each command writes to. Stdout *bytes.Buffer // Stderr is the standard error stream which each command writes to. Stderr *bytes.Buffer // BuildDate is the date when the binary was built. BuildDate string // BuildVersion is the version of the binary. BuildVersion string // MaxComment is the max number of comments in a gist to be fetched. MaxComment int }
Gisty is the main struct of this package.
func (*Gisty) Clone ¶
Clone clones a gist with the given args.
[]string{ <gist>, // required [<directory>], // optional [-- <gitflags>...], // optional }
<gist> is a gist ID or URL and <directory> is the directory to clone the gist into. <gitflags> listed after '--' are the additional flags to pass directly as a 'git clone' flags.
func (*Gisty) Comments ¶ added in v0.0.2
Comments returns the comments in the gist.
Example ¶
package main import ( "fmt" "log" "strings" "github.com/KEINOS/go-gisty/gisty" ) func main() { // Instantiate a new Gisty object. obj := gisty.NewGisty() // Get the comments in the gist. const gistID = "42f5f23053ab59ca480f480b8d01e1fd" comments, err := obj.Comments(gistID) if err != nil { log.Fatal(err) } if len(comments) == 0 { log.Fatal("No comments found.") } firstComment := comments[0] // Print available fields in the Comment struct. for _, field := range []struct { nameField string value interface{} }{ // List of fields in the Comment struct. {"Name", firstComment.Author.Login}, {"Icon", firstComment.Author.AvatarURL}, {"Association", firstComment.AuthorAssociation}, {"Comment ID", firstComment.ID}, {"Comment body(Raw)", firstComment.BodyRaw}, // Note that raw body contains "\r\n" for line breaks. {"Comment body(HTML)", firstComment.BodyHTML}, // Note that html body contains "\n" for line breaks. {"Comment body(Text)", firstComment.BodyText}, // Note that text body contains "\n" for line breaks. {"Created at", firstComment.CreatedAt}, {"Published at", firstComment.PublishedAt}, {"Updated at", firstComment.LastEditedAt}, {"Is minimized", firstComment.IsMinimized}, {"Minimized reason", firstComment.MinimizedReason}, } { val, ok := field.value.(string) if ok { fmt.Printf("%s: %#v\n", field.nameField, strings.TrimSpace(val)) } else { fmt.Printf("%s: %v\n", field.nameField, field.value) } } }
Output: Name: "KEINOS" Icon: "https://avatars.githubusercontent.com/u/11840938?u=e915b35bd36abfdcbbaaa6fbe5ea0c6e8ee51e70&v=4" Association: "OWNER" Comment ID: "GC_lADOALStqtoAIDQyZjVmMjMwNTNhYjU5Y2E0ODBmNDgwYjhkMDFlMWZkzgBF6l4" Comment body(Raw): "1st example comment @ 20230528.\r\n\r\n- This line was added by edit." Comment body(HTML): "<p dir=\"auto\">1st example comment @ 20230528.</p>\n<ul dir=\"auto\">\n<li>This line was added by edit.</li>\n</ul>" Comment body(Text): "1st example comment @ 20230528.\n\nThis line was added by edit." Created at: "2023-05-28T08:36:32Z" Published at: "2023-05-28T08:36:32Z" Updated at: "2023-05-28T08:44:10Z" Is minimized: false Minimized reason: ""
func (*Gisty) Create ¶
func (g *Gisty) Create(args CreateArgs) (*url.URL, error)
Create creates a new gist with the given args and returns the URL of the gist.
func (*Gisty) Delete ¶
Delete deletes a gist for a given gist ID or URL.
Note that it will remove the gist right away, without any confirmation.
func (*Gisty) List ¶
List returns a list of GistInfo objects. The returned list depends on the arguments passed to the function.
Example (Dummy_api_call) ¶
Example to retrieve the list of gists but WITHOUT calling the actual GitHub API.
package main import ( "fmt" "log" "github.com/KEINOS/go-gisty/gisty" "github.com/cli/cli/v2/pkg/cmd/gist/list" ) func main() { obj := gisty.NewGisty() // Dummy function to avoid calling the actual GitHub API during test/example. // Usually, you do not need to set this. obj.AltFunctions.List = func(*list.ListOptions) error { // Mock the GitHub API response. fmt.Fprint( obj.Stdout, "d5b9800c636dd78defa4f15894d54d29 Title of gist item2 6 files secret 2022-04-16T06:08:46Z", ) return nil } // Retrieve the list of gists. gistInfos, err := obj.List(gisty.ListArgs{ Limit: 1000, // Maximum number of gists to be obtained. OnlyPublic: true, // Get only public gists. OnlySecret: false, // Get only secret gists. If true, then prior than OnlyPublic. }) if err != nil { log.Fatal(err) } // Loop through the obtained gist information. In this example, only one // gist is obtained. for numItem, gistInfo := range gistInfos { fmt.Printf("#%d GistID: %v\n", numItem+1, gistInfo.GistID) fmt.Printf("#%d Description: %v\n", numItem+1, gistInfo.Description) fmt.Printf("#%d Num files in a gist: %v\n", numItem+1, gistInfo.Files) fmt.Printf("#%d IsPublic: %v\n", numItem+1, gistInfo.IsPublic) fmt.Printf("#%d UpdatedAt: %v\n", numItem+1, gistInfo.UpdatedAt) } }
Output: #1 GistID: d5b9800c636dd78defa4f15894d54d29 #1 Description: Title of gist item2 #1 Num files in a gist: 6 #1 IsPublic: false #1 UpdatedAt: 2022-04-16 06:08:46 +0000 UTC
func (*Gisty) Read ¶
Read returns a list of GistInfo objects. The returned list depends on the arguments passed to the function.
func (*Gisty) Stargazer ¶
Stargazer returns the number of stars in the gist for a given gist ID.
Note that gistID should not be the gist URL.
Example ¶
Example to get the number of stars in the gist.
package main import ( "fmt" "log" "github.com/KEINOS/go-gisty/gisty" "github.com/cli/cli/v2/pkg/cmd/api" ) func main() { obj := gisty.NewGisty() // Dummy function to avoid calling the actual GitHub API during test/example. // Usually, you do not need to set this. obj.AltFunctions.Stargazer = func(*api.ApiOptions) error { numStarsDummy := 10 // Mock the GitHub API response. fmt.Fprintf(obj.Stdout, "'%d'", numStarsDummy) return nil } // Target gist ID to obtain the number of stars. gistID := "5b10b34f87955dfc86d310cd623a61d1" count, err := obj.Stargazer(gistID) if err != nil { log.Fatal(err) } fmt.Println(count) }
Output: 10
type ListArgs ¶
type ListArgs struct { Limit int // Limit is the maximum number of gists to fetch (default 10) OnlyPublic bool // Show only public gists. Ignored if OnlySecret is true. OnlySecret bool // Show only secret gists. Prior than OnlyPublic. }
ListArgs are the arguments/options to the List function.
type UpdateArgs ¶
type UpdateArgs struct { PathDirRepo string // path to the local repository to sync. Branch string // if set, syncs local repo from remote parent on specific branch. Destination string // If set, syncs as a destination repo. If not set, syncs to remote parent. Source string // if set, syncs remote repo from another remote source repo. Force bool // if true, syncs using a hard reset. fast forward update if false. }
UpdateArgs are the arguments for the Update function.
func NewUpdateArgs ¶
func NewUpdateArgs(pathDirRepo string) UpdateArgs