nimgrep: version 0.8
This commit is contained in:
parent
1eba1063bd
commit
71f7938d38
2 changed files with 56 additions and 17 deletions
2
todo.txt
2
todo.txt
|
|
@ -27,6 +27,8 @@ Bugs
|
||||||
- detected by pegs module 64bit: p(result, result) should use a temporary!
|
- detected by pegs module 64bit: p(result, result) should use a temporary!
|
||||||
- the parser allows empty object case branches
|
- the parser allows empty object case branches
|
||||||
- Exception matching needs to take subclasses into account
|
- Exception matching needs to take subclasses into account
|
||||||
|
- pegs: the anchor '^' does not work because many procs use a linear search
|
||||||
|
and matchLen()
|
||||||
|
|
||||||
|
|
||||||
To implement
|
To implement
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import
|
||||||
os, strutils, parseopt, pegs, re, terminal
|
os, strutils, parseopt, pegs, re, terminal
|
||||||
|
|
||||||
const
|
const
|
||||||
Version = "0.7"
|
Version = "0.8"
|
||||||
Usage = "nimgrep - Nimrod Grep Utility Version " & version & """
|
Usage = "nimgrep - Nimrod Grep Utility Version " & version & """
|
||||||
|
|
||||||
(c) 2011 Andreas Rumpf
|
(c) 2011 Andreas Rumpf
|
||||||
|
|
@ -20,15 +20,15 @@ Usage:
|
||||||
Options:
|
Options:
|
||||||
--find, -f find the pattern (default)
|
--find, -f find the pattern (default)
|
||||||
--replace, -r replace the pattern
|
--replace, -r replace the pattern
|
||||||
--peg pattern is a peg (default)
|
--peg pattern is a peg
|
||||||
--re pattern is a regular expression; extended syntax for
|
--re pattern is a regular expression (default); extended
|
||||||
the regular expression is always turned on
|
syntax for the regular expression is always turned on
|
||||||
--recursive process directories recursively
|
--recursive process directories recursively
|
||||||
--confirm confirm each occurence/replacement; there is a chance
|
--confirm confirm each occurence/replacement; there is a chance
|
||||||
to abort any time without touching the file
|
to abort any time without touching the file
|
||||||
--stdin read pattern from stdin (to avoid the shell's confusing
|
--stdin read pattern from stdin (to avoid the shell's confusing
|
||||||
quoting rules)
|
quoting rules)
|
||||||
--word, -w the pattern should have word boundaries
|
--word, -w the match should have word boundaries (buggy for pegs!)
|
||||||
--ignoreCase, -i be case insensitive
|
--ignoreCase, -i be case insensitive
|
||||||
--ignoreStyle, -y be style insensitive
|
--ignoreStyle, -y be style insensitive
|
||||||
--ext:EX1|EX2|... only search the files with the given extension(s)
|
--ext:EX1|EX2|... only search the files with the given extension(s)
|
||||||
|
|
@ -49,7 +49,7 @@ var
|
||||||
pattern = ""
|
pattern = ""
|
||||||
replacement = ""
|
replacement = ""
|
||||||
extensions: seq[string] = @[]
|
extensions: seq[string] = @[]
|
||||||
options: TOptions
|
options: TOptions = {optRegex}
|
||||||
|
|
||||||
proc ask(msg: string): string =
|
proc ask(msg: string): string =
|
||||||
stdout.write(msg)
|
stdout.write(msg)
|
||||||
|
|
@ -108,14 +108,16 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
|
||||||
|
|
||||||
proc processFile(filename: string) =
|
proc processFile(filename: string) =
|
||||||
var buffer = system.readFile(filename)
|
var buffer = system.readFile(filename)
|
||||||
if isNil(buffer): quit("cannot open file: " & filename)
|
if isNil(buffer):
|
||||||
|
echo "cannot open file: ", filename
|
||||||
|
return
|
||||||
stdout.writeln(filename)
|
stdout.writeln(filename)
|
||||||
var pegp: TPeg
|
var pegp: TPeg
|
||||||
var rep: TRegex
|
var rep: TRegex
|
||||||
var result: string
|
var result: string
|
||||||
|
|
||||||
if optRegex in options:
|
if optRegex in options:
|
||||||
if optIgnoreCase in options:
|
if {optIgnoreCase, optIgnoreStyle} * options != {}:
|
||||||
rep = re(pattern, {reExtended, reIgnoreCase})
|
rep = re(pattern, {reExtended, reIgnoreCase})
|
||||||
else:
|
else:
|
||||||
rep = re(pattern)
|
rep = re(pattern)
|
||||||
|
|
@ -187,10 +189,42 @@ proc hasRightExt(filename: string, exts: seq[string]): bool =
|
||||||
for x in items(exts):
|
for x in items(exts):
|
||||||
if os.cmpPaths(x, y) == 0: return true
|
if os.cmpPaths(x, y) == 0: return true
|
||||||
|
|
||||||
|
proc styleInsensitive(s: string): string =
|
||||||
|
template addx: stmt =
|
||||||
|
result.add(s[i])
|
||||||
|
inc(i)
|
||||||
|
result = ""
|
||||||
|
var i = 0
|
||||||
|
var brackets = 0
|
||||||
|
while i < s.len:
|
||||||
|
case s[i]
|
||||||
|
of 'A'..'Z', 'a'..'z', '0'..'9':
|
||||||
|
addx()
|
||||||
|
if brackets == 0: result.add("_?")
|
||||||
|
of '_':
|
||||||
|
addx()
|
||||||
|
result.add('?')
|
||||||
|
of '[':
|
||||||
|
addx()
|
||||||
|
inc(brackets)
|
||||||
|
of ']':
|
||||||
|
addx()
|
||||||
|
if brackets > 0: dec(brackets)
|
||||||
|
of '?':
|
||||||
|
addx()
|
||||||
|
if s[i] == '<':
|
||||||
|
addx()
|
||||||
|
while s[i] != '>' and s[i] != '\0': addx()
|
||||||
|
of '\\':
|
||||||
|
addx()
|
||||||
|
if s[i] in strutils.digits:
|
||||||
|
while s[i] in strutils.digits: addx()
|
||||||
|
else:
|
||||||
|
addx()
|
||||||
|
else: addx()
|
||||||
|
|
||||||
proc walker(dir: string) =
|
proc walker(dir: string) =
|
||||||
var isDir = false
|
|
||||||
for kind, path in walkDir(dir):
|
for kind, path in walkDir(dir):
|
||||||
isDir = true
|
|
||||||
case kind
|
case kind
|
||||||
of pcFile:
|
of pcFile:
|
||||||
if extensions.len == 0 or path.hasRightExt(extensions):
|
if extensions.len == 0 or path.hasRightExt(extensions):
|
||||||
|
|
@ -199,7 +233,7 @@ proc walker(dir: string) =
|
||||||
if optRecursive in options:
|
if optRecursive in options:
|
||||||
walker(path)
|
walker(path)
|
||||||
else: nil
|
else: nil
|
||||||
if not isDir: processFile(dir)
|
if existsFile(dir): processFile(dir)
|
||||||
|
|
||||||
proc writeHelp() = quit(Usage)
|
proc writeHelp() = quit(Usage)
|
||||||
proc writeVersion() = quit(Version)
|
proc writeVersion() = quit(Version)
|
||||||
|
|
@ -223,8 +257,12 @@ for kind, key, val in getopt():
|
||||||
case normalize(key)
|
case normalize(key)
|
||||||
of "find", "f": incl(options, optFind)
|
of "find", "f": incl(options, optFind)
|
||||||
of "replace", "r": incl(options, optReplace)
|
of "replace", "r": incl(options, optReplace)
|
||||||
of "peg": incl(options, optPeg)
|
of "peg":
|
||||||
of "re": incl(options, optRegex)
|
excl(options, optRegex)
|
||||||
|
incl(options, optPeg)
|
||||||
|
of "re":
|
||||||
|
incl(options, optRegex)
|
||||||
|
excl(options, optPeg)
|
||||||
of "recursive": incl(options, optRecursive)
|
of "recursive": incl(options, optRecursive)
|
||||||
of "confirm": incl(options, optConfirm)
|
of "confirm": incl(options, optConfirm)
|
||||||
of "stdin": incl(options, optStdin)
|
of "stdin": incl(options, optStdin)
|
||||||
|
|
@ -240,7 +278,6 @@ for kind, key, val in getopt():
|
||||||
checkOptions({optFind, optReplace}, "find", "replace")
|
checkOptions({optFind, optReplace}, "find", "replace")
|
||||||
checkOptions({optPeg, optRegex}, "peg", "re")
|
checkOptions({optPeg, optRegex}, "peg", "re")
|
||||||
checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style")
|
checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style")
|
||||||
checkOptions({optIgnoreCase, optPeg}, "ignore_case", "peg")
|
|
||||||
|
|
||||||
if optStdin in options:
|
if optStdin in options:
|
||||||
pattern = ask("pattern [ENTER to exit]: ")
|
pattern = ask("pattern [ENTER to exit]: ")
|
||||||
|
|
@ -254,15 +291,15 @@ else:
|
||||||
if filenames.len == 0:
|
if filenames.len == 0:
|
||||||
filenames.add(os.getCurrentDir())
|
filenames.add(os.getCurrentDir())
|
||||||
if optRegex notin options:
|
if optRegex notin options:
|
||||||
|
if optWord in options:
|
||||||
|
pattern = r"(^ / !\letter)(" & pattern & r") !\letter"
|
||||||
if optIgnoreStyle in options:
|
if optIgnoreStyle in options:
|
||||||
pattern = "\\y " & pattern
|
pattern = "\\y " & pattern
|
||||||
elif optIgnoreCase in options:
|
elif optIgnoreCase in options:
|
||||||
pattern = "\\i " & pattern
|
pattern = "\\i " & pattern
|
||||||
if optWord in options:
|
|
||||||
pattern = r"(&\letter? / ^ )(" & pattern & r") !\letter"
|
|
||||||
else:
|
else:
|
||||||
if optIgnoreStyle in options:
|
if optIgnoreStyle in options:
|
||||||
quit "ignorestyle not supported for regular expressions"
|
pattern = styleInsensitive(pattern)
|
||||||
if optWord in options:
|
if optWord in options:
|
||||||
pattern = r"\b (:?" & pattern & r") \b"
|
pattern = r"\b (:?" & pattern & r") \b"
|
||||||
for f in items(filenames):
|
for f in items(filenames):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue