improve formatting of `tea repos` (#223)
make fmt code review use OutputMarkdown use FormatTime() improved repo printing - ReposList() now allows selection of fields - RepoDetail() uses glamour and provides more details Co-authored-by: Norwin Roosen <git@nroo.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/223 Reviewed-by: 6543 <6543@noreply.gitea.io> Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-Authored-By: Norwin <noerw@noreply.gitea.io> Co-Committed-By: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
parent
a4b792e24d
commit
6ea331ce3b
|
@ -6,11 +6,28 @@ package repos
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/modules/print"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// printFieldsFlag provides a selection of fields to print
|
||||
var printFieldsFlag = cli.StringFlag{
|
||||
Name: "fields",
|
||||
Aliases: []string{"f"},
|
||||
Usage: fmt.Sprintf(`Comma-separated list of fields to print. Available values:
|
||||
%s
|
||||
`, strings.Join(print.RepoFields, ",")),
|
||||
Value: "owner,name,type,ssh",
|
||||
}
|
||||
|
||||
func getFields(ctx *cli.Context) []string {
|
||||
return strings.Split(ctx.String("fields"), ",")
|
||||
}
|
||||
|
||||
var typeFilterFlag = cli.StringFlag{
|
||||
Name: "type",
|
||||
Aliases: []string{"T"},
|
||||
|
|
|
@ -27,6 +27,7 @@ var CmdReposListFlags = append([]cli.Flag{
|
|||
Required: false,
|
||||
Usage: "List your starred repos instead",
|
||||
},
|
||||
&printFieldsFlag,
|
||||
&typeFilterFlag,
|
||||
&flags.PaginationPageFlag,
|
||||
&flags.PaginationLimitFlag,
|
||||
|
@ -79,7 +80,7 @@ func RunReposList(ctx *cli.Context) error {
|
|||
reposFiltered = filterReposByType(rps, typeFilter)
|
||||
}
|
||||
|
||||
print.ReposList(reposFiltered)
|
||||
print.ReposList(reposFiltered, getFields(ctx))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ var CmdReposSearch = cli.Command{
|
|||
Required: false,
|
||||
Usage: "Filter archived repos (true|false)",
|
||||
},
|
||||
&printFieldsFlag,
|
||||
&flags.PaginationPageFlag,
|
||||
&flags.PaginationLimitFlag,
|
||||
}, flags.LoginOutputFlags...),
|
||||
|
@ -122,6 +123,6 @@ func runReposSearch(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
print.ReposList(rps)
|
||||
print.ReposList(rps, getFields(ctx))
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,78 +6,158 @@ package print
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
)
|
||||
|
||||
type rp = *gitea.Repository
|
||||
type fieldFormatter = func(*gitea.Repository) string
|
||||
|
||||
var (
|
||||
fieldFormatters map[string]fieldFormatter
|
||||
|
||||
// RepoFields are the available fields to print with ReposList()
|
||||
RepoFields []string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fieldFormatters = map[string]fieldFormatter{
|
||||
"description": func(r rp) string { return r.Description },
|
||||
"forks": func(r rp) string { return fmt.Sprintf("%d", r.Forks) },
|
||||
"id": func(r rp) string { return r.FullName },
|
||||
"name": func(r rp) string { return r.Name },
|
||||
"owner": func(r rp) string { return r.Owner.UserName },
|
||||
"stars": func(r rp) string { return fmt.Sprintf("%d", r.Stars) },
|
||||
"ssh": func(r rp) string { return r.SSHURL },
|
||||
"updated": func(r rp) string { return FormatTime(r.Updated) },
|
||||
"url": func(r rp) string { return r.HTMLURL },
|
||||
"permission": func(r rp) string {
|
||||
if r.Permissions.Admin {
|
||||
return "admin"
|
||||
} else if r.Permissions.Push {
|
||||
return "write"
|
||||
}
|
||||
return "read"
|
||||
},
|
||||
"type": func(r rp) string {
|
||||
if r.Fork {
|
||||
return "fork"
|
||||
}
|
||||
if r.Mirror {
|
||||
return "mirror"
|
||||
}
|
||||
return "source"
|
||||
},
|
||||
}
|
||||
|
||||
for f := range fieldFormatters {
|
||||
RepoFields = append(RepoFields, f)
|
||||
}
|
||||
}
|
||||
|
||||
// ReposList prints a listing of the repos
|
||||
func ReposList(rps []*gitea.Repository) {
|
||||
if len(rps) == 0 {
|
||||
func ReposList(repos []*gitea.Repository, fields []string) {
|
||||
if len(repos) == 0 {
|
||||
fmt.Println("No repositories found")
|
||||
return
|
||||
}
|
||||
|
||||
headers := []string{
|
||||
"Name",
|
||||
"Type",
|
||||
"SSH",
|
||||
"Owner",
|
||||
}
|
||||
var values [][]string
|
||||
|
||||
for _, rp := range rps {
|
||||
var mode = "source"
|
||||
if rp.Fork {
|
||||
mode = "fork"
|
||||
}
|
||||
if rp.Mirror {
|
||||
mode = "mirror"
|
||||
if len(fields) == 0 {
|
||||
fmt.Println("No fields to print")
|
||||
return
|
||||
}
|
||||
|
||||
values = append(
|
||||
values,
|
||||
[]string{
|
||||
rp.FullName,
|
||||
mode,
|
||||
rp.SSHURL,
|
||||
rp.Owner.UserName,
|
||||
},
|
||||
)
|
||||
formatters := make([]fieldFormatter, len(fields))
|
||||
values := make([][]string, len(repos))
|
||||
|
||||
// find field format functions by header name
|
||||
for i, f := range fields {
|
||||
if formatter, ok := fieldFormatters[strings.ToLower(f)]; ok {
|
||||
formatters[i] = formatter
|
||||
} else {
|
||||
log.Fatalf("invalid field '%s'", f)
|
||||
}
|
||||
}
|
||||
|
||||
OutputList(flags.GlobalOutputValue, headers, values)
|
||||
// extract values from each repo and store them in 2D table
|
||||
for i, repo := range repos {
|
||||
values[i] = make([]string, len(formatters))
|
||||
for j, format := range formatters {
|
||||
values[i][j] = format(repo)
|
||||
}
|
||||
}
|
||||
|
||||
OutputList(flags.GlobalOutputValue, fields, values)
|
||||
}
|
||||
|
||||
// RepoDetails print an repo formatted to stdout
|
||||
func RepoDetails(repo *gitea.Repository, topics []string) {
|
||||
output := repo.FullName
|
||||
title := "# " + repo.FullName
|
||||
if repo.Mirror {
|
||||
output += " (mirror)"
|
||||
title += " (mirror)"
|
||||
}
|
||||
if repo.Fork {
|
||||
output += " (fork)"
|
||||
title += " (fork)"
|
||||
}
|
||||
if repo.Archived {
|
||||
output += " (archived)"
|
||||
title += " (archived)"
|
||||
}
|
||||
if repo.Empty {
|
||||
output += " (empty)"
|
||||
title += " (empty)"
|
||||
}
|
||||
output += "\n"
|
||||
if len(topics) != 0 {
|
||||
output += "Topics: " + strings.Join(topics, ", ") + "\n"
|
||||
title += "\n"
|
||||
|
||||
var desc string
|
||||
if len(repo.Description) != 0 {
|
||||
desc = fmt.Sprintf("*%s*\n\n", repo.Description)
|
||||
}
|
||||
output += "\n"
|
||||
output += repo.Description + "\n\n"
|
||||
output += fmt.Sprintf(
|
||||
"Open Issues: %d, Stars: %d, Forks: %d, Size: %s\n\n",
|
||||
|
||||
stats := fmt.Sprintf(
|
||||
"Issues: %d, Stars: %d, Forks: %d, Size: %s\n",
|
||||
repo.OpenIssues,
|
||||
repo.Stars,
|
||||
repo.Forks,
|
||||
formatSize(int64(repo.Size)),
|
||||
)
|
||||
|
||||
fmt.Print(output)
|
||||
// NOTE: for mirrors, this is the time the mirror was last fetched..
|
||||
updated := fmt.Sprintf(
|
||||
"Updated: %s (%s ago)\n",
|
||||
repo.Updated.Format("2006-01-02 15:04"),
|
||||
time.Now().Sub(repo.Updated).Truncate(time.Minute),
|
||||
)
|
||||
|
||||
urls := fmt.Sprintf(
|
||||
"- Browse:\t%s\n- Clone:\t%s\n",
|
||||
repo.HTMLURL,
|
||||
repo.SSHURL,
|
||||
)
|
||||
if len(repo.Website) != 0 {
|
||||
urls += fmt.Sprintf("- Web:\t%s\n", repo.Website)
|
||||
}
|
||||
|
||||
perm := fmt.Sprintf(
|
||||
"- Permission:\t%s\n",
|
||||
fieldFormatters["permission"](repo),
|
||||
)
|
||||
|
||||
var tops string
|
||||
if len(topics) != 0 {
|
||||
tops = fmt.Sprintf("- Topics:\t%s\n", strings.Join(topics, ", "))
|
||||
}
|
||||
|
||||
OutputMarkdown(fmt.Sprintf(
|
||||
"%s%s\n%s\n%s%s%s%s",
|
||||
title,
|
||||
desc,
|
||||
stats,
|
||||
updated,
|
||||
urls,
|
||||
perm,
|
||||
tops,
|
||||
))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue