code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(149 lines)
1 #!/usr/bin/env nomsu -V7.0.0
2 ###
3 This is a tool to replace syntax trees with something new.
5 Usage:
6 nomsu -t replace [-i] [-f] [-q] [--literal="$v1 $v2..."] <pattern> <replacement> file1 file2...
8 Example:
9 nomsu -t replace "($1 and $2) and $3" "all of [$1, $2, $3]" my_file.nom
11 If the "-i" flag is used, the file(s) will be edited in-place.
12 When editing in-place, if the "-f" flag is not used, each change will be
13 run past the user first.
14 If the "-q" flag is used and a file fails to parse, the original file
15 contents will be output.
16 If no files are passed in, this will read from stdin.
18 use "filesystem"
19 use "consolecolor"
20 use "commandline"
22 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 command line program with $args:
25 if (#$args.extras < 2):
26 fail ("
27 Usage: nomsu -t replace [--literal="$v1 $v2..."] <pattern> <replacement> file1 file2...
28 ")
29 $pattern = $args.extras.1
30 $replacement = $args.extras.2
31 $pattern_tree = ($pattern parsed)
32 $replacement_tree = ($replacement parsed)
33 $literal_vars = {}
34 if $args.literal:
35 for $var in ($args.literal, all matches of "$([^ ]*)"):
36 $literal_vars.$var = (yes)
38 if (($pattern_tree.type == "Var") and (not $literal_vars.($pattern_tree.1))):
39 fail "Pattern matches every part of the file."
41 $pattern_vars = {:
42 for $ in recursive $pattern_tree:
43 if (($.type == "Var") and (not $literal_vars.($.1))): add $.1
44 for $child in $:
45 if ($child is "a Syntax Tree"):
46 recurse $ on $child
49 ### TODO: support wildcards and unpacking
50 e.g. nomsu -t replace "test(: $test; *$more_tests)" "*$more_tests; *$test"
51 ($tree matches $patt with $substitution_values) means:
52 ### TODO: optimize
53 $substitution_values = {: for ($k = $v) in $substitution_values: add $k = $v}
54 when:
55 (not ($tree is syntax tree)): return (no)
56 (($patt.type == "Var") and $pattern_vars.($patt.1)):
57 if $substitution_values.($patt.1):
58 if ($tree == $substitution_values.($patt.1)):
59 return $substitution_values
60 ..else:
61 return (nil)
62 ..else:
63 $substitution_values.($patt.1) = $tree
64 return $substitution_values
66 ($tree.type != $patt.type): return (nil)
67 ($tree.type == "Action"):
68 if (($tree, get stub) != ($patt, get stub)): return (nil)
70 for $ in (1 to #$patt):
71 if ($patt.$ is syntax tree):
72 $new_values = ($tree.$ matches $patt.$ with $substitution_values)
73 unless $new_values:
74 return (nil)
76 for ($k = $v) in $new_values:
77 $substitution_values.$k = $v
78 ..else:
79 unless ($tree.$ == $patt.$): return (nil)
81 if (#$tree != #$patt):
82 return (nil)
84 return $substitution_values
85 $filenames = ($args.extras, from 3 to -1)
86 if (#$filenames == 0):
87 say ("
88 Warning: searching stdin (ctrl-d to abort). To avoid this message, use nomsu -t find -
89 ")
90 $filenames = ["stdin"]
92 for $filename in $filenames:
93 $file = (read file $filename)
94 unless $file:
95 fail "File does not exist: \$filename"
96 $code = (NomsuCode from ($Source $filename 1 #$file) $file)
97 try:
98 $tree = ($code parsed)
99 ..if it fails with $msg:
100 if $args.q:
101 unless $args.i:
102 say $code
103 ..else:
104 say $msg
106 unless $tree:
107 do next $filename
109 $replaced = {}
110 $matched = {}
111 $user_answers = {}
112 ($tree with replacements) means
113 $tree, with
114 for $t:
115 $values = ($t matches $pattern_tree with {})
116 if $values:
117 $matched.$t = (yes)
118 for ($k = $v) in $values:
119 $values.$k = ($v with replacements)
120 $ret = ($replacement_tree, with $values)
121 if ($args.i and (not $args.f)):
122 if ($user_answers.$t == (nil)):
123 if (#$user_answers > 0): say ""
124 $user_answers.$t = "n"
125 say "\(bright)Should this:"
126 say ("
127 \(bright)\(yellow)\("\(($t with replacements) as nomsu)", with "\n" -> "\n ")\
128 ..\(reset color)
130 say "\(bright)..be replaced with:"
131 say ("
132 \(bright)\(blue)\("\($ret as nomsu)", with "\n" -> "\n ")\(reset color)
134 $user_answers.$t = (ask "\(bright)..? [Y/n]\(reset color) ")
135 if ($user_answers.$t == "n"): return (nil)
136 $replaced.$t = (yes)
137 return $ret
139 $tree2 = ($tree with replacements)
140 if $args.i:
141 if (#$user_answers > 0): say ""
142 say ("
143 \(#$replaced)/\(#$matched) replacement\("" if (#$replaced == 1) else "s") in \$filename
146 if (#$replaced > 0):
147 write "\($tree2 as nomsu)" to file $filename
148 ..else:
149 say ($tree2 as nomsu)