From c17deafdac174d7f570f1c771fd7ce81a80a8171 Mon Sep 17 00:00:00 2001 From: Rami Awar Date: Fri, 9 Feb 2024 23:33:03 +0100 Subject: [PATCH] feat: :lipstick: Refactored new command to allow empty tags instead of cancelling --- cmd/new.go | 41 +++++++++++++------- cmd/new_test.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 cmd/new_test.go diff --git a/cmd/new.go b/cmd/new.go index 82a3979..bcace36 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -5,8 +5,6 @@ import ( "fmt" "io" "os" - "path/filepath" - "runtime" "strings" "github.com/chzyer/readline" @@ -25,15 +23,21 @@ var newCmd = &cobra.Command{ RunE: new, } -func scan(message string) (string, error) { +func CanceledError() error { + return errors.New("canceled") +} + +func scan(message string, out io.Writer, in io.ReadCloser, allowEmpty bool) (string, error) { f, err := os.CreateTemp("", "pet-") - tempFile := f.Name() - defer os.Remove(f.Name()) // clean up - if runtime.GOOS == "windows" { - tempDir := os.Getenv("TEMP") - tempFile = filepath.Join(tempDir, "pet.tmp") + if err != nil { + return "", err } + defer os.Remove(f.Name()) // clean up temp file + tempFile := f.Name() + l, err := readline.NewEx(&readline.Config{ + Stdout: out, + Stdin: in, Prompt: message, HistoryFile: tempFile, InterruptPrompt: "^C", @@ -41,6 +45,7 @@ func scan(message string) (string, error) { HistorySearchFold: true, }) + if err != nil { return "", err } @@ -58,13 +63,16 @@ func scan(message string) (string, error) { break } + // If empty string, just ignore tags line = strings.TrimSpace(line) - if line == "" { + if line == "" && !allowEmpty { continue + } else if line == "" { + return "", nil } return line, nil } - return "", errors.New("canceled") + return "", CanceledError() } func new(cmd *cobra.Command, args []string) (err error) { @@ -81,27 +89,30 @@ func new(cmd *cobra.Command, args []string) (err error) { command = strings.Join(args, " ") fmt.Fprintf(color.Output, "%s %s\n", color.YellowString("Command>"), command) } else { - command, err = scan(color.YellowString("Command> ")) + command, err = scan(color.YellowString("Command> "), os.Stdout, os.Stdin, false) if err != nil { return err } } - description, err = scan(color.GreenString("Description> ")) + description, err = scan(color.GreenString("Description> "), os.Stdout, os.Stdin, false) if err != nil { return err } if config.Flag.Tag { var t string - if t, err = scan(color.CyanString("Tag> ")); err != nil { + if t, err = scan(color.CyanString("Tag> "), os.Stdout, os.Stdin, true); err != nil { return err } - tags = strings.Fields(t) + + if t != "" { + tags = strings.Fields(t) + } } for _, s := range snippets.Snippets { if s.Description == description { - return fmt.Errorf("Snippet [%s] already exists", description) + return fmt.Errorf("snippet [%s] already exists", description) } } diff --git a/cmd/new_test.go b/cmd/new_test.go new file mode 100644 index 0000000..3a76056 --- /dev/null +++ b/cmd/new_test.go @@ -0,0 +1,101 @@ +package cmd + +import ( + "bytes" + "strings" + "testing" +) + +// MockReadCloser is a mock implementation of io.ReadCloser +type MockReadCloser struct { + *strings.Reader +} + +// Close does nothing for this mock implementation +func (m *MockReadCloser) Close() error { + return nil +} + +func TestScan(t *testing.T) { + message := "Enter something: " + + input := "test\n" // Simulated user input + want := "test" // Expected output + expectedError := error(nil) + + // Create a buffer for output + var outputBuffer bytes.Buffer + // Create a mock ReadCloser for input + inputReader := &MockReadCloser{strings.NewReader(input)} + + result, err := scan(message, &outputBuffer, inputReader, false) + + // Check if the input was printed + got := result + + // Check if the result matches the expected result + if want != got { + t.Errorf("Expected result %q, but got %q", want, got) + } + + // Check if the error matches the expected error + if err != expectedError { + t.Errorf("Expected error %v, but got %v", expectedError, err) + } +} + +func TestScan_EmptyStringWithAllowEmpty(t *testing.T) { + message := "Enter something: " + + input := "\n" // Simulated user input + want := "" // Expected output + expectedError := error(nil) + + // Create a buffer for output + var outputBuffer bytes.Buffer + // Create a mock ReadCloser for input + inputReader := &MockReadCloser{strings.NewReader(input)} + + result, err := scan(message, &outputBuffer, inputReader, true) + + // Check if the input was printed + got := result + + // Check if the result matches the expected result + if want != got { + t.Errorf("Expected result %q, but got %q", want, got) + } + + // Check if the error matches the expected error + if err != expectedError { + t.Errorf("Expected error %v, but got %v", expectedError, err) + } +} + +func TestScan_EmptyStringWithoutAllowEmpty(t *testing.T) { + message := "Enter something: " + + input := "\n" // Simulated user input + want := "" // Expected output + expectedError := CanceledError() + + // Create a buffer for output + var outputBuffer bytes.Buffer + // Create a mock ReadCloser for input + inputReader := &MockReadCloser{strings.NewReader(input)} + + result, err := scan(message, &outputBuffer, inputReader, false) + + // Check if the input was printed + got := result + + // Check if the result matches the expected result + if want != got { + t.Errorf("Expected result %q, but got %q", want, got) + } + + // Check if the error matches the expected error + if err.Error() != expectedError.Error() { + t.Errorf("Expected error %v, but got %v", expectedError, err) + } +}