aboutsummaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2020-06-26 01:02:27 +0200
committerGitHub <noreply@github.com>2020-06-26 01:02:27 +0200
commit2dd0dbb1344ae9293aae05346f977b5d5907934b (patch)
tree610ff7e381ef99827dc1b1dbc9ae4ea137fe5e21 /commands
parentf790083fb28ac0e68acddc9d5e7a709107a70bab (diff)
parentc326007d01b623bcf883f74f31fc3e5ab3078396 (diff)
downloadgit-bug-2dd0dbb1344ae9293aae05346f977b5d5907934b.tar.gz
Merge pull request #410 from MichaelMure/output-formatting-2
Add formatting options to the 'show' and 'user ls' commands
Diffstat (limited to 'commands')
-rw-r--r--commands/json_common.go55
-rw-r--r--commands/ls.go152
-rw-r--r--commands/show.go198
-rw-r--r--commands/user_ls.go47
4 files changed, 380 insertions, 72 deletions
diff --git a/commands/json_common.go b/commands/json_common.go
new file mode 100644
index 00000000..9a144a1e
--- /dev/null
+++ b/commands/json_common.go
@@ -0,0 +1,55 @@
+package commands
+
+import (
+ "time"
+
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/identity"
+ "github.com/MichaelMure/git-bug/util/lamport"
+)
+
+type JSONIdentity struct {
+ Id string `json:"id"`
+ HumanId string `json:"human_id"`
+ Name string `json:"name"`
+ Login string `json:"login"`
+}
+
+func NewJSONIdentity(i identity.Interface) JSONIdentity {
+ return JSONIdentity{
+ Id: i.Id().String(),
+ HumanId: i.Id().Human(),
+ Name: i.Name(),
+ Login: i.Login(),
+ }
+}
+
+func NewJSONIdentityFromExcerpt(excerpt *cache.IdentityExcerpt) JSONIdentity {
+ return JSONIdentity{
+ Id: excerpt.Id.String(),
+ HumanId: excerpt.Id.Human(),
+ Name: excerpt.Name,
+ Login: excerpt.Login,
+ }
+}
+
+func NewJSONIdentityFromLegacyExcerpt(excerpt *cache.LegacyAuthorExcerpt) JSONIdentity {
+ return JSONIdentity{
+ Name: excerpt.Name,
+ Login: excerpt.Login,
+ }
+}
+
+type JSONTime struct {
+ Timestamp int64 `json:"timestamp"`
+ Time time.Time `json:"time"`
+ Lamport lamport.Time `json:"lamport,omitempty"`
+}
+
+func NewJSONTime(t time.Time, l lamport.Time) JSONTime {
+ return JSONTime{
+ Timestamp: t.Unix(),
+ Time: t,
+ Lamport: l,
+ }
+}
diff --git a/commands/ls.go b/commands/ls.go
index 68cb0cfc..34f1f982 100644
--- a/commands/ls.go
+++ b/commands/ls.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"strings"
- "time"
text "github.com/MichaelMure/go-term-text"
"github.com/spf13/cobra"
@@ -61,6 +60,8 @@ func runLsBug(_ *cobra.Command, args []string) error {
}
switch lsOutputFormat {
+ case "org-mode":
+ return lsOrgmodeFormatter(backend, bugExcerpt)
case "plain":
return lsPlainFormatter(backend, bugExcerpt)
case "json":
@@ -72,11 +73,11 @@ func runLsBug(_ *cobra.Command, args []string) error {
}
}
-type JSONBug struct {
- Id string `json:"id"`
- HumanId string `json:"human_id"`
- CreationTime time.Time `json:"creation_time"`
- LastEdited time.Time `json:"last_edited"`
+type JSONBugExcerpt struct {
+ Id string `json:"id"`
+ HumanId string `json:"human_id"`
+ CreateTime JSONTime `json:"create_time"`
+ EditTime JSONTime `json:"edit_time"`
Status string `json:"status"`
Labels []bug.Label `json:"labels"`
@@ -89,29 +90,19 @@ type JSONBug struct {
Metadata map[string]string `json:"metadata"`
}
-type JSONIdentity struct {
- Id string `json:"id"`
- HumanId string `json:"human_id"`
- Name string `json:"name"`
- Login string `json:"login"`
-}
-
func lsJsonFormatter(backend *cache.RepoCache, bugExcerpts []*cache.BugExcerpt) error {
- jsonBugs := make([]JSONBug, len(bugExcerpts))
+ jsonBugs := make([]JSONBugExcerpt, len(bugExcerpts))
for i, b := range bugExcerpts {
- jsonBug := JSONBug{
- b.Id.String(),
- b.Id.Human(),
- time.Unix(b.CreateUnixTime, 0),
- time.Unix(b.EditUnixTime, 0),
- b.Status.String(),
- b.Labels,
- b.Title,
- []JSONIdentity{},
- []JSONIdentity{},
- JSONIdentity{},
- b.LenComments,
- b.CreateMetadata,
+ jsonBug := JSONBugExcerpt{
+ Id: b.Id.String(),
+ HumanId: b.Id.Human(),
+ CreateTime: NewJSONTime(b.CreateTime(), b.CreateLamportTime),
+ EditTime: NewJSONTime(b.EditTime(), b.EditLamportTime),
+ Status: b.Status.String(),
+ Labels: b.Labels,
+ Title: b.Title,
+ Comments: b.LenComments,
+ Metadata: b.CreateMetadata,
}
if b.AuthorId != "" {
@@ -119,41 +110,27 @@ func lsJsonFormatter(backend *cache.RepoCache, bugExcerpts []*cache.BugExcerpt)
if err != nil {
return err
}
-
- jsonBug.Author.Name = author.DisplayName()
- jsonBug.Author.Login = author.Login
- jsonBug.Author.Id = author.Id.String()
- jsonBug.Author.HumanId = author.Id.Human()
+ jsonBug.Author = NewJSONIdentityFromExcerpt(author)
} else {
- jsonBug.Author.Name = b.LegacyAuthor.DisplayName()
- jsonBug.Author.Login = b.LegacyAuthor.Login
+ jsonBug.Author = NewJSONIdentityFromLegacyExcerpt(&b.LegacyAuthor)
}
- for _, element := range b.Actors {
+ jsonBug.Actors = make([]JSONIdentity, len(b.Actors))
+ for i, element := range b.Actors {
actor, err := backend.ResolveIdentityExcerpt(element)
if err != nil {
return err
}
-
- jsonBug.Actors = append(jsonBug.Actors, JSONIdentity{
- actor.Id.String(),
- actor.Id.Human(),
- actor.Name,
- actor.Login,
- })
+ jsonBug.Actors[i] = NewJSONIdentityFromExcerpt(actor)
}
- for _, element := range b.Participants {
+ jsonBug.Participants = make([]JSONIdentity, len(b.Participants))
+ for i, element := range b.Participants {
participant, err := backend.ResolveIdentityExcerpt(element)
if err != nil {
return err
}
- jsonBug.Participants = append(jsonBug.Participants, JSONIdentity{
- participant.Id.String(),
- participant.Id.Human(),
- participant.DisplayName(),
- participant.Login,
- })
+ jsonBug.Participants[i] = NewJSONIdentityFromExcerpt(participant)
}
jsonBugs[i] = jsonBug
@@ -207,11 +184,84 @@ func lsDefaultFormatter(backend *cache.RepoCache, bugExcerpts []*cache.BugExcerp
func lsPlainFormatter(_ *cache.RepoCache, bugExcerpts []*cache.BugExcerpt) error {
for _, b := range bugExcerpts {
- fmt.Printf("[%s] %s\n", b.Status, b.Title)
+ fmt.Printf("%s [%s] %s\n", b.Id.Human(), b.Status, b.Title)
}
return nil
}
+func lsOrgmodeFormatter(backend *cache.RepoCache, bugExcerpts []*cache.BugExcerpt) error {
+ fmt.Println("+TODO: OPEN | CLOSED")
+
+ for _, b := range bugExcerpts {
+ status := strings.Title(b.Status.String())
+
+ var title string
+ if link, ok := b.CreateMetadata["github-url"]; ok {
+ title = fmt.Sprintf("[%s][%s]", link, b.Title)
+ } else {
+ title = b.Title
+ }
+
+ var name string
+ if b.AuthorId != "" {
+ author, err := backend.ResolveIdentityExcerpt(b.AuthorId)
+ if err != nil {
+ return err
+ }
+ name = author.DisplayName()
+ } else {
+ name = b.LegacyAuthor.DisplayName()
+ }
+
+ labels := b.Labels
+ var labelsString string
+ if len(labels) > 0 {
+ labelsString = fmt.Sprintf(":%s:", strings.Replace(fmt.Sprint(labels), " ", ":", -1))
+ } else {
+ labelsString = ""
+ }
+
+ fmt.Printf("* %s %s [%s] %s: %s %s\n",
+ b.Id.Human(),
+ status,
+ b.CreateTime(),
+ name,
+ title,
+ labelsString,
+ )
+
+ fmt.Printf("** Last Edited: %s\n", b.EditTime().String())
+
+ fmt.Printf("** Actors:\n")
+ for _, element := range b.Actors {
+ actor, err := backend.ResolveIdentityExcerpt(element)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf(": %s %s\n",
+ actor.Id.Human(),
+ actor.DisplayName(),
+ )
+ }
+
+ fmt.Printf("** Participants:\n")
+ for _, element := range b.Participants {
+ participant, err := backend.ResolveIdentityExcerpt(element)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf(": %s %s\n",
+ participant.Id.Human(),
+ participant.DisplayName(),
+ )
+ }
+ }
+
+ return nil
+}
+
// Finish the command flags transformation into the query.Query
func completeQuery() error {
for _, str := range lsStatusQuery {
@@ -294,5 +344,5 @@ func init() {
lsCmd.Flags().StringVarP(&lsSortDirection, "direction", "d", "asc",
"Select the sorting direction. Valid values are [asc,desc]")
lsCmd.Flags().StringVarP(&lsOutputFormat, "format", "f", "default",
- "Select the output formatting style. Valid values are [default, plain(text), json]")
+ "Select the output formatting style. Valid values are [default,plain,json,org-mode]")
}
diff --git a/commands/show.go b/commands/show.go
index 0bb3dc4a..2f4e46ed 100644
--- a/commands/show.go
+++ b/commands/show.go
@@ -1,22 +1,26 @@
package commands
import (
+ "encoding/json"
"errors"
"fmt"
"strings"
+ "github.com/spf13/cobra"
+
+ "github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
_select "github.com/MichaelMure/git-bug/commands/select"
"github.com/MichaelMure/git-bug/util/colors"
"github.com/MichaelMure/git-bug/util/interrupt"
- "github.com/spf13/cobra"
)
var (
- showFieldsQuery string
+ showFieldsQuery string
+ showOutputFormat string
)
-func runShowBug(cmd *cobra.Command, args []string) error {
+func runShowBug(_ *cobra.Command, args []string) error {
backend, err := cache.NewRepoCache(repo)
if err != nil {
return err
@@ -35,16 +39,16 @@ func runShowBug(cmd *cobra.Command, args []string) error {
return errors.New("invalid bug: no comment")
}
- firstComment := snapshot.Comments[0]
-
if showFieldsQuery != "" {
switch showFieldsQuery {
case "author":
- fmt.Printf("%s\n", firstComment.Author.DisplayName())
+ fmt.Printf("%s\n", snapshot.Author.DisplayName())
case "authorEmail":
- fmt.Printf("%s\n", firstComment.Author.Email())
+ fmt.Printf("%s\n", snapshot.Author.Email())
case "createTime":
- fmt.Printf("%s\n", firstComment.FormatTime())
+ fmt.Printf("%s\n", snapshot.CreateTime.String())
+ case "lastEdit":
+ fmt.Printf("%s\n", snapshot.EditTime().String())
case "humanId":
fmt.Printf("%s\n", snapshot.Id().Human())
case "id":
@@ -74,16 +78,33 @@ func runShowBug(cmd *cobra.Command, args []string) error {
return nil
}
+ switch showOutputFormat {
+ case "org-mode":
+ return showOrgmodeFormatter(snapshot)
+ case "json":
+ return showJsonFormatter(snapshot)
+ case "default":
+ return showDefaultFormatter(snapshot)
+ default:
+ return fmt.Errorf("unknown format %s", showOutputFormat)
+ }
+}
+
+func showDefaultFormatter(snapshot *bug.Snapshot) error {
// Header
- fmt.Printf("[%s] %s %s\n\n",
- colors.Yellow(snapshot.Status),
+ fmt.Printf("%s [%s] %s\n\n",
colors.Cyan(snapshot.Id().Human()),
+ colors.Yellow(snapshot.Status),
snapshot.Title,
)
- fmt.Printf("%s opened this issue %s\n\n",
- colors.Magenta(firstComment.Author.DisplayName()),
- firstComment.FormatTimeRel(),
+ fmt.Printf("%s opened this issue %s\n",
+ colors.Magenta(snapshot.Author.DisplayName()),
+ snapshot.CreateTime.String(),
+ )
+
+ fmt.Printf("This was last edited at %s\n\n",
+ snapshot.EditTime().String(),
)
// Labels
@@ -143,6 +164,151 @@ func runShowBug(cmd *cobra.Command, args []string) error {
return nil
}
+type JSONBugSnapshot struct {
+ Id string `json:"id"`
+ HumanId string `json:"human_id"`
+ CreateTime JSONTime `json:"create_time"`
+ EditTime JSONTime `json:"edit_time"`
+ Status string `json:"status"`
+ Labels []bug.Label `json:"labels"`
+ Title string `json:"title"`
+ Author JSONIdentity `json:"author"`
+ Actors []JSONIdentity `json:"actors"`
+ Participants []JSONIdentity `json:"participants"`
+ Comments []JSONComment `json:"comments"`
+}
+
+type JSONComment struct {
+ Id string `json:"id"`
+ HumanId string `json:"human_id"`
+ Author JSONIdentity `json:"author"`
+ Message string `json:"message"`
+}
+
+func NewJSONComment(comment bug.Comment) JSONComment {
+ return JSONComment{
+ Id: comment.Id().String(),
+ HumanId: comment.Id().Human(),
+ Author: NewJSONIdentity(comment.Author),
+ Message: comment.Message,
+ }
+}
+
+func showJsonFormatter(snapshot *bug.Snapshot) error {
+ jsonBug := JSONBugSnapshot{
+ Id: snapshot.Id().String(),
+ HumanId: snapshot.Id().Human(),
+ CreateTime: NewJSONTime(snapshot.CreateTime, 0),
+ EditTime: NewJSONTime(snapshot.EditTime(), 0),
+ Status: snapshot.Status.String(),
+ Labels: snapshot.Labels,
+ Title: snapshot.Title,
+ Author: NewJSONIdentity(snapshot.Author),
+ }
+
+ jsonBug.Actors = make([]JSONIdentity, len(snapshot.Actors))
+ for i, element := range snapshot.Actors {
+ jsonBug.Actors[i] = NewJSONIdentity(element)
+ }
+
+ jsonBug.Participants = make([]JSONIdentity, len(snapshot.Participants))
+ for i, element := range snapshot.Participants {
+ jsonBug.Participants[i] = NewJSONIdentity(element)
+ }
+
+ jsonBug.Comments = make([]JSONComment, len(snapshot.Comments))
+ for i, comment := range snapshot.Comments {
+ jsonBug.Comments[i] = NewJSONComment(comment)
+ }
+
+ jsonObject, _ := json.MarshalIndent(jsonBug, "", " ")
+ fmt.Printf("%s\n", jsonObject)
+
+ return nil
+}
+
+func showOrgmodeFormatter(snapshot *bug.Snapshot) error {
+ // Header
+ fmt.Printf("%s [%s] %s\n",
+ snapshot.Id().Human(),
+ snapshot.Status,
+ snapshot.Title,
+ )
+
+ fmt.Printf("* Author: %s\n",
+ snapshot.Author.DisplayName(),
+ )
+
+ fmt.Printf("* Creation Time: %s\n",
+ snapshot.CreateTime.String(),
+ )
+
+ fmt.Printf("* Last Edit: %s\n",
+ snapshot.EditTime().String(),
+ )
+
+ // Labels
+ var labels = make([]string, len(snapshot.Labels))
+ for i, label := range snapshot.Labels {
+ labels[i] = string(label)
+ }
+
+ fmt.Printf("* Labels:\n")
+ if len(labels) > 0 {
+ fmt.Printf("** %s\n",
+ strings.Join(labels, "\n** "),
+ )
+ }
+
+ // Actors
+ var actors = make([]string, len(snapshot.Actors))
+ for i, actor := range snapshot.Actors {
+ actors[i] = fmt.Sprintf("%s %s",
+ actor.Id().Human(),
+ actor.DisplayName(),
+ )
+ }
+
+ fmt.Printf("* Actors:\n** %s\n",
+ strings.Join(actors, "\n** "),
+ )
+
+ // Participants
+ var participants = make([]string, len(snapshot.Participants))
+ for i, participant := range snapshot.Participants {
+ participants[i] = fmt.Sprintf("%s %s",
+ participant.Id().Human(),
+ participant.DisplayName(),
+ )
+ }
+
+ fmt.Printf("* Participants:\n** %s\n",
+ strings.Join(participants, "\n** "),
+ )
+
+ fmt.Printf("* Comments:\n")
+
+ for i, comment := range snapshot.Comments {
+ var message string
+ fmt.Printf("** #%d %s\n",
+ i,
+ comment.Author.DisplayName(),
+ )
+
+ if comment.Message == "" {
+ message = "No description provided."
+ } else {
+ message = strings.ReplaceAll(comment.Message, "\n", "\n: ")
+ }
+
+ fmt.Printf(": %s\n",
+ message,
+ )
+ }
+
+ return nil
+}
+
var showCmd = &cobra.Command{
Use: "show [<id>]",
Short: "Display the details of a bug.",
@@ -152,6 +318,8 @@ var showCmd = &cobra.Command{
func init() {
RootCmd.AddCommand(showCmd)
- showCmd.Flags().StringVarP(&showFieldsQuery, "field", "f", "",
- "Select field to display. Valid values are [author,authorEmail,createTime,humanId,id,labels,shortId,status,title,actors,participants]")
+ showCmd.Flags().StringVarP(&showFieldsQuery, "field", "", "",
+ "Select field to display. Valid values are [author,authorEmail,createTime,lastEdit,humanId,id,labels,shortId,status,title,actors,participants]")
+ showCmd.Flags().StringVarP(&showOutputFormat, "format", "f", "default",
+ "Select the output formatting style. Valid values are [default,json,org-mode]")
}
diff --git a/commands/user_ls.go b/commands/user_ls.go
index 609ff5a4..b3fb32e6 100644
--- a/commands/user_ls.go
+++ b/commands/user_ls.go
@@ -1,15 +1,21 @@
package commands
import (
+ "encoding/json"
"fmt"
+ "github.com/spf13/cobra"
+
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/util/colors"
"github.com/MichaelMure/git-bug/util/interrupt"
- "github.com/spf13/cobra"
)
-func runUserLs(cmd *cobra.Command, args []string) error {
+var (
+ userLsOutputFormat string
+)
+
+func runUserLs(_ *cobra.Command, _ []string) error {
backend, err := cache.NewRepoCache(repo)
if err != nil {
return err
@@ -17,21 +23,48 @@ func runUserLs(cmd *cobra.Command, args []string) error {
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
- for _, id := range backend.AllIdentityIds() {
- i, err := backend.ResolveIdentityExcerpt(id)
+ ids := backend.AllIdentityIds()
+ var users []*cache.IdentityExcerpt
+ for _, id := range ids {
+ user, err := backend.ResolveIdentityExcerpt(id)
if err != nil {
return err
}
+ users = append(users, user)
+ }
+
+ switch userLsOutputFormat {
+ case "json":
+ return userLsJsonFormatter(users)
+ case "default":
+ return userLsDefaultFormatter(users)
+ default:
+ return fmt.Errorf("unknown format %s", userLsOutputFormat)
+ }
+}
+func userLsDefaultFormatter(users []*cache.IdentityExcerpt) error {
+ for _, user := range users {
fmt.Printf("%s %s\n",
- colors.Cyan(i.Id.Human()),
- i.DisplayName(),
+ colors.Cyan(user.Id.Human()),
+ user.DisplayName(),
)
}
return nil
}
+func userLsJsonFormatter(users []*cache.IdentityExcerpt) error {
+ jsonUsers := make([]JSONIdentity, len(users))
+ for i, user := range users {
+ jsonUsers[i] = NewJSONIdentityFromExcerpt(user)
+ }
+
+ jsonObject, _ := json.MarshalIndent(jsonUsers, "", " ")
+ fmt.Printf("%s\n", jsonObject)
+ return nil
+}
+
var userLsCmd = &cobra.Command{
Use: "ls",
Short: "List identities.",
@@ -42,4 +75,6 @@ var userLsCmd = &cobra.Command{
func init() {
userCmd.AddCommand(userLsCmd)
userLsCmd.Flags().SortFlags = false
+ userLsCmd.Flags().StringVarP(&userLsOutputFormat, "format", "f", "default",
+ "Select the output formatting style. Valid values are [default,json]")
}