Skip to content

Commit d24eee4

Browse files
committed
add NO_COLOR
1 parent 9728f4a commit d24eee4

14 files changed

Lines changed: 182 additions & 101 deletions

SKILL.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ before warnings and match results.
4545

4646
Each match result prints the source line covered by the finding plus up to two
4747
lines of surrounding source context. Surrounding context lines are rendered in
48-
gray; matched source lines are rendered without gray styling.
48+
gray; matched source lines are rendered without gray styling. Set `NO_COLOR=1`
49+
to disable gray context styling and render matched source lines with `>` instead
50+
of `|`.
4951

5052
If `scan-root` is omitted, `moongrep` scans the current directory:
5153

cli_args.mbt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ priv struct CliOptions {
1414
exclude_dirs : Array[String]
1515
verbose : Bool
1616
enable_builtin_rules : Bool
17+
no_color : Bool
1718
}
1819

1920
///|
@@ -161,6 +162,14 @@ fn cli_flag_enabled(flags : Map[String, Bool], name : String) -> Bool {
161162
}
162163
}
163164

165+
///|
166+
fn no_color_enabled(env : Map[String, String]) -> Bool {
167+
match env.get("NO_COLOR") {
168+
Some(value) if value == "1" => true
169+
_ => false
170+
}
171+
}
172+
164173
///|
165174
fn docs_cli_command(
166175
docs_matches : @argparse.Matches,
@@ -206,12 +215,16 @@ fn dump_cli_command(
206215
}
207216

208217
///|
209-
fn scan_cli_options(scan_matches : @argparse.Matches) -> CliOptions raise {
218+
fn scan_cli_options(
219+
scan_matches : @argparse.Matches,
220+
env : Map[String, String],
221+
) -> CliOptions raise {
210222
let verbose = cli_flag_enabled(scan_matches.flags, "verbose")
211223
let enable_builtin_rules = cli_flag_enabled(
212224
scan_matches.flags,
213225
"enable-builtin-rules",
214226
)
227+
let no_color = no_color_enabled(env)
215228
let rules_root = last_cli_value(scan_matches.values, "rules")
216229
let rule_file = last_cli_value(scan_matches.values, "rule")
217230
let patterns = all_cli_values(scan_matches.values, "pattern")
@@ -241,6 +254,7 @@ fn scan_cli_options(scan_matches : @argparse.Matches) -> CliOptions raise {
241254
exclude_dirs,
242255
verbose,
243256
enable_builtin_rules,
257+
no_color,
244258
}
245259
}
246260

@@ -304,7 +318,7 @@ fn parse_cli_command(
304318
}
305319
match matches.subcommand {
306320
Some(("scan", scan_matches)) =>
307-
("scan", Some(scan_cli_options(scan_matches)), None)
321+
("scan", Some(scan_cli_options(scan_matches, env)), None)
308322
Some(("docs", docs_matches)) => docs_cli_command(docs_matches)
309323
Some(("dump", dump_matches)) => dump_cli_command(dump_matches)
310324
_ => raise CliError::Usage(message="missing required command", exit_code=2)

cli_wbtest.mbt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,41 @@ test "cli args parse rules root and default scan root" {
9090
inspect(options.scan_root, content=".")
9191
assert_false(options.verbose)
9292
assert_false(options.enable_builtin_rules)
93+
assert_false(options.no_color)
9394
}
9495
_ => fail("unexpected command")
9596
}
9697
}
9798

99+
///|
100+
test "cli args enable no color only when NO_COLOR is 1" {
101+
match parse_cli_command(["scan", "--rules", "custom-rules"]) {
102+
("scan", Some(options), None) => assert_false(options.no_color)
103+
_ => fail("unexpected command")
104+
}
105+
match
106+
parse_cli_command(["scan", "--rules", "custom-rules"], env={
107+
"NO_COLOR": "",
108+
}) {
109+
("scan", Some(options), None) => assert_false(options.no_color)
110+
_ => fail("unexpected command")
111+
}
112+
match
113+
parse_cli_command(["scan", "--rules", "custom-rules"], env={
114+
"NO_COLOR": "true",
115+
}) {
116+
("scan", Some(options), None) => assert_false(options.no_color)
117+
_ => fail("unexpected command")
118+
}
119+
match
120+
parse_cli_command(["scan", "--rules", "custom-rules"], env={
121+
"NO_COLOR": "1",
122+
}) {
123+
("scan", Some(options), None) => assert_true(options.no_color)
124+
_ => fail("unexpected command")
125+
}
126+
}
127+
98128
///|
99129
test "cli args parse single rule file and default scan root" {
100130
match parse_cli_command(["scan", "--rule", "custom-rules/example.yaml"]) {

e2etests/BASIC.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,26 @@ description:
4747
Found inspect() snapshots whose expected value is a plain number.
4848
Prefer numeric assertions for numeric checks.
4949
source:
50-
\x1b[90m1 | ///|\x1b[39m (escaped)
51-
\x1b[90m2 | fn has_builtin_hits(value : Int?) -> Unit {\x1b[39m (escaped)
52-
3 | inspect(1, content="1")
53-
\x1b[90m4 | assert_true(\x1b[39m (escaped)
54-
\x1b[90m5 | match value {\x1b[39m (escaped)
50+
1 | ///|
51+
2 | fn has_builtin_hits(value : Int?) -> Unit {
52+
3 > inspect(1, content="1")
53+
4 | assert_true(
54+
5 | match value {
5555
5656
testdata/builtin-rules/hit.mbt:5:5-8:6
5757
rule: moonbitlang/match_option
5858
description:
5959
Found an Option value handled with match over Some and None.
6060
Prefer if + is for simple Option checks.
6161
source:
62-
\x1b[90m3 | inspect(1, content="1")\x1b[39m (escaped)
63-
\x1b[90m4 | assert_true(\x1b[39m (escaped)
64-
5 | match value {
65-
6 | Some(inner) => inner > 0
66-
7 | None => false
67-
8 | },
68-
\x1b[90m9 | )\x1b[39m (escaped)
69-
\x1b[90m10 | }\x1b[39m (escaped)
62+
3 | inspect(1, content="1")
63+
4 | assert_true(
64+
5 > match value {
65+
6 > Some(inner) => inner > 0
66+
7 > None => false
67+
8 > },
68+
9 | )
69+
10 | }
7070
```
7171

7272
## moongrep dump --help

e2etests/INTEGRATION.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ outer_loc: testdata/inside-expr-target/src/hit.mbt:2:3-3:15
88
description:
99
Local println shadows the builtin.
1010
source:
11-
\x1b[90m1 | fn sample {\x1b[39m (escaped)
12-
\x1b[90m2 | let println = custom;\x1b[39m (escaped)
13-
3 | println("x")
14-
\x1b[90m4 | }\x1b[39m (escaped)
11+
1 | fn sample {
12+
2 | let println = custom;
13+
3 > println("x")
14+
4 | }
1515
```
1616

1717
```mooncram
@@ -21,10 +21,10 @@ rule: example
2121
description:
2222
Attrs built with `inner_html(...)` carry raw DOM content.
2323
source:
24-
\x1b[90m1 | fn hit(raw, child) {\x1b[39m (escaped)
25-
\x1b[90m2 | let attrs = @html.Attrs::build().inner_html(raw);\x1b[39m (escaped)
26-
3 | @html.div(class="x", attrs=attrs, child)
27-
\x1b[90m4 | }\x1b[39m (escaped)
24+
1 | fn hit(raw, child) {
25+
2 | let attrs = @html.Attrs::build().inner_html(raw);
26+
3 > @html.div(class="x", attrs=attrs, child)
27+
4 | }
2828
```
2929

3030
```mooncram
@@ -34,21 +34,21 @@ rule: example
3434
description:
3535
Sink call where positive match wins over patterns-not.
3636
source:
37-
\x1b[90m1 | fn sample {\x1b[39m (escaped)
38-
2 | sink(raw);
39-
\x1b[90m3 | sink(safe(raw))\x1b[39m (escaped)
40-
\x1b[90m4 | }\x1b[39m (escaped)
37+
1 | fn sample {
38+
2 > sink(raw);
39+
3 | sink(safe(raw))
40+
4 | }
4141
4242
testdata/patterns-not-structural/src/hit.mbt:3:3-3:18
4343
rule: example
4444
description:
4545
Sink call where positive match wins over patterns-not.
4646
source:
47-
\x1b[90m1 | fn sample {\x1b[39m (escaped)
48-
\x1b[90m2 | sink(raw);\x1b[39m (escaped)
49-
3 | sink(safe(raw))
50-
\x1b[90m4 | }\x1b[39m (escaped)
51-
\x1b[90m5 | \x1b[39m (escaped)
47+
1 | fn sample {
48+
2 | sink(raw);
49+
3 > sink(safe(raw))
50+
4 | }
51+
5 |
5252
```
5353

5454
```mooncram
@@ -59,8 +59,8 @@ outer_loc: testdata/patterns-not-inside/src/hit.mbt:2:3-2:18
5959
description:
6060
Wrapper payload without danger.
6161
source:
62-
\x1b[90m1 | fn sample {\x1b[39m (escaped)
63-
2 | wrapper(safe());
64-
\x1b[90m3 | wrapper(danger());\x1b[39m (escaped)
65-
\x1b[90m4 | wrapper(holder(danger()))\x1b[39m (escaped)
62+
1 | fn sample {
63+
2 > wrapper(safe());
64+
3 | wrapper(danger());
65+
4 | wrapper(holder(danger()))
6666
```

e2etests/LOAD.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ rule: example
77
description:
88
Repeated equality.
99
source:
10-
\x1b[90m1 | fn sample {\x1b[39m (escaped)
11-
2 | let same = value == value
12-
\x1b[90m3 | let x = get_user_input()\x1b[39m (escaped)
13-
\x1b[90m4 | sink(x)\x1b[39m (escaped)
10+
1 | fn sample {
11+
2 > let same = value == value
12+
3 | let x = get_user_input()
13+
4 | sink(x)
1414
1515
testdata/recursive-rule-discovery-src/hits.mbt:4:8-4:9
1616
rule: nested/example
1717
description:
1818
User input reaches sink.
1919
source:
20-
\x1b[90m2 | let same = value == value\x1b[39m (escaped)
21-
\x1b[90m3 | let x = get_user_input()\x1b[39m (escaped)
22-
4 | sink(x)
23-
\x1b[90m5 | }\x1b[39m (escaped)
20+
2 | let same = value == value
21+
3 | let x = get_user_input()
22+
4 > sink(x)
23+
5 | }
2424
```
2525

2626
```mooncram
@@ -30,10 +30,10 @@ rule: example
3030
description:
3131
User input reaches sink.
3232
source:
33-
\x1b[90m2 | let same = value == value\x1b[39m (escaped)
34-
\x1b[90m3 | let x = get_user_input()\x1b[39m (escaped)
35-
4 | sink(x)
36-
\x1b[90m5 | }\x1b[39m (escaped)
33+
2 | let same = value == value
34+
3 | let x = get_user_input()
35+
4 > sink(x)
36+
5 | }
3737
```
3838

3939
```mooncram

0 commit comments

Comments
 (0)