11package main
22
33import (
4- "fmt"
5- "errors"
6- "bytes"
7- "io/ioutil"
8- "bufio"
9- "os"
10- "strings"
11- "regexp"
12- flags "github.com/jessevdk/go-flags"
4+ "fmt"
5+ "errors"
6+ "bytes"
7+ "io/ioutil"
8+ "bufio"
9+ "os"
10+ "strings"
11+ "regexp"
12+ flags "github.com/jessevdk/go-flags"
1313)
1414
1515const (
16- Author = "webdevops.io"
17- Version = "0.2.1"
16+ Author = "webdevops.io"
17+ Version = "0.2.1"
1818)
1919
2020var opts struct {
21- Search string `short:"s" long:"search" required:"true" description:"search term"`
22- SearchRegex * regexp.Regexp
23- Replace string `short:"r" long:"replace" required:"true" description:"replacement term" `
24- IgnoreCase bool `short:"i" long:"ignore-case" description:"ignore pattern case"`
25- ReplaceLine bool ` long:"replace-line" description:"replace whole line instead of only match"`
26- Regex bool ` long:"regex" description:"treat pattern as regex"`
27- RegexBackref bool ` long:"regex-backrefs" description:"enable backreferences in replace term"`
28- Verbose bool `short:"v" long:"verbose" description:"verbose mode"`
29- DryRun bool ` long:"dry-run" description:"dry run mode"`
30- ShowVersion bool `short:"V" long:"version" description:"show version and exit"`
31- ShowHelp bool `short:"h" long:"help" description:"show this help message"`
21+ Search string `short:"s" long:"search" required:"true" description:"search term"`
22+ SearchRegex * regexp.Regexp
23+ Replace string `short:"r" long:"replace" required:"true" description:"replacement term" `
24+ IgnoreCase bool `short:"i" long:"ignore-case" description:"ignore pattern case"`
25+ ReplaceLine bool ` long:"replace-line" description:"replace whole line instead of only match"`
26+ Regex bool ` long:"regex" description:"treat pattern as regex"`
27+ RegexBackref bool ` long:"regex-backrefs" description:"enable backreferences in replace term"`
28+ RegexPosix bool ` long:"regex-posix" description:"parse regex term as POSIX regex"`
29+ Verbose bool `short:"v" long:"verbose" description:"verbose mode"`
30+ DryRun bool ` long:"dry-run" description:"dry run mode"`
31+ ShowVersion bool `short:"V" long:"version" description:"show version and exit"`
32+ ShowHelp bool `short:"h" long:"help" description:"show this help message"`
3233}
3334
3435// Replace line (if match is found) in file
3536func replaceInFile (filepath string ) {
37+ // try open file
3638 file , err := os .Open (filepath )
3739 if err != nil {
3840 panic (err )
@@ -45,9 +47,12 @@ func replaceInFile(filepath string) {
4547 line , e := Readln (r )
4648 for e == nil {
4749 if searchMatch (line ) {
50+ // --replace-line
4851 if opts .ReplaceLine {
52+ // replace whole line with replace term
4953 line = opts .Replace
5054 } else {
55+ // replace only term inside line
5156 line = replaceText (line )
5257 }
5358
@@ -95,6 +100,7 @@ func searchMatch(content string) (bool) {
95100
96101// Replace text in whole content based on search options
97102func replaceText (content string ) (string ) {
103+ // --regex-backrefs
98104 if opts .RegexBackref {
99105 return opts .SearchRegex .ReplaceAllString (content , opts .Replace )
100106 } else {
@@ -104,14 +110,15 @@ func replaceText(content string) (string) {
104110
105111// Write content to file
106112func writeContentToFile (filepath string , content bytes.Buffer ) {
113+ // --dry-run
107114 if opts .DryRun {
108115 title := fmt .Sprintf ("%s:" , filepath )
109116
117+ fmt .Println ()
110118 fmt .Println (title )
111119 fmt .Println (strings .Repeat ("-" , len (title )))
112120 fmt .Println (content .String ())
113121 fmt .Println ()
114- fmt .Println ()
115122 } else {
116123 var err error
117124 err = ioutil .WriteFile (filepath , content .Bytes (), 0 )
@@ -131,6 +138,7 @@ func logMessage(message string) {
131138 }
132139}
133140
141+ // Log error object as message
134142func logError (err error ) {
135143 fmt .Printf ("Error: %s\n " , err )
136144}
@@ -140,13 +148,16 @@ func logError(err error) {
140148func buildSearchTerm () {
141149 var regex string
142150
151+ // --regex
143152 if opts .Regex {
153+ // use search term as regex
144154 regex = opts .Search
145155 } else {
156+ // use search term as normal string, escape it for regex usage
146157 regex = regexp .QuoteMeta (opts .Search )
147158 }
148159
149-
160+ // --ignore-case
150161 if opts .IgnoreCase {
151162 regex = "(?i:" + regex + ")"
152163 }
@@ -155,45 +166,50 @@ func buildSearchTerm() {
155166 logMessage (fmt .Sprintf ("Using regular expression: %s" , regex ))
156167 }
157168
158- opts .SearchRegex = regexp .MustCompile (regex )
169+ if opts .RegexPosix {
170+ opts .SearchRegex = regexp .MustCompilePOSIX (regex )
171+ } else {
172+ opts .SearchRegex = regexp .MustCompile (regex )
173+ }
159174}
160175
161- func handleSpecialOptions (argparser * flags.Parser , args []string ) {
176+ func handleSpecialCliOptions (argparser * flags.Parser , args []string ) {
177+ // --version
162178 if (opts .ShowVersion ) {
163- fmt .Printf ("goreplace %s\n " , Version )
179+ fmt .Printf ("goreplace version %s\n " , Version )
164180 os .Exit (0 )
165181 }
166182
183+ // --help
167184 if (opts .ShowHelp ) {
168- argparser .WriteHelp (os .Stdout )
169- os .Exit (1 )
170- }
171-
172- if (len (args ) == 0 ) {
173- err := errors .New ("No files specified" )
174- logError (err )
175- fmt .Println ()
176- argparser .WriteHelp (os .Stdout )
177- os .Exit (1 )
178- }
185+ argparser .WriteHelp (os .Stdout )
186+ os .Exit (1 )
187+ }
188+
189+ // missing any files
190+ if (len (args ) == 0 ) {
191+ err := errors .New ("No files specified" )
192+ logError (err )
193+ fmt .Println ()
194+ argparser .WriteHelp (os .Stdout )
195+ os .Exit (1 )
196+ }
179197}
180198
181199func main () {
182200 var argparser = flags .NewParser (& opts , flags .PassDoubleDash )
183- args , err := argparser .Parse ()
201+ args , err := argparser .Parse ()
184202
185- if err != nil {
186- handleSpecialOptions (argparser , args )
203+ handleSpecialCliOptions (argparser , args )
187204
205+ if err != nil {
188206 logError (err )
189207 fmt .Println ()
190208 argparser .WriteHelp (os .Stdout )
191209 os .Exit (1 )
192210 }
193211
194- handleSpecialOptions (argparser , args )
195-
196- buildSearchTerm ()
212+ buildSearchTerm ()
197213
198214 for i := range args {
199215 var file string
@@ -203,4 +219,4 @@ func main() {
203219 }
204220
205221 os .Exit (0 )
206- }
222+ }
0 commit comments