Skip to content

Commit a01992d

Browse files
claude[bot]claude
authored andcommitted
Enhance format command with stdin/stdout support and remove dry-run
- Remove dry-run functionality from format command - Implement stdin/stdout behavior when no files provided - Support in-place formatting when files are specified - Fix formatter to properly handle trailing newlines - Update test files to reflect new stdin/stdout behavior - Remove unused lineno field from formatter Co-Authored-By: Brandon Bloom <[email protected]> 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 80cf9ee commit a01992d

6 files changed

Lines changed: 40 additions & 48 deletions

File tree

internal/cli/format.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ import (
1212
)
1313

1414
func init() {
15-
formatCmd.Flags().BoolVarP(&formatFlags.DryRun, "dry-run", "n", false, "dry run")
1615
rootCmd.AddCommand(formatCmd)
1716
}
1817

19-
var formatFlags struct {
20-
DryRun bool
21-
}
22-
2318
var formatCmd = &cobra.Command{
24-
Use: "format <transcripts...>",
19+
Use: "format [transcripts...]",
2520
Short: "Formats transcript files",
2621
Long: `Formats transcript files by normalizing comments, blank lines,
2722
trailing whitespace (except in command output), trailing newline,
2823
and special directive syntax.
2924
30-
Transcript files are formatted in-place, unless --dry-run is specified. In a dry
31-
run, the formatted output is printed to stdout instead.
25+
If no files are provided, reads from stdin and writes to stdout.
26+
If files are provided, formats them in-place.
3227
`,
3328
RunE: func(cmd *cobra.Command, args []string) error {
3429
ctx := cmd.Context()
30+
if len(args) == 0 {
31+
// Read from stdin, write to stdout
32+
return formatStdin(ctx)
33+
}
34+
// Format files in-place
3535
for _, filename := range args {
3636
if err := formatFile(ctx, filename); err != nil {
3737
return fmt.Errorf("formatting %q: %w", filename, err)
@@ -41,6 +41,16 @@ run, the formatted output is printed to stdout instead.
4141
},
4242
}
4343

44+
func formatStdin(ctx context.Context) error {
45+
formatter := &core.Formatter{}
46+
transcript, err := formatter.FormatTranscript(ctx, os.Stdin)
47+
if err != nil {
48+
return err
49+
}
50+
_, err = io.Copy(os.Stdout, transcript)
51+
return err
52+
}
53+
4454
func formatFile(ctx context.Context, filename string) error {
4555
f, err := os.Open(filename)
4656
if err != nil {
@@ -53,9 +63,5 @@ func formatFile(ctx context.Context, filename string) error {
5363
if err != nil {
5464
return err
5565
}
56-
if formatFlags.DryRun {
57-
_, err := io.Copy(os.Stdout, transcript)
58-
return err
59-
}
6066
return atomic.WriteFile(filename, transcript)
61-
}
67+
}

internal/core/formatter.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,37 @@ package core
33
import (
44
"bytes"
55
"context"
6-
"fmt"
76
"io"
87
"strconv"
98
"strings"
109
)
1110

1211
type Formatter struct {
13-
buf *bytes.Buffer
14-
lineno int
12+
buf *bytes.Buffer
1513
}
1614

1715
func (f *Formatter) FormatTranscript(ctx context.Context, r io.Reader) (transcript *bytes.Buffer, err error) {
1816
f.buf = &bytes.Buffer{}
19-
17+
2018
// Use the regular interpreter with the formatter as handler.
2119
interp := &Interpreter{
2220
Handler: f,
2321
}
2422
if err := interp.ExecTranscript(ctx, r); err != nil {
2523
return nil, err
2624
}
27-
25+
2826
// Ensure file ends with exactly one newline
2927
content := f.buf.Bytes()
3028
content = bytes.TrimRight(content, "\n")
3129
if len(content) > 0 {
3230
content = append(content, '\n')
3331
}
34-
32+
3533
return bytes.NewBuffer(content), nil
3634
}
3735

3836
func (f *Formatter) HandleComment(ctx context.Context, text string) error {
39-
f.lineno++
40-
4137
// Normalize comments and blank lines
4238
trimmed := strings.TrimSpace(text)
4339
if trimmed == "" {
@@ -53,56 +49,46 @@ func (f *Formatter) HandleComment(ctx context.Context, text string) error {
5349
f.buf.WriteString("# " + comment + "\n")
5450
}
5551
}
56-
52+
5753
return nil
5854
}
5955

6056
func (f *Formatter) HandleRun(ctx context.Context, command string) error {
61-
f.lineno++
62-
6357
// Write the command with normalized formatting
6458
f.buf.WriteString("$ " + strings.TrimSpace(command) + "\n")
65-
59+
6660
return nil
6761
}
6862

6963
func (f *Formatter) HandleOutput(ctx context.Context, fd int, line string) error {
70-
f.lineno++
71-
7264
// Output lines preserve their exact content (including whitespace)
7365
f.buf.WriteString(strconv.Itoa(fd) + " " + line + "\n")
74-
66+
7567
return nil
7668
}
7769

7870
func (f *Formatter) HandleFileOutput(ctx context.Context, fd int, filepath string) error {
79-
f.lineno++
80-
8171
// File output references with normalized formatting
8272
f.buf.WriteString(strconv.Itoa(fd) + "< " + strings.TrimSpace(filepath) + "\n")
83-
73+
8474
return nil
8575
}
8676

8777
func (f *Formatter) HandleNoNewline(ctx context.Context, fd int) error {
88-
f.lineno++
89-
9078
// No-newline directive with normalized formatting
9179
f.buf.WriteString("% no-newline\n")
92-
80+
9381
return nil
9482
}
9583

9684
func (f *Formatter) HandleExitCode(ctx context.Context, exitCode int) error {
97-
f.lineno++
98-
9985
// Exit code with normalized formatting
10086
f.buf.WriteString("? " + strconv.Itoa(exitCode) + "\n")
101-
87+
10288
return nil
10389
}
10490

10591
func (f *Formatter) HandleEnd(ctx context.Context) error {
10692
// No special handling needed for end
10793
return nil
108-
}
94+
}

internal/core/updater.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ func (upr *Updater) flushCurrentCommand(ctx context.Context) error {
3535
if upr.currentCommand == "" {
3636
return nil // No command to flush
3737
}
38-
38+
3939
// Set up recorder with file references for this command
4040
upr.rec.SetPreferredFiles(upr.fileRefs)
41-
41+
4242
// Execute the command
4343
if _, err := upr.rec.RunCommand(ctx, upr.currentCommand); err != nil {
4444
return err
4545
}
46-
46+
4747
// Clear the buffer
4848
upr.fileRefs = nil
4949
upr.currentCommand = ""
50-
50+
5151
return nil
5252
}
5353

@@ -66,7 +66,7 @@ func (upr *Updater) HandleRun(ctx context.Context, command string) error {
6666
if err := upr.flushCurrentCommand(ctx); err != nil {
6767
return err
6868
}
69-
69+
7070
// Buffer this command - don't execute it yet
7171
upr.currentCommand = command
7272
return nil
@@ -97,4 +97,3 @@ func (upr *Updater) HandleEnd(ctx context.Context) error {
9797
// Flush any remaining command at the end
9898
return upr.flushCurrentCommand(ctx)
9999
}
100-

tests/format-basic.cmdt.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
$ echo hello
44
1 hello
55

6+
# Multiple blank lines should be normalized
67

78
$ echo world
89
1 world

tests/format-command.cmdt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ $ false
1313
? 1
1414
EOF
1515

16-
# Test dry-run format
17-
$ transcript format --dry-run unformatted.cmdt
16+
# Test stdin/stdout formatting
17+
$ transcript format < unformatted.cmdt
1818
1 # comment without space
1919
1
2020
1 $ echo hello

tests/format-simple.cmdt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ $ echo test
99
? 0
1010
EOF
1111

12-
# Format it and show the result
13-
$ transcript format --dry-run test.cmdt
12+
# Format it using stdin/stdout
13+
$ transcript format < test.cmdt
1414
1 # comment
1515
1 $ echo test
1616
1 1 test

0 commit comments

Comments
 (0)