1+ package core
2+
3+ import (
4+ "bytes"
5+ "context"
6+ "fmt"
7+ "io"
8+ "strconv"
9+ "strings"
10+ )
11+
12+ type Formatter struct {
13+ buf * bytes.Buffer
14+ lineno int
15+ }
16+
17+ func (f * Formatter ) FormatTranscript (ctx context.Context , r io.Reader ) (transcript * bytes.Buffer , err error ) {
18+ f .buf = & bytes.Buffer {}
19+
20+ // Use the regular interpreter with the formatter as handler.
21+ interp := & Interpreter {
22+ Handler : f ,
23+ }
24+ if err := interp .ExecTranscript (ctx , r ); err != nil {
25+ return nil , err
26+ }
27+
28+ // Ensure file ends with exactly one newline
29+ content := f .buf .Bytes ()
30+ content = bytes .TrimRight (content , "\n " )
31+ if len (content ) > 0 {
32+ content = append (content , '\n' )
33+ }
34+
35+ return bytes .NewBuffer (content ), nil
36+ }
37+
38+ func (f * Formatter ) HandleComment (ctx context.Context , text string ) error {
39+ f .lineno ++
40+
41+ // Normalize comments and blank lines
42+ trimmed := strings .TrimSpace (text )
43+ if trimmed == "" {
44+ // Blank line
45+ f .buf .WriteString ("\n " )
46+ } else if strings .HasPrefix (trimmed , "#" ) {
47+ // Normalize comment formatting
48+ comment := strings .TrimPrefix (trimmed , "#" )
49+ comment = strings .TrimSpace (comment )
50+ if comment == "" {
51+ f .buf .WriteString ("#\n " )
52+ } else {
53+ f .buf .WriteString ("# " + comment + "\n " )
54+ }
55+ }
56+
57+ return nil
58+ }
59+
60+ func (f * Formatter ) HandleRun (ctx context.Context , command string ) error {
61+ f .lineno ++
62+
63+ // Write the command with normalized formatting
64+ f .buf .WriteString ("$ " + strings .TrimSpace (command ) + "\n " )
65+
66+ return nil
67+ }
68+
69+ func (f * Formatter ) HandleOutput (ctx context.Context , fd int , line string ) error {
70+ f .lineno ++
71+
72+ // Output lines preserve their exact content (including whitespace)
73+ f .buf .WriteString (strconv .Itoa (fd ) + " " + line + "\n " )
74+
75+ return nil
76+ }
77+
78+ func (f * Formatter ) HandleFileOutput (ctx context.Context , fd int , filepath string ) error {
79+ f .lineno ++
80+
81+ // File output references with normalized formatting
82+ f .buf .WriteString (strconv .Itoa (fd ) + "< " + strings .TrimSpace (filepath ) + "\n " )
83+
84+ return nil
85+ }
86+
87+ func (f * Formatter ) HandleNoNewline (ctx context.Context , fd int ) error {
88+ f .lineno ++
89+
90+ // No-newline directive with normalized formatting
91+ f .buf .WriteString ("% no-newline\n " )
92+
93+ return nil
94+ }
95+
96+ func (f * Formatter ) HandleExitCode (ctx context.Context , exitCode int ) error {
97+ f .lineno ++
98+
99+ // Exit code with normalized formatting
100+ f .buf .WriteString ("? " + strconv .Itoa (exitCode ) + "\n " )
101+
102+ return nil
103+ }
104+
105+ func (f * Formatter ) HandleEnd (ctx context.Context ) error {
106+ // No special handling needed for end
107+ return nil
108+ }
0 commit comments