Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: updates Package Structure, Add Interfaces, and Enhance Testing #29

Merged
merged 14 commits into from
Jun 28, 2024
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
113 changes: 113 additions & 0 deletions cli/clipper/clipper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package clipper

import (
"fmt"
"io"
"os"
"strings"

"github.com/atotto/clipboard"
"github.com/supitsdu/clipper/cli/options"
)

// ContentReader defines an interface for reading content from various sources.
type ContentReader interface {
Read() (string, error)
}

// ClipboardWriter defines an interface for writing content to the clipboard.
type ClipboardWriter interface {
Write(content string) error
}

// FileContentReader reads content from a specified file path.
type FileContentReader struct {
FilePath string
}

// Read reads the content from the file specified in FileContentReader.
func (f FileContentReader) Read() (string, error) {
content, err := os.ReadFile(f.FilePath)
if err != nil {
return "", fmt.Errorf("error reading file '%s': %w", f.FilePath, err)
}
return string(content), nil
}

// StdinContentReader reads content from the standard input (stdin).
type StdinContentReader struct{}

// Read reads the content from stdin.
func (s StdinContentReader) Read() (string, error) {
input, err := io.ReadAll(os.Stdin)
if err != nil {
return "", fmt.Errorf("error reading from stdin: %w", err)
}
return string(input), nil
}

// DefaultClipboardWriter writes content to the clipboard using the default clipboard implementation.
type DefaultClipboardWriter struct{}

// Write writes the given content to the clipboard.
func (c DefaultClipboardWriter) Write(content string) error {
return clipboard.WriteAll(content)
}

// ParseContent aggregates content from the provided readers, or returns the direct text if provided.
func ParseContent(directText *string, readers ...ContentReader) (string, error) {
if directText != nil && *directText != "" {
return *directText, nil
}

if len(readers) == 0 {
return "", fmt.Errorf("no content readers provided")
}

var sb strings.Builder
for _, reader := range readers {
content, err := reader.Read()
if err != nil {
return "", err
}
sb.WriteString(content + "\n")
}

return sb.String(), nil
}

func GetReaders(targets []string) []ContentReader {
if len(targets) == 0 {
// If no file paths are provided, use StdinContentReader to read from stdin.
return []ContentReader{StdinContentReader{}}
} else {
// If file paths are provided as arguments, create FileContentReader instances for each.
var readers []ContentReader
for _, filePath := range targets {
readers = append(readers, FileContentReader{FilePath: filePath})
}
return readers
}
}

// Run executes the clipper tool logic based on the provided configuration.
func Run(config *options.Config, writer ClipboardWriter) (string, error) {
if *config.ShowVersion {
return options.Version, nil
}

readers := GetReaders(config.Args)

// Aggregate the content from the provided sources.
content, err := ParseContent(config.DirectText, readers...)
if err != nil {
return "", fmt.Errorf("parsing content: %w", err)
}

// Write the parsed content to the provided clipboard.
if err = writer.Write(content); err != nil {
return "", fmt.Errorf("copying content to clipboard: %w", err)
}

return "updated clipboard successfully. Ready to paste!", nil
}
25 changes: 25 additions & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"fmt"
"os"

"github.com/supitsdu/clipper/cli/clipper"
"github.com/supitsdu/clipper/cli/options"
)

func main() {
config := options.ParseFlags()
writer := clipper.DefaultClipboardWriter{}

msg, err := clipper.Run(config, writer)
if err != nil {
fmt.Printf("Error %s\n", err)
os.Exit(1)
}

if msg != "" {
fmt.Printf("Clipper %s\n", msg)
os.Exit(0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this one

}
}
38 changes: 38 additions & 0 deletions cli/options/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package options

import (
"flag"
"fmt"
)

type Config struct {
DirectText *string
ShowVersion *bool
Args []string
}

const Version = "1.5.0"

// ParseFlags parses the command-line flags and arguments.
func ParseFlags() *Config {
directText := flag.String("c", "", "Copy text directly from command line argument")
showVersion := flag.Bool("v", false, "Show the current version of the clipper tool")

flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Clipper is a lightweight command-line tool for copying contents to the clipboard.\n")
fmt.Fprintf(flag.CommandLine.Output(), "\nUsage:\n")
fmt.Fprintf(flag.CommandLine.Output(), " clipper [arguments] [file ...]\n")
fmt.Fprintf(flag.CommandLine.Output(), "\nArguments:\n")
fmt.Fprintf(flag.CommandLine.Output(), " -c <string> Copy text directly from command line argument\n")
fmt.Fprintf(flag.CommandLine.Output(), " -v Show the current version of the clipper tool\n")
fmt.Fprintf(flag.CommandLine.Output(), "\nIf no file or text is provided, reads from standard input.\n")
}

flag.Parse()

return &Config{
DirectText: directText,
ShowVersion: showVersion,
Args: flag.Args(),
}
}
103 changes: 0 additions & 103 deletions main.go

This file was deleted.

Loading
Loading