feat: add replace subcommand with multi-pattern support

This commit is contained in:
Rogee
2025-10-29 17:46:54 +08:00
parent fa57af8a26
commit ceea09f7be
42 changed files with 1848 additions and 14 deletions

View File

@@ -0,0 +1,61 @@
package replace
import (
"errors"
"fmt"
"os"
"path/filepath"
)
// ReplaceRequest captures all inputs needed to evaluate a replace operation.
type ReplaceRequest struct {
WorkingDir string
Patterns []string
Replacement string
IncludeDirectories bool
Recursive bool
IncludeHidden bool
Extensions []string
}
// Validate ensures the request is well-formed before preview/apply.
func (r *ReplaceRequest) Validate() error {
if r == nil {
return errors.New("replace request cannot be nil")
}
if len(r.Patterns) == 0 {
return errors.New("at least one pattern is required")
}
if r.Replacement == "" {
// Allow empty replacement but make sure caller has surfaced warnings elsewhere.
// No error returned; preview will message accordingly.
}
if r.WorkingDir == "" {
cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("determine working directory: %w", err)
}
r.WorkingDir = cwd
}
if !filepath.IsAbs(r.WorkingDir) {
abs, err := filepath.Abs(r.WorkingDir)
if err != nil {
return fmt.Errorf("resolve working directory: %w", err)
}
r.WorkingDir = abs
}
info, err := os.Stat(r.WorkingDir)
if err != nil {
return fmt.Errorf("stat working directory: %w", err)
}
if !info.IsDir() {
return fmt.Errorf("working directory %q is not a directory", r.WorkingDir)
}
return nil
}