From 5a1127790b42f3a69320136dc591ba2efaa62243 Mon Sep 17 00:00:00 2001 From: Matthias Diester Date: Wed, 1 Jan 2025 21:33:09 +0100 Subject: [PATCH] Refactor show command code logic Move code logic into scaffold for consinstency. Introduce test case for show command flag. --- internal/cmd/root.go | 17 +++-------------- internal/img/output.go | 19 +++++++++++++++++++ internal/img/output_test.go | 7 +++++++ test/data/expected-show-cmd.png | Bin 0 -> 19069 bytes 4 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 test/data/expected-show-cmd.png diff --git a/internal/cmd/root.go b/internal/cmd/root.go index b9f4fe3..e280f20 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -42,15 +42,6 @@ var version string // saveToClipboard function will be implemented by OS specific code var saveToClipboard func(img.Scaffold) error -// commandIndicator is the string to be used to indicate the command in the screenshot -var commandIndicator = func() string { - if val, ok := os.LookupEnv("TS_COMMAND_INDICATOR"); ok { - return val - } - - return "➜" -}() - var rootCmd = &cobra.Command{ Use: fmt.Sprintf("%s [%s flags] [--] command [command flags] [command arguments] [...]", executableName(), executableName()), Short: "Creates a screenshot of terminal command output", @@ -111,11 +102,9 @@ window including all terminal colors and text decorations. // Optional: Prepend command line arguments to output content // if includeCommand, err := cmd.Flags().GetBool("show-cmd"); err == nil && includeCommand { - // #nosec G104 - bunt.Fprintf(&buf, "Lime{%s} DimGray{%s}\n", - commandIndicator, - strings.Join(args, " "), - ) + if err := scaffold.AddCommand(args...); err != nil { + return err + } } // Run the provided command in a pseudo terminal and capture diff --git a/internal/img/output.go b/internal/img/output.go index 52c4fb6..18f025f 100644 --- a/internal/img/output.go +++ b/internal/img/output.go @@ -27,6 +27,7 @@ import ( "image/png" "io" "math" + "os" "strings" "github.com/esimov/stackblur-go" @@ -49,6 +50,15 @@ const ( defaultFontDPI = 144 ) +// commandIndicator is the string to be used to indicate the command in the screenshot +var commandIndicator = func() string { + if val, ok := os.LookupEnv("TS_COMMAND_INDICATOR"); ok { + return val + } + + return "➜" +}() + type Scaffold struct { content bunt.String @@ -138,6 +148,15 @@ func (s *Scaffold) GetFixedColumns() int { return columns } +func (s *Scaffold) AddCommand(args ...string) error { + return s.AddContent(strings.NewReader( + bunt.Sprintf("Lime{%s} DimGray{%s}\n", + commandIndicator, + strings.Join(args, " "), + ), + )) +} + func (s *Scaffold) AddContent(in io.Reader) error { parsed, err := bunt.ParseStream(in) if err != nil { diff --git a/internal/img/output_test.go b/internal/img/output_test.go index f48c8d0..b67cb79 100644 --- a/internal/img/output_test.go +++ b/internal/img/output_test.go @@ -75,6 +75,13 @@ var _ = Describe("Creating images", func() { Expect(scaffold).To(LookLike(testdata("expected-wrapping.png"))) }) + It("should show the command when configured", func() { + scaffold := NewImageCreator() + Expect(scaffold.AddCommand("echo", "foobar")).To(Succeed()) + Expect(scaffold.AddContent(strings.NewReader("foobar"))).To(Succeed()) + Expect(scaffold).To(LookLike(testdata("expected-show-cmd.png"))) + }) + It("should write a PNG stream based on provided input with ANSI sequences", func() { var buf bytes.Buffer _, _ = Fprintf(&buf, "Text with emphasis, like *bold*, _italic_, _*bold/italic*_ or ~underline~.\n\n") diff --git a/test/data/expected-show-cmd.png b/test/data/expected-show-cmd.png new file mode 100644 index 0000000000000000000000000000000000000000..ab053006110ce160609383c1d5f3aa72cceda318 GIT binary patch literal 19069 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 literal 0 HcmV?d00001