all repos — fae @ 05c403fbfcbceae5b33bdb743045443f896bc186

A minuscule find and edit utility.

Merge branch 'master' of github.com:h3rald/fae
h3rald h3rald@h3rald.com
Fri, 19 Mar 2021 17:20:20 +0100
commit

05c403fbfcbceae5b33bdb743045443f896bc186

parent

da63668046e65dffb6520d7cb87a811636c76f2b

M fae.nimblefae.nimble

@@ -24,11 +24,7 @@ installExt = @["nim", "c", "h"]

# Dependencies -requires "nim >= 1.4.0", "nifty" - -before install: - exec "nimble install nifty" - exec "nifty install" +requires "nim >= 1.4.0" # Build
D nifty.json

@@ -1,36 +0,0 @@

-{ - "storage": "packages", - "commands": { - "install": { - "_syntax": "install [<package>]", - "_description": "Installs the specified package (or all mapped packages) to the storage directory.", - "git+src": { - "cmd": "git clone {{src}} --depth 1" - }, - "git+src+tag": { - "cmd": "git clone --branch {{tag}} {{src}} --depth 1" - }, - "curl+src+name": { - "cmd": "curl {{src}} -o {{name}}" - } - }, - "upgrade": { - "_syntax": "upgrade [<package>]", - "_description": "Upgrades the specified previously-installed package (or all packages).", - "git+name": { - "cmd": "git pull", - "pwd": "{{name}}" - }, - "curl+src+name": { - "cmd": "curl {{src}} -o {{name}}" - } - } - }, - "packages": { - "nim-sgregex": { - "name": "nim-sgregex", - "src": "git@github.com:h3rald/nim-sgregex.git", - "git": true - } - } -}
M src/fae.nimsrc/fae.nim

@@ -1,5 +1,5 @@

import - ../packages/nim-sgregex/sgregex, + nre, std/exitprocs, parseopt, os,

@@ -21,18 +21,25 @@ apply: bool

test: bool silent: bool +when defined(windows): + {.passL: "-static -Lfaepkg/vendor/pcre/windows -lpcre".} +elif defined(linux): + {.passL: "-static -Lfaepkg/vendor/pcre/linux -lpcre".} +elif defined(macosx): + {.passL: "-Bstatic -Lfaepkg/vendor/pcre/macosx -lpcre -Bdynamic".} + addExitProc(resetAttributes) const usage = appName & """ (""" & appDescription & """) v""" & appVersion & """ - (c) 2020 """ & appAuthor & """ + (c) 2020-2021 """ & appAuthor & """ Usage: - fae <pattern> <replacement> [option1 option2 ...] + fae <pattern> [<replacement> option1 option2 ...] Where: - <pattern> A regular expression to search for. + <pattern> A Perl-compatible regular expression to search for. <replacement> An optional replacement string - (use \1, \2, etc. to reference captured groups). + (use $1, $2, etc. to reference captured groups). Options: -a, --apply Substitute all occurrences of <pattern> with <replacement>

@@ -40,33 +47,26 @@ in all files without asking for confirmation.

-d, --directory Search in the specified directory (default: .). -f, --filter Specify a regular expression to filter file paths. -h, --help Display this message. - -i, --insensitive Case-insensitive matching. -r, --recursive Search directories recursively. -s, --silent Do not display matches. -t, --test Do not perform substitutions, just print results. -v, --version Display the program version. """ -proc flags(options: FaeOptions): string = - if options.insensitive: - "i" - else: - "" - -proc matchBounds(str, expr: string, start = 0, options: FaeOptions): StringBounds = +proc matchBounds(str, reg: string, start = 0, options: FaeOptions): StringBounds = if start > str.len-2: return [-1, -1] let s = str.substr(start) - let c = s.search(expr, options.flags) - if c[0].len > 0: - let match = c[0] + let m = nre.find(s, re(reg)) + if m.isNone: + result = [-1, 1] + else: + let match = m.get.match let mstart = strutils.find(s, match) if mstart < 0: return [-1, -1] let mfinish = mstart + match.len-1 result = [mstart+start, mfinish+start] - else: - result = [-1, -1] proc matchBoundsRec(str, regex: string, start = 0, matches: var seq[StringBounds], options: FaeOptions) = let match = str.matchBounds(regex, start, options)

