Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add json to list cmd #379

Merged
merged 6 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 60 additions & 23 deletions internal/cmd/list.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
package cmd

import (
"bytes"
"encoding/json"
"path/filepath"
"sort"
"strings"

"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/go-gh/pkg/jsonpretty"
"github.com/cli/go-gh/pkg/tableprinter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/stateful/runme/internal/project"
"github.com/stateful/runme/internal/shell"
)

type row struct {
Name string `json:"name"`
File string `json:"file"`
FirstCommand string `json:"first_command"`
Description string `json:"description"`
Named bool `json:"named"`
}

func listCmd() *cobra.Command {
var formatJSON bool
cmd := cobra.Command{
Use: "list [search]",
Aliases: []string{"ls"},
Expand Down Expand Up @@ -49,43 +61,68 @@ func listCmd() *cobra.Command {

// TODO: this should be taken from cmd.
io := iostreams.System()
table := tableprinter.New(io.Out, io.IsStdoutTTY(), io.TerminalWidth())

// table header
table.AddField(strings.ToUpper("Name"))
table.AddField(strings.ToUpper("File"))
table.AddField(strings.ToUpper("First Command"))
table.AddField(strings.ToUpper("Description"))
table.AddField(strings.ToUpper("Named"))
table.EndRow()

var rows []row
for _, fileBlock := range blocks {
block := fileBlock.Block

lines := block.Lines()

isNamedField := "Yes"
if block.IsUnnamed() {
isNamedField = "No"
r := row{
Name: block.Name(),
File: fileBlock.File,
FirstCommand: shell.TryGetNonCommentLine(lines),
Description: block.Intro(),
Named: !block.IsUnnamed(),
}

table.AddField(block.Name())
table.AddField(fileBlock.File)
table.AddField(shell.TryGetNonCommentLine(lines))
table.AddField(block.Intro())
table.AddField(isNamedField)
table.EndRow()
rows = append(rows, r)
}
if !formatJSON {
return displayTable(io, rows)
}

return errors.Wrap(table.Render(), "failed to render")
return displayJSON(io, rows)
},
}

cmd.PersistentFlags().BoolVar(&formatJSON, "json", false, "This flag tells the list command to print the output in json")
setDefaultFlags(&cmd)

return &cmd
}

func displayTable(io *iostreams.IOStreams, rows []row) error {
table := tableprinter.New(io.Out, io.IsStdoutTTY(), io.TerminalWidth())

// table header
table.AddField(strings.ToUpper("Name"))
table.AddField(strings.ToUpper("File"))
table.AddField(strings.ToUpper("First Command"))
table.AddField(strings.ToUpper("Description"))
table.AddField(strings.ToUpper("Named"))
table.EndRow()

for _, row := range rows {
named := "Yes"
if !row.Named {
named = "No"
}
table.AddField(row.Name)
table.AddField(row.File)
table.AddField(row.FirstCommand)
table.AddField(row.Description)
table.AddField(named)
table.EndRow()
}

return errors.Wrap(table.Render(), "failed to render")
}

func displayJSON(io *iostreams.IOStreams, rows []row) error {
by, err := json.Marshal(&rows)
if err != nil {
return err
}
return jsonpretty.Format(io.Out, bytes.NewReader(by), " ", false)
}

// sort blocks in ascending nested order
func sortBlocks(blocks []project.CodeBlock) (res []project.CodeBlock) {
blocksByFile := make(map[string][]project.CodeBlock, 0)
Expand Down
28 changes: 28 additions & 0 deletions testdata/script/basic.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ exec runme ls
cmp stdout golden-list.txt
! stderr .

exec runme ls --json
cmp stdout golden-list-json.txt
! stderr .

exec runme ls --allow-unnamed=true
cmp stdout golden-list-allow-unnamed.txt
! stderr .
Expand Down Expand Up @@ -148,3 +152,27 @@ hello-js README.md console.log("Hello, runme, from javascript!") It can even run
hello-js-cat README.md console.log("Hello, runme, from javascript!") And it can even run a cell with a custom interpreter. Yes
tempdir README.md temp_dir=$(mktemp -d -t "runme-XXXXXXX") It works with cd, pushd, and similar because all lines are executed as a single script. No
package-main README.md package main It can also execute a snippet of Go code. No
-- golden-list-json.txt --
[
{
"name": "echo",
"file": "README.md",
"first_command": "echo \"Hello, runme!\"",
"description": "With {name=hello} you can annotate it and give it a nice name.",
"named": true
},
{
"name": "hello-js",
"file": "README.md",
"first_command": "console.log(\"Hello, runme, from javascript!\")",
"description": "It can even run scripting languages.",
"named": true
},
{
"name": "hello-js-cat",
"file": "README.md",
"first_command": "console.log(\"Hello, runme, from javascript!\")",
"description": "And it can even run a cell with a custom interpreter.",
"named": true
}
]
Loading