Skip to content

Commit

Permalink
apply
Browse files Browse the repository at this point in the history
  • Loading branch information
itayd committed May 23, 2022
1 parent 7479e89 commit 143a0e3
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 16 deletions.
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,34 @@
# pounce
simple find and replace in files

simple find and replace in files.

```
$ pounce collect -r -s 'dog' > /tmp/dogs.txt
$ cat /tmp/dogs.txt
README.md:1:I like dogs
some/dir/dogs.txt:3:dogs are the best!
$ # The idea is that this can be done interactively using vim.
$ # This allows trial and error and faster feedback, but for
$ # the sake of demo, we'll use sed.
$ sed -i '' -e 's/dog/cat/g' /tmp/dogs.txt
$ pounce apply < /tmp/dogs.txt
$ cat README.md
I like cats
```

One liner version:
```
$ pounce collect -r -s 'dog' | sed -e 's/dog/cat/g' | pounce apply
```

# TODO

[ ] deal with colons in file names.
[ ] deal with no EOL last line.
[ ] apply: only generate backup files if content actually changed.
[ ] apply: read/write piece wise.
[ ] \n vs \r\n?

# Disclaimer

Both cats and dogs are awesome.
2 changes: 1 addition & 1 deletion app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import (
var app = cli.App{
Commands: []*cli.Command{
&collectCmd,
&replaceCmd,
&applyCmd,
},
}
25 changes: 13 additions & 12 deletions replace.go → apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ import (
"github.com/urfave/cli/v2"
)

var replaceFlags = struct {
var applyFlags = struct {
print bool
bak string
}{}

var replaceCmd = cli.Command{
Name: "replace",
UsageText: "pounce replace [-opts]",
Description: "replace lines in files according given replacement content",
Aliases: []string{"r"},
var applyCmd = cli.Command{
Name: "apply",
UsageText: "pounce apply [-opts]",
Description: "apply modified modified lines",
Aliases: []string{"a"},
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "print",
Aliases: []string{"p"},
Destination: &replaceFlags.print,
Destination: &applyFlags.print,
Usage: "print each incoming line",
},
&cli.StringFlag{
Name: "bak",
Aliases: []string{"i"},
Destination: &replaceFlags.bak,
Destination: &applyFlags.bak,
Usage: "if not empty, backup originals with given suffix",
},
},
Expand All @@ -55,7 +55,7 @@ func processReplaceInput(r io.Reader) error {
return nil
}

if err := replace(acc.path, acc.data); err != nil {
if err := apply(acc.path, acc.data); err != nil {
return fmt.Errorf("%s: %w", acc.path, err)
}

Expand All @@ -72,7 +72,7 @@ func processReplaceInput(r io.Reader) error {
continue
}

if replaceFlags.print {
if applyFlags.print {
fmt.Fprintln(os.Stderr, text)
}

Expand Down Expand Up @@ -106,13 +106,14 @@ func processReplaceInput(r io.Reader) error {
return nil
}

func replace(path string, data map[int]string) error {
// TODO: all contents is read into memory. Need to do it piecewise.
func apply(path string, data map[int]string) error {
content, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("%s: %w", path, err)
}

if bak := replaceFlags.bak; len(bak) > 0 {
if bak := applyFlags.bak; len(bak) > 0 {
if err := os.WriteFile(path+bak, content, 0755); err != nil {
return fmt.Errorf("backup %s%s: %w", path, bak, err)
}
Expand Down
19 changes: 17 additions & 2 deletions collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var collectFlags = struct {
print bool
bin bool
recursive bool
abs bool
}{}

var collectCmd = cli.Command{
Expand Down Expand Up @@ -66,6 +67,12 @@ var collectCmd = cli.Command{
Destination: &collectFlags.bin,
Usage: "also search in binary files",
},
&cli.BoolFlag{
Name: "abs",
Aliases: []string{"a"},
Destination: &collectFlags.abs,
Usage: "write all file's absolute paths",
},
},
Action: func(c *cli.Context) error {
m, err := matcher()
Expand Down Expand Up @@ -176,15 +183,23 @@ func gather(prev, path string, matcher func(string) bool) error {
r = io.MultiReader(bytes.NewReader(pre), f)
}

if collectFlags.abs {
apath, err := filepath.Abs(path)
if err != nil {
return fmt.Errorf("abs %s: %w", path, err)
}

path = apath
}

if collectFlags.print {
fmt.Fprintln(os.Stderr, path)
}

s := bufio.NewScanner(r)
for lineNum := 1; s.Scan(); lineNum++ {
text := s.Text()

if matcher(text) {
if text := s.Text(); matcher(text) {
fmt.Printf("%s:%d:%s\n", path, lineNum, text)
}
}
Expand Down

0 comments on commit 143a0e3

Please sign in to comment.