Skip to content
Open
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
18 changes: 12 additions & 6 deletions cmd/base64.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ Input can be a string argument or piped from stdin.`,
if err != nil {
return err
}
fmt.Print(decoded)
} else {
// Encode to base64
encoded := base64.Encode(data)
fmt.Print(encoded)
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), decoded)
}
_, err = fmt.Fprint(cmd.OutOrStdout(), decoded)
return err
}

return nil
// Encode to base64
encoded := base64.Encode(data)
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), encoded)
}
_, err = fmt.Fprint(cmd.OutOrStdout(), encoded)
return err
},
}

Expand Down
7 changes: 7 additions & 0 deletions cmd/count.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ in a formatted table. Input can be a string argument or piped from stdin.`,
if err != nil {
return err
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), map[string]int{
"characters": stats.Characters,
"spaces": stats.Spaces,
"words": stats.Words,
})
}

_, err = fmt.Fprintln(cmd.OutOrStdout(), table.New().Border(lipgloss.NormalBorder()).
Row("Characters", strconv.Itoa(stats.Characters)).
Expand Down
11 changes: 10 additions & 1 deletion cmd/cssfmt.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"bytes"
"strings"

tea "github.com/charmbracelet/bubbletea"
Expand Down Expand Up @@ -85,10 +86,18 @@ custom spacing. Input can be a string argument or piped from stdin.`,
}

inputStr := string(data)
err = cssformat.Format(strings.NewReader(inputStr), cmd.OutOrStdout())
var buffer bytes.Buffer
output := cmd.OutOrStdout()
if outputJSON {
output = &buffer
}
err = cssformat.Format(strings.NewReader(inputStr), output)
if err != nil {
return cmderror.FormatParseError("cssfmt", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), buffer.String())
}

return nil
},
Expand Down
11 changes: 10 additions & 1 deletion cmd/cssmin.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"bytes"
"strings"

"github.com/client9/csstool"
Expand Down Expand Up @@ -41,10 +42,18 @@ Input can be a string argument or piped from stdin.`,
}

inputStr := string(data)
err = cssformat.Format(strings.NewReader(inputStr), cmd.OutOrStdout())
var buffer bytes.Buffer
output := cmd.OutOrStdout()
if outputJSON {
output = &buffer
}
err = cssformat.Format(strings.NewReader(inputStr), output)
if err != nil {
return cmderror.FormatParseError("cssmin", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), buffer.String())
}

return nil
},
Expand Down
11 changes: 10 additions & 1 deletion cmd/csv2md.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"encoding/csv"
"fmt"
"strings"

"github.com/skatkov/devtui/internal/cmderror"
Expand Down Expand Up @@ -53,7 +54,15 @@ and --header to add a main heading (h1) to the output.`,
return cmderror.FormatParseError("csv2md", inputStr, err)
}

csv2md.Print(csv2md.Convert(csv2mdHeader, records, csv2mdAlignColumns))
rows := csv2md.Convert(csv2mdHeader, records, csv2mdAlignColumns)
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), strings.Join(rows, "\n"))
}
for _, row := range rows {
if _, err := fmt.Fprintln(cmd.OutOrStdout(), row); err != nil {
return err
}
}

return nil
},
Expand Down
3 changes: 3 additions & 0 deletions cmd/gqlquery.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ or piped from stdin.`,
f := formatter.NewFormatter(&buf, opts...)
f.FormatQueryDocument(query)
result := buf.String()
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

// Write the result to stdout
_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
Expand Down
12 changes: 7 additions & 5 deletions cmd/iban.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ Use the --formatted flag to output the IBAN in paper format with spaces.`,
}

// Format output based on flag
output := generatedIban
if ibanFormatted {
fmt.Println(iban.PaperFormat(generatedIban))
} else {
fmt.Println(generatedIban)
output = iban.PaperFormat(generatedIban)
}

return nil
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), output)
}
_, err = fmt.Fprintln(cmd.OutOrStdout(), output)
return err
},
}

Expand Down
3 changes: 3 additions & 0 deletions cmd/json2toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ results in an interactive terminal interface.`,
if err != nil {
return cmderror.FormatParseError("json2toml", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions cmd/json2toon.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ reduced token usage (typically 30-60% fewer tokens than JSON).`,
if err != nil {
return cmderror.FormatParseError("json2toon", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

_, err = fmt.Fprint(cmd.OutOrStdout(), result)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions cmd/json2xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Input can be a string argument or piped from stdin.`,
if err != nil {
return cmderror.FormatParseError("json2xml", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions cmd/json2yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Input can be a string argument or piped from stdin.`,
if err != nil {
return cmderror.FormatParseError("json2yaml", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions cmd/json_output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cmd

import (
"encoding/json"
"io"
)

var outputJSON bool

func writeJSONValue(out io.Writer, value any) error {
encoder := json.NewEncoder(out)
encoder.SetEscapeHTML(false)
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The writeJSONValue function uses json.NewEncoder which produces compact (non-indented) JSON output. However, the uuiddecode and numbers commands previously used json.MarshalIndent with 2-space indentation. This creates an inconsistency where these two commands now produce compact JSON while they previously produced indented JSON.

Consider either:

  1. Using encoder.SetIndent("", " ") in writeJSONValue to produce indented output consistently across all commands, or
  2. Updating uuiddecode.go and numbers.go to also use writeJSONValue so all commands have the same compact JSON format

Option 1 is generally preferred for CLI tools as it makes the JSON output more human-readable.

Suggested change
encoder.SetEscapeHTML(false)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", " ")

Copilot uses AI. Check for mistakes.
return encoder.Encode(value)
}
1 change: 0 additions & 1 deletion cmd/jsonfmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ The output is always valid, properly indented JSON.`,
// }

result := json.FormatJSON(string(data))

_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
if err != nil {
return err
Expand Down
6 changes: 2 additions & 4 deletions cmd/numbers.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
return err
}

if numbersJSONOutput {
if outputJSON {
bytes, err := json.MarshalIndent(result, "", " ")
if err != nil {
return err
Expand All @@ -65,13 +65,11 @@
},
}

var (

Check failure on line 68 in cmd/numbers.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gofumpt)

Check failure on line 68 in cmd/numbers.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gofumpt)
numbersBase int
numbersJSONOutput bool
numbersBase int
)

func init() {
rootCmd.AddCommand(numbersCmd)
numbersCmd.Flags().IntVarP(&numbersBase, "base", "b", 10, "input number base (2, 8, 10, 16)")
numbersCmd.Flags().BoolVar(&numbersJSONOutput, "json", false, "output conversions as JSON")
}
4 changes: 2 additions & 2 deletions cmd/numbers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func TestNumbersCmd(t *testing.T) {
numbersBase = 10
numbersJSONOutput = false
outputJSON = false

cmd := GetRootCmd()
buf := new(bytes.Buffer)
Expand All @@ -33,7 +33,7 @@ func TestNumbersCmd(t *testing.T) {

func TestNumbersCmdJSON(t *testing.T) {
numbersBase = 10
numbersJSONOutput = false
outputJSON = false

cmd := GetRootCmd()
buf := new(bytes.Buffer)
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,5 @@ func GetRootCmd() *cobra.Command {
func init() {
// fang.Execute automatically adds --version flag
// We configure it via fang.WithVersion() in Execute()
rootCmd.PersistentFlags().BoolVar(&outputJSON, "json", false, "output as JSON")
}
3 changes: 3 additions & 0 deletions cmd/toml2yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Input can be a string argument or piped from stdin.`,
if err != nil {
return cmderror.FormatParseError("toml2yaml", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions cmd/tomlfmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ in an interactive terminal interface.`,
if err != nil {
return cmderror.FormatParseError("tomlfmt", inputStr, err)
}
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), result)
}

_, err = fmt.Fprintln(cmd.OutOrStdout(), result)
if err != nil {
Expand Down
11 changes: 10 additions & 1 deletion cmd/tsv2md.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"encoding/csv"
"fmt"
"strings"

"github.com/skatkov/devtui/internal/cmderror"
Expand Down Expand Up @@ -56,7 +57,15 @@ and --header to add a main heading (h1) to the output.`,
return cmderror.FormatParseError("tsv2md", inputStr, err)
}

csv2md.Print(csv2md.Convert(tsv2mdHeader, records, tsv2mdAlignColumns))
rows := csv2md.Convert(tsv2mdHeader, records, tsv2mdAlignColumns)
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), strings.Join(rows, "\n"))
}
for _, row := range rows {
if _, err := fmt.Fprintln(cmd.OutOrStdout(), row); err != nil {
return err
}
}

return nil
},
Expand Down
12 changes: 10 additions & 2 deletions cmd/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,18 @@ Input can be a string argument or piped from stdin.`,
}
}

if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), uniqueURLs)
}

// Output results
if len(uniqueURLs) > 0 {
fmt.Print(strings.Join(uniqueURLs, "\n"))
fmt.Print("\n")
_, err = fmt.Fprint(cmd.OutOrStdout(), strings.Join(uniqueURLs, "\n"))
if err != nil {
return err
}
_, err = fmt.Fprint(cmd.OutOrStdout(), "\n")
return err
}

return nil
Expand Down
5 changes: 1 addition & 4 deletions cmd/uuiddecode.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Input can be provided as an argument or piped from stdin.`,
}

fields := uuidutil.Decode(parsed)
if uuiddecodeJSONOutput {
if outputJSON {
payload := uuidDecodeJSON{
UUID: parsed.String(),
Fields: fields,
Expand All @@ -73,9 +73,6 @@ Input can be provided as an argument or piped from stdin.`,
},
}

var uuiddecodeJSONOutput bool

func init() {
rootCmd.AddCommand(uuiddecodeCmd)
uuiddecodeCmd.Flags().BoolVar(&uuiddecodeJSONOutput, "json", false, "output decoded fields as JSON")
}
6 changes: 3 additions & 3 deletions cmd/uuiddecode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func TestUUIDDecodeCmd(t *testing.T) {
uuiddecodeJSONOutput = false
outputJSON = false
input := "4326ff5f-774d-4506-a18c-4bc50c761863"

cmd := GetRootCmd()
Expand All @@ -33,7 +33,7 @@ func TestUUIDDecodeCmd(t *testing.T) {
}

func TestUUIDDecodeCmdJSON(t *testing.T) {
uuiddecodeJSONOutput = false
outputJSON = false
input := "4326ff5f-774d-4506-a18c-4bc50c761863"

cmd := GetRootCmd()
Expand Down Expand Up @@ -61,7 +61,7 @@ func TestUUIDDecodeCmdJSON(t *testing.T) {
}

func TestUUIDDecodeCmdNoInput(t *testing.T) {
uuiddecodeJSONOutput = false
outputJSON = false
cmd := GetRootCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
Expand Down
10 changes: 7 additions & 3 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ var versionCmd = &cobra.Command{
Use: "version",
Short: "Print version information",
Long: "Print version, commit and date of release for this software",
RunE: func(_ *cobra.Command, _ []string) error {
fmt.Print("devtui version " + GetVersionShort())
return nil
RunE: func(cmd *cobra.Command, _ []string) error {
output := "devtui version " + GetVersionShort()
if outputJSON {
return writeJSONValue(cmd.OutOrStdout(), output)
}
_, err := fmt.Fprint(cmd.OutOrStdout(), output)
return err
},
}

Expand Down
Loading
Loading