Skip to content
Merged
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
1 change: 1 addition & 0 deletions cmd/tuirec/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ pacing to stderr.`,
cmd.Flags().Float64Var(&flags.config.GIF.LineHeight, "line-height", flags.config.GIF.LineHeight, "Line-height multiplier")
cmd.Flags().Float64Var(&flags.config.GIF.LetterSpacing, "letter-spacing", flags.config.GIF.LetterSpacing, "Letter-spacing adjustment in pixels (negative closes gaps)")
cmd.Flags().Float64Var(&flags.config.GIF.Speed, "speed", flags.config.GIF.Speed, "GIF playback speed multiplier")
cmd.Flags().StringVar(&flags.config.GIF.Select, "select", flags.config.GIF.Select, "agg --select frame range (e.g. \"0.2..\") to trim the recording's lead-in")
cmd.Flags().IntVar(&flags.maxDurationSec, "max-duration", flags.maxDurationSec, "Max recording duration in seconds")
cmd.Flags().StringVar(&flags.config.Title, "title", "", "Title embedded in the cast file")
cmd.Flags().StringVar(&flags.config.GIF.AggPath, "agg-path", flags.config.GIF.AggPath, "Path to agg binary")
Expand Down
45 changes: 45 additions & 0 deletions cmd/tuirec/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,51 @@ func TestRecordCommandNameFlag(t *testing.T) {
}
}

func TestSelectFlagOnlyOnRecord(t *testing.T) {
t.Parallel()

opts := cliOptions{stdout: &bytes.Buffer{}, stderr: &bytes.Buffer{}}

if f := newRecordCommand(opts).Flags().Lookup("select"); f == nil {
t.Fatal("record command should expose --select to trim the GIF lead-in")
}

// snapshot must NOT expose --select: it would apply agg's selection to the
// rendered PNG while the assertion/print-frame-text path reconstructs text
// from the unselected cast by frame index, so the two would disagree about
// which frame is being inspected. snapshot already targets any frame via
// --frame at:<ms>.
if f := newSnapshotCommand(opts).Flags().Lookup("select"); f != nil {
t.Fatal("snapshot command must not expose --select (desyncs PNG from assertion text)")
}
}

func TestRecordCommandParsesSelect(t *testing.T) {
t.Parallel()

var got record.Config
code := execute([]string{
"record",
"--binary", "demo-app",
"--select", "0.2..",
"--keystrokes", "wait:10,Ctrl+Q",
}, cliOptions{
stdout: &bytes.Buffer{},
stderr: &bytes.Buffer{},
look: func(path string) (string, error) { return path, nil },
run: func(_ context.Context, config record.Config) (record.Result, error) {
got = config
return record.Result{CastPath: config.CastOutput, GIFPath: config.Output}, nil
},
})
if code != exitSuccess {
t.Fatalf("execute code = %d, want %d", code, exitSuccess)
}
if got.GIF.Select != "0.2.." {
t.Fatalf("GIF.Select = %q, want %q", got.GIF.Select, "0.2..")
}
}

func TestRecordCommandNameFlagExplicitOutputOverrides(t *testing.T) {
t.Parallel()

Expand Down
8 changes: 8 additions & 0 deletions pkg/gif/gif.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ type Config struct {
FontSize int
LineHeight float64
LetterSpacing float64
// Select is passed to agg's --select to render only part of the timeline.
// Use it to trim a recording's lead-in (e.g. "0.2.." drops the first 0.2s),
// which is handy for sixel apps that paint a cell-based fallback frame
// before the terminal's sixel-capability handshake completes.
Select string
}

// Validation describes a decoded GIF.
Expand Down Expand Up @@ -72,6 +77,9 @@ func renderArgs(castPath, outputPath string, config Config) []string {
if config.LetterSpacing != 0 {
args = append(args, "--letter-spacing", formatFloat(config.LetterSpacing))
}
if config.Select != "" {
args = append(args, "--select", config.Select)
}
args = append(args, castPath, outputPath)

return args
Expand Down
18 changes: 18 additions & 0 deletions pkg/gif/gif_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ func TestRenderArgsIncludesLetterSpacingWhenSet(t *testing.T) {
}
}

func TestRenderArgsIncludesSelectWhenSet(t *testing.T) {
t.Parallel()

got := renderArgs("in.cast", "out.gif", NormalizeConfig(Config{Select: "0.2.."}))
want := []string{
"--theme", "monokai",
"--speed", "1",
"--font-size", "14",
"--line-height", "1.3",
"--select", "0.2..",
"in.cast", "out.gif",
}

if !reflect.DeepEqual(got, want) {
t.Fatalf("renderArgs() = %#v, want %#v", got, want)
}
}

func TestValidateRejectsSingleFrameGIF(t *testing.T) {
t.Parallel()

Expand Down
Loading