@@ -74,15 +74,15 @@ if match[0] >= 0:

matches.add(match) matchBoundsRec(str, regex, match[1]+1, matches, options) -proc replace(str, regex: string, substitute: var string, start = 0, options: FaeOptions): string = - return sgregex.replace(str, regex, substitute, options.flags) +proc replace(str, reg: string, substitute: var string, start = 0): string = + return nre.replace(str, re(reg), substitute) proc displayMatch(str: string, start, finish: int, color = fgYellow, lineN: int, silent = false) = if silent: return let max_extra_chars = 20 let context_start = max(start-max_extra_chars, 0) - let context_finish = min(finish+max_extra_chars, str.len) + let context_finish = min(finish+max_extra_chars, str.len-1) let match: string = str.substr(start, finish) var context: string = str.substr(context_start, context_finish) if context_start > 2:

@@ -90,7 +90,7 @@ context = "..." & context

if context_finish < str.len + 3: context = context & "..." let match_context_start:int = strutils.find(context, match, start-context_start) - let match_context_finish:int = match_context_start+match.len + let match_context_finish:int = match_context_start+match.len-1 stdout.write(" ") setForegroundColor(color, true) stdout.write(lineN)

@@ -118,9 +118,9 @@

proc confirm(msg: string): bool = stdout.write(msg) var answer = stdin.readLine() - if answer.match("y(es)?", "i"): + if answer.find(re"(?i)y(es)?").isSome: return true - elif answer.match("n(o)?", "i"): + elif answer.find(re"(?)n(o)?").isSome: return false else: return confirm(msg)

@@ -176,7 +176,7 @@ ## Processing Options

var duration = cpuTime() -var options = FaeOptions(regex: "", insensitive: false, recursive: false, filter: "", substitute: "", directory: ".", apply: false, test: false, silent: false) +var options = FaeOptions(regex: "", recursive: false, filter: "", substitute: "", directory: ".", apply: false, test: false, silent: false) for kind, key, val in getOpt(): case kind:

@@ -227,7 +227,7 @@ var res: array[0..1, int]

if options.recursive: for f in walkDirRec(options.directory): - if options.filter == "" or f.match(options.filter): + if options.filter == "" or f.match(re(options.filter)).isSome: try: count.inc res = processFile(f, options)

@@ -238,7 +238,7 @@ stderr.writeLine getCurrentExceptionMsg()

continue else: for kind, f in walkDir(options.directory): - if kind == pcFile and (options.filter == "" or f.match(options.filter)): + if kind == pcFile and (options.filter == "" or f.match(re(options.filter)).isSome): try: count.inc res = processFile(f, options)
A src/fae.nims

@@ -0,0 +1,24 @@

+# https://blog.filippo.io/easy-windows-and-linux-cross-compilers-for-macos/ + +switch("amd64.windows.gcc.path", "/usr/local/bin") +switch("amd64.windows.gcc.exe", "x86_64-w64-mingw32-gcc") +switch("amd64.windows.gcc.linkerexe", "x86_64-w64-mingw32-gcc") + +switch("amd64.linux.gcc.path", "/usr/local/bin") +switch("amd64.linux.gcc.exe", "x86_64-linux-musl-gcc") +switch("amd64.linux.gcc.linkerexe", "x86_64-linux-musl-gcc") + +switch("opt", "size") +switch("gc", "orc") + +when not defined(dev): + switch("define", "release") + +if findExe("musl-gcc") != "": + switch("gcc.exe", "musl-gcc") + switch("gcc.linkerexe", "musl-gcc") + +when defined(windows): + switch("dynlibOverride", "pcre64") +else: + switch("dynlibOverride", "pcre")
M src/faepkg/config.nimsrc/faepkg/config.nim

@@ -1,5 +1,5 @@

const appName* = "fae" const appDescription* = "Find and Edit Utility" -const appVersion* = "1.0.0" +const appVersion* = "1.1.0" const appLicense* = "MIT" const appAuthor* = "Fabio Cevasco"