Skip to content

Commit

Permalink
feat: add --output formats (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
notnmeyer authored Jul 17, 2024
1 parent 106fe74 commit b6af2e2
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 44 deletions.
15 changes: 13 additions & 2 deletions cmd/tsk/tsk.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"regexp"
"strings"

output "github.com/notnmeyer/tsk/internal/outputformat"
"github.com/notnmeyer/tsk/internal/task"

flag "github.com/spf13/pflag"
)

Expand All @@ -21,11 +23,14 @@ type Options struct {
filter string
init bool
listTasks bool
output string
pure bool
taskFile string
tasks []string
}

const defaultOutputFormat = output.OutputFormat(output.Text)

func init() {
// TOML 1.1 features are behind a flag until officially released
os.Setenv("BURNTSUSHI_TOML_110", "")
Expand All @@ -35,8 +40,9 @@ func main() {
opts := Options{}
flag.BoolVarP(&opts.displayVersion, "version", "V", false, "display tsk version")
flag.StringVarP(&opts.filter, "filter", "F", ".*", "regex filter for --list")
flag.BoolVarP(&opts.listTasks, "list", "l", false, "list tasks")
flag.BoolVar(&opts.init, "init", false, "create a tasks.toml file in $PWD")
flag.BoolVarP(&opts.listTasks, "list", "l", false, "list tasks")
flag.StringVarP(&opts.output, "output", "o", "text", fmt.Sprintf("output format (applies only to --list) (one of: %s, %s)", string(output.Text), string(output.Markdown)))
flag.BoolVarP(&opts.pure, "pure", "", false, "don't inherit the parent env")
flag.StringVarP(&opts.taskFile, "file", "f", "tasks.toml", "taskfile to use")
flag.BoolVarP(&help, "help", "h", false, "")
Expand All @@ -63,6 +69,11 @@ func main() {
return
}

if !output.IsValid(opts.output) {
fmt.Printf("--output must one of: %s\n", output.String())
os.Exit(1)
}

// check if there are args passed after "--".
// - if "--" is not present ArgsLenAtDash() returns -1.
// - dash position 0 would be invocations like, `tsk -l -- foo`
Expand All @@ -87,7 +98,7 @@ func main() {
}

if opts.listTasks {
exec.ListTasksFromTaskFile(regexp.MustCompile(opts.filter))
exec.ListTasksFromTaskFile(regexp.MustCompile(opts.filter), output.OutputFormat(opts.output))
return
}

Expand Down
25 changes: 25 additions & 0 deletions internal/outputformat/outputformat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package outputformat

import (
"fmt"
)

type OutputFormat string

const (
Markdown OutputFormat = "md"
Text OutputFormat = "text"
TOML OutputFormat = "toml"
)

func String() string {
return fmt.Sprintf("%s, %s, %s", string(Markdown), string(Text), string(TOML))
}

func IsValid(format string) bool {
switch format {
case string(Markdown), string(Text), string(TOML):
return true
}
return false
}
17 changes: 17 additions & 0 deletions internal/outputformat/outputformat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package outputformat

import (
"testing"
)

func TestIsValid(t *testing.T) {
want, got := true, IsValid("toml")
if want != got {
t.Errorf("got %t, wanted %t\n", got, want)
}

want, got = false, IsValid("XML")
if want != got {
t.Errorf("got %t, wanted %t\n", got, want)
}
}
98 changes: 56 additions & 42 deletions internal/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"strings"
"sync"

output "github.com/notnmeyer/tsk/internal/outputformat"

"github.com/BurntSushi/toml"
"mvdan.cc/sh/v3/expand"
"mvdan.cc/sh/v3/interp"
Expand Down Expand Up @@ -167,62 +169,74 @@ func (exec *Executor) runCommand(cmd string, dir string, env []string) error {
return nil
}

func (exec *Executor) ListTasksFromTaskFile(regex *regexp.Regexp) {
func (exec *Executor) ListTasksFromTaskFile(regex *regexp.Regexp, format output.OutputFormat) {
tasks := filterTasks(&exec.Config.Tasks, regex)

// gaaaah, i like the end result but i hate this
indent := " "
for name, t := range tasks {
// name
fmt.Printf("%s:\n", name)

// description
if t.Description != "" {
fmt.Printf("%sdescription:\n", indent)
trimmed := strings.TrimSpace(t.Description)
for _, line := range strings.Split(trimmed, "\n") {
fmt.Printf("%s%s\n", strings.Repeat(indent, 2), line)

switch format {
case output.Markdown:
for name, t := range tasks {
fmt.Printf("## %s\n", name)
if len(t.Cmds) > 0 {
for _, cmd := range t.Cmds {
fmt.Printf("%s- %s\n", indent, cmd)
}
} else {
fmt.Printf("%s- %s/%s\n", indent, exec.Config.ScriptDir, name)
}
}
case output.TOML:
toml.NewEncoder(os.Stdout).Encode(tasks)
case output.Text:
for name, t := range tasks {
// name
fmt.Printf("%s:\n", name)

// description
if t.Description != "" {
fmt.Printf("%sdescription:\n", indent)
trimmed := strings.TrimSpace(t.Description)
for _, line := range strings.Split(trimmed, "\n") {
fmt.Printf("%s%s\n", strings.Repeat(indent, 2), line)
}
}

// deps
if len(t.Deps) > 0 {
fmt.Printf("%sdeps:\n", indent)
for _, dep := range t.Deps {
fmt.Printf("%s%v\n", indent+indent, dep)
// deps
if len(t.Deps) > 0 {
fmt.Printf("%sdeps:\n", indent)
for _, dep := range t.Deps {
fmt.Printf("%s%v\n", indent+indent, dep)
}
}
}

// cmds
if len(t.Cmds) > 0 {
// cmds
fmt.Printf("%scommands:\n", indent)
for _, cmd := range t.Cmds {
fmt.Printf("%s\n", indent+indent+cmd)
if len(t.Cmds) > 0 {
for _, cmd := range t.Cmds {
fmt.Printf("%s\n", indent+indent+cmd)
}
} else {
fmt.Printf("%s%s/%s\n", indent+indent, exec.Config.ScriptDir, name)
}
} else {
fmt.Printf("%s# will run `%s/%s`\n", indent, exec.Config.ScriptDir, name)
}

// dir
if t.Dir != "" {
fmt.Printf("%sdir: %s\n", indent, t.Dir)
}
// dir
if t.Dir != "" {
fmt.Printf("%sdir: %s\n", indent, t.Dir)
}

// dotenv
if t.DotEnv != "" {
fmt.Printf("%sdotenv: %s\n", indent, t.DotEnv)
}
// dotenv
if t.DotEnv != "" {
fmt.Printf("%sdotenv: %s\n", indent, t.DotEnv)
}

// pure
if t.Pure == true {
fmt.Printf("%spure: %t\n", indent, t.Pure)
}
// pure
if t.Pure == true {
fmt.Printf("%spure: %t\n", indent, t.Pure)
}

fmt.Println("")
fmt.Println("")
}
}

// pure toml representation. simple but includes blank task attributes.
// toml.NewEncoder(os.Stdout).Encode(tasks)
}

func filterTasks(tasks *map[string]Task, regex *regexp.Regexp) map[string]Task {
Expand Down

0 comments on commit b6af2e2

Please sign in to comment.