aboutsummaryrefslogtreecommitdiff
path: root/tools/replace.nom
diff options
context:
space:
mode:
Diffstat (limited to 'tools/replace.nom')
-rw-r--r--tools/replace.nom144
1 files changed, 144 insertions, 0 deletions
diff --git a/tools/replace.nom b/tools/replace.nom
new file mode 100644
index 0000000..2737ce0
--- /dev/null
+++ b/tools/replace.nom
@@ -0,0 +1,144 @@
+#!/usr/bin/env nomsu -V6.13.12.8
+#
+ This is a tool to replace syntax trees with something new.
+
+ Usage:
+ nomsu -t replace [-i] [--literal="$v1 $v2..."] <pattern> <replacement> file1 file2...
+
+ Example:
+ nomsu -t replace "($1 and $2) and $3" "all of [$1, $2, $3]" my_file.nom
+
+ If the "-i" flag is used, the file(s) will be edited in-place.
+ When editing in-place, if the "-f" flag is not used, each change will be
+ run past the user first.
+ If no files are passed in, this will read from stdin.
+
+use "lib/os.nom"
+use "lib/consolecolor.nom"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+if ((#$(COMMAND LINE ARGS).extras) < 2):
+ barf ("
+ Usage: nomsu -t replace [--literal="$v1 $v2..."] <pattern> <replacement> file1 file2...
+ ")
+$pattern = $(COMMAND LINE ARGS).extras.1
+$replacement = $(COMMAND LINE ARGS).extras.2
+$pattern_tree = ($pattern parsed)
+$replacement_tree = ($replacement parsed)
+$literal_vars = {}
+if $(COMMAND LINE ARGS).literal:
+ for $var in ($(COMMAND LINE ARGS).literal, all matches of "$([^ ]*)"):
+ $literal_vars.$var = (yes)
+
+if (($pattern_tree.type == "Var") and (not $literal_vars.($pattern_tree.1))):
+ barf "Pattern matches every part of the file."
+
+$pattern_vars = {
+ : for $ in recursive $pattern_tree:
+ if (($.type == "Var") and (not $literal_vars.($.1))): add $.1
+ for $child in $:
+ if ($child is a "Syntax Tree"):
+ recurse $ on $child
+}
+
+($tree matches $patt with $substitution_values) means:
+ # TODO: optimize
+ $substitution_values = {: for $k = $v in $substitution_values: add $k = $v}
+ when:
+ (not ($tree is syntax tree)): return (no)
+ (($patt.type == "Var") and $pattern_vars.($patt.1)):
+ if $substitution_values.($patt.1):
+ if ($tree == $substitution_values.($patt.1)):
+ return $substitution_values
+ ..else:
+ return (nil)
+ ..else:
+ $substitution_values.($patt.1) = $tree
+ return $substitution_values
+ ($tree.type != $patt.type): return (nil)
+ ($tree.type == "Action"):
+ if (($tree, get stub) != ($patt, get stub)): return (nil)
+
+ for $ in 1 to (#$patt):
+ if ($patt.$ is syntax tree):
+ $new_values = ($tree.$ matches $patt.$ with $substitution_values)
+ unless $new_values:
+ return (nil)
+
+ for $k = $v in $new_values:
+ $substitution_values.$k = $v
+ ..else:
+ unless ($tree.$ == $patt.$): return (nil)
+
+ if ((#$tree) != (#$patt)): return (nil)
+ return $substitution_values
+
+$filenames = ($(COMMAND LINE ARGS).extras, from 3 to -1)
+if ((#$filenames) == 0):
+ say ("
+ Warning: searching stdin (ctrl-d to abort). To avoid this message, use nomsu -t find -
+ ")
+ $filenames = ["stdin"]
+
+for $filename in $filenames:
+ $file = (read file $filename)
+ unless $file:
+ barf "File does not exist: \$filename"
+ $code = (NomsuCode from ($Source $filename 1 (size of $file)) $file)
+ try:
+ $tree = ($code parsed)
+ ..and if it barfs $msg:
+ say
+ red ("
+ \$filename failed to parse:
+ \$msg
+ ")
+ $tree = (nil)
+
+ unless $tree:
+ do next $filename
+
+ $replaced = {}
+ $matched = {}
+ $user_answers = {}
+ ($tree with replacements) means
+ $tree, map
+ for $t:
+ $values = ($t matches $pattern_tree with {})
+ if $values:
+ $matched.$t = (yes)
+ for $k = $v in $values:
+ $values.$k = ($v with replacements)
+ $ret = ($replacement_tree with vars $values)
+ if ($(COMMAND LINE ARGS).i and (not $(COMMAND LINE ARGS).f)):
+ if ($user_answers.$t == (nil)):
+ if ((#$user_answers) > 0): say ""
+ $user_answers.$t = "n"
+ say "\(bright)Should this:"
+ say ("
+ \(bright)\(yellow)\("\(($t with replacements) as nomsu)", with "\n" -> "\n ")\
+ ..\(reset color)
+ ")
+ say "\(bright)..be replaced with:"
+
+ say ("
+ \(bright)\(blue)\("\($ret as nomsu)", with "\n" -> "\n ")\(reset color)
+ ")
+
+ $user_answers.$t = (ask "\(bright)..? [Y/n]\(reset color) ")
+
+ if ($user_answers.$t == "n"): return (nil)
+ $replaced.$t = (yes)
+ return $ret
+ $tree2 = ($tree with replacements)
+ if $(COMMAND LINE ARGS).i:
+ if ((#$user_answers) > 0): say ""
+ say ("
+ \(#$replaced)/\(#$matched) replacement\("" if ((#$replaced) == 1) else "s") in \$filename
+ ")
+
+ if ((#$replaced) > 0):
+ write "\($tree2 as nomsu)" to file $filename
+ ..else:
+ say ($tree2 as nomsu)