From 6e2f68ef5ef7c71ec3dbaf80f5403911336024b3 Mon Sep 17 00:00:00 2001 From: Digital Studium Date: Thu, 9 Oct 2025 09:42:27 +0300 Subject: [PATCH 1/2] Read from stdin --- README.md | 5 ++--- main.go | 38 ++++++++++++++++++++++++++++++++++++-- templates_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d89c64c..2da9f60 100644 --- a/README.md +++ b/README.md @@ -243,7 +243,7 @@ To use `helmfmt` as a pre-commit hook, add the following to your `.pre-commit-co ```yaml repos: - repo: https://github.com/digitalstudium/helmfmt - rev: v0.2.0 + rev: v0.3.0 hooks: - id: helmfmt ``` @@ -258,7 +258,6 @@ Add these lines to your `settings.json`: "formatter": { "external": { "command": "helmfmt", - "arguments": ["--files", "{buffer_path}", "--stdout"] } } } @@ -277,7 +276,7 @@ Add these lines to your settings: ```json "advancedLocalFormatters.formatters": [ { - "command": ["helmfmt", "--files", "$absoluteFilePath", "--stdout"], + "command": ["helmfmt"], "languages": ["helm"] } ], diff --git a/main.go b/main.go index ecaad79..e1d64fe 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "io" "io/fs" "os" "path/filepath" @@ -85,7 +86,7 @@ func run() int { RunE: func(cmd *cobra.Command, args []string) error { // Apply rule overrides from flags for _, rule := range disableRules { - if _, exists := config.Rules.Indent[rule]; exists { // Updated access pattern + if _, exists := config.Rules.Indent[rule]; exists { ruleConfig := config.Rules.Indent[rule] ruleConfig.Disabled = true config.Rules.Indent[rule] = ruleConfig @@ -95,7 +96,7 @@ func run() int { } for _, rule := range enableRules { - if _, exists := config.Rules.Indent[rule]; exists { // Updated access pattern + if _, exists := config.Rules.Indent[rule]; exists { ruleConfig := config.Rules.Indent[rule] ruleConfig.Disabled = false config.Rules.Indent[rule] = ruleConfig @@ -104,6 +105,18 @@ func run() int { } } + // Check if stdin is being piped + stat, _ := os.Stdin.Stat() + stdinPiped := (stat.Mode() & os.ModeCharDevice) == 0 + + if stdinPiped { + // Process from stdin + if len(args) > 0 { + return fmt.Errorf("cannot specify files when reading from stdin") + } + return processStdin(config) + } + if files { // Files mode if len(args) == 0 { @@ -150,6 +163,27 @@ func run() int { return 0 } +func processStdin(config *Config) error { + // Read all input from stdin + input, err := io.ReadAll(os.Stdin) + if err != nil { + return fmt.Errorf("error reading from stdin: %w", err) + } + + orig := string(input) + + // Validate syntax + if err := validateTemplateSyntax(orig); err != nil { + return fmt.Errorf("invalid syntax: %w", err) + } + + // Format and output to stdout + formatted := ensureTrailingNewline(formatIndentation(orig, config, "")) + fmt.Print(formatted) + + return nil +} + func collectFiles(root string, config *Config) ([]string, error) { var out []string err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { diff --git a/templates_test.go b/templates_test.go index 60ea37a..01b5c37 100644 --- a/templates_test.go +++ b/templates_test.go @@ -1,6 +1,8 @@ package main import ( + "bytes" + "io" "os" "path/filepath" "testing" @@ -73,7 +75,7 @@ func TestFormatIndentationFromTemplates(t *testing.T) { t.Fatalf("Failed to read expected file %s: %v", expectedPath, err) } - // Format using the input file path for exclusion matching + // Test 1: Direct formatting (file mode) result := formatIndentation(string(inputContent), config, testCase.InputFile) result = ensureTrailingNewline(result) expected := string(expectedContent) @@ -83,6 +85,49 @@ func TestFormatIndentationFromTemplates(t *testing.T) { t.Errorf("Test '%s' failed\nInput file: %s\nExpected file: %s\nExpected:\n%s\n\nGot:\n%s", testCase.Name, testCase.InputFile, testCase.ExpectedFile, expected, result) } + + // Test 2: stdin mode (skip if test uses file exclusion patterns) + hasExcludePatterns := false + if testCase.Config != nil && testCase.Config.Rules.Indent != nil { + for _, ruleConfig := range testCase.Config.Rules.Indent { + if len(ruleConfig.Exclude) > 0 { + hasExcludePatterns = true + break + } + } + } + + if !hasExcludePatterns { + t.Run("stdin", func(t *testing.T) { + // Setup stdin/stdout pipes + oldStdin, oldStdout := os.Stdin, os.Stdout + r, w, _ := os.Pipe() + os.Stdin = r + + rOut, wOut, _ := os.Pipe() + os.Stdout = wOut + + // Write input and process + go func() { + w.Write(inputContent) + w.Close() + }() + + processStdin(config) + + wOut.Close() + os.Stdin, os.Stdout = oldStdin, oldStdout + + // Read output + var buf bytes.Buffer + io.Copy(&buf, rOut) + + if buf.String() != expected { + t.Errorf("Test '%s' failed (stdin)\nExpected:\n%s\n\nGot:\n%s", + testCase.Name, expected, buf.String()) + } + }) + } }) } } From 30b719df690ffe1ce1c1ddf39854159a4f31582b Mon Sep 17 00:00:00 2001 From: Digital Studium Date: Thu, 9 Oct 2025 09:45:19 +0300 Subject: [PATCH 2/2] Bump version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0ea3a94..0d91a54 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.3.0