diff --git a/.gitignore b/.gitignore index 132c5ef..5d9b45e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ course-definition-tester .history/ + +## MacOS +.DS_Store diff --git a/course-definition.yml b/course-definition.yml index 8a9cd42..895eb52 100644 --- a/course-definition.yml +++ b/course-definition.yml @@ -76,6 +76,16 @@ extensions: Along the way, you'll learn about how to implement the `*` quantifier (zero or more), and bounded quantifiers. [1]: https://learn.microsoft.com/en-us/dotnet/standard/base-types/quantifiers-in-regular-expressions + - slug: "highlighting" + name: "Highlighting" + description_markdown: | + In this challenge extension, you'll add support for [highlighting][1] to your Grep implementation. + + Along the way, you'll learn about [ANSI escape codes][2], and more. + + [1]: https://linuxcommando.blogspot.com/2007/10/grep-with-color-output.html + [2]: https://en.wikipedia.org/wiki/ANSI_escape_code + stages: - slug: "cq2" name: "Match a literal character" @@ -304,3 +314,39 @@ stages: difficulty: hard marketing_md: |- In this stage, we'll add support for `{n,m}`, the [between n and m times](https://docs.microsoft.com/en-us/dotnet/standard/base-types/quantifiers-in-regular-expressions#match-between-n-and-m-times-nm) quantifier. + + # Highlighting + - slug: "bm2" + primary_extension_slug: "highlighting" + name: "Highlighting a single match" + difficulty: hard + marketing_md: |- + In this stage, you'll add support for highlighting a single match in your grep implementation. + + - slug: "eq0" + primary_extension_slug: "highlighting" + name: "Highlighting multiple matches" + difficulty: hard + marketing_md: |- + In this stage, you'll add support for highlighting multiple matches in your grep implementation. + + - slug: "jk4" + primary_extension_slug: "highlighting" + name: "Disabling highlighting" + difficulty: easy + marketing_md: |- + In this stage, you'll add support for disabling the highlighting in your grep implementation using the `never` coloring option. + + - slug: "na5" + primary_extension_slug: "highlighting" + name: "Auto highlighting option" + difficulty: medium + marketing_md: |- + In this stage, you'll add support for `auto` coloring option in the `--color` flag in your grep implementation. + + - slug: "nd0" + primary_extension_slug: "highlighting" + name: "Default highlighting behavior" + difficulty: easy + marketing_md: |- + In this stage, you'll implement the `auto` coloring option as the default coloring option when the `--color` flag is not present. \ No newline at end of file diff --git a/stage_descriptions/highlighting-01-bm2.md b/stage_descriptions/highlighting-01-bm2.md new file mode 100644 index 0000000..85de8c2 --- /dev/null +++ b/stage_descriptions/highlighting-01-bm2.md @@ -0,0 +1,92 @@ +In this stage, you'll add support for highlighting a single match in your grep implementation. + +### Highlighting the matched text + +When `--color=always` option is used with grep, it always highlights the matched text in its output. + +Example usage: + + +
+$ echo -n "I have 1 apple" | grep --color=always -E '\d'
+I have 1 apple
+
+ + +Grep uses [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code) to add color to terminal output. These are special character sequences that terminals interpret as formatting commands rather than regular text. + +The default color used by grep for the matched text is bold red. For example, grep uses the following ANSI escape sequences for wrapping the matched text: + +``` +\033[01;31m\033[K +... +\033[m\033[K +``` + +**Exaple Opening Sequence: `\033[01;31m\033[K`** + +| Component | Meaning | +|-----------|---------| +| `\033` | Escape character that introduces the ANSI control sequence | +| `[` | Start marker for [Select Graphic Rendition (SGR)](https://vt100.net/docs/vt510-rm/SGR.html) parameters | +| `01;31` | SGR codes: `01` = bold/bright text, `31` = red foreground color (separated by `;`) | +| `m` | Terminates the SGR sequence | +| | +| `\033` | Escape character that introduces the ANSI control sequence | +| `[` | Start marker for SGR parameters | +| `K` | Erase all characters to the right of the cursor | + +**Example Closing Sequence: `\033[m\033[K`** + +| Component | Meaning | +|-----------|---------| +| `\033` | Escape character that introduces the ANSI control sequence | +| `[` | Start marker for SGR parameters | +| *(empty)* | No parameters = reset all attributes to default | +| `m` | Terminates the SGR sequence | +| | +| `\033` | Escape character that introduces the ANSI control sequence +| `[` | Start marker for SGR parameters | +| `K` | Erase all characters to the right of the cursor | + +When the SGR parameter is `0` or is not present (empty), it resets all attributes so that the rest of the text will be printed without any highlights. + +### Tests + +The tester will execute your program like this: + + +
+$ echo -n "I have 3 apples" | grep --color=always -E '\d'
+I have 3 apples
+
+ + +If the input does not match the pattern, your program must: +- Exit with the code 1 +- Exit with no printed output + +If the input text matches the pattern, your program must: +- Exit with the code 0 +- Print the input text to the standard output +- Highlight the matched text in the input using the grep's default color. + +### Notes + +1. You only need to handle the case of single match. We'll get to highlighting multiple matches in the next stage. + +2. The matched text should highlighted using the bold (`01`) and red (`31`) attributes. You may use any combination of ANSI codes to achieve this highlighting effect. For example, to produce the following output: + + +
+hellomatchedworld
+
+ + +Any of the following sequences can be used + +``` +hello\033[31;01m\033[Kmatched\033[m\033[Kworld +hello\033[31;01m\033[K\033[Kmatched\033[m\033[K\033[Kworld +hello\033[01;31m\033[Kmatched\033[m\033[Kworld +``` \ No newline at end of file diff --git a/stage_descriptions/highlighting-02-eq0.md b/stage_descriptions/highlighting-02-eq0.md new file mode 100644 index 0000000..d3bb8a8 --- /dev/null +++ b/stage_descriptions/highlighting-02-eq0.md @@ -0,0 +1,42 @@ +In this stage, you'll add support for highlighting multiple matches in your grep implementation. + +### Highlighting multiple matches + +Grep highlights all the matching texts it can find in each line. + +Example usage: + + +
+$ echo -n "dogs and cats are pets" | grep --color=always -E '(dogs|cats)'
+dogs and cats are pets
+
+ + +### Tests + +The tester will execute your program like this: + + +
+$ echo -n "jekyll and hyde" | grep --color=always -E '(jekyll|hyde)'
+jekyll and hyde
+
+$ echo -n "2025" | grep --color=always -E '\d' +2025
+ + +If the input does not match the pattern, your program must: +- Exit with the code 1 +- Exit with no printed output + +If the input text matches the pattern, your program must: +- Exit with the code 0 +- Print the input text to the standard output +- Highlight all the matched texts in the input using the grep's default color. + +### Notes + +- The tester accepts multiple valid ANSI-encoded representations of the same highlighted text. To display the bold red text: 2025, any equivalent combination is acceptable. Example of valid ANSI sequences: + - `\u001b[1;31m2025\u001b[0m` + - `\u001b[1;31m20\u001b[0m\u001b[1;31m25\u001b[0m` diff --git a/stage_descriptions/highlighting-03-jk4.md b/stage_descriptions/highlighting-03-jk4.md new file mode 100644 index 0000000..194738d --- /dev/null +++ b/stage_descriptions/highlighting-03-jk4.md @@ -0,0 +1,30 @@ +In this stage, you'll add support for disabling the highlighting in your grep implementation using the `never` coloring option. + +### The `--color=never` option + +When a line is matched, grep only prints the matched line to the standard output. It does not highlight the matched text. + +Example usage: + +```bash +$ echo -n "Sally has 3 parrots" | grep --color=never -E "par+ots?" +Sally has 3 parrots +``` + +### Tests + +The tester will execute your program like this: + +```bash +$ echo -n "I have 5 vegetables" | grep --color=never -E '\d' +I have 5 vegetables +``` + +If the input matches the pattern, your program must: +- Exit with the code 0 +- Print the input line to the standard output +- No highlights should be placed in the output text because `--color=never` option is being used. + +If the input does not match the pattern, your program must: +- Exit with the code 1 +- Exit with no printed output \ No newline at end of file diff --git a/stage_descriptions/highlighting-04-na5.md b/stage_descriptions/highlighting-04-na5.md new file mode 100644 index 0000000..91c9241 --- /dev/null +++ b/stage_descriptions/highlighting-04-na5.md @@ -0,0 +1,82 @@ +In this stage, you'll add support for `auto` coloring option in the `--color` flag in your grep implementation. + +### The `auto` color option + +When `--color=auto` option is used with grep, it behaves in the following manner: + +- If the output stream is a [TTY device](https://www.ibm.com/docs/en/aix/7.1.0?topic=communications-tty-terminal-device), like the terminal, highlighting is enabled. + +- If the output stream is not a TTY device, for example, the output is piped to another command, or being redirected to a non-TTY device, highlighting is disabled. + +Example usage: + + +
+$ echo -n "I have 3 cows" | grep --color=auto -E 'cows'
+I have 3 cows
+$ echo -n "I have 4 cows" | grep --color=auto -E 'cows' >> /dev/tty
+I have 4 cows
+
+ + +The output text is highlighted in this case since the output in both cases is a TTY device. + +When the output stream is piped to another command, or redirected to a non-TTY device, the ANSI highlighting sequences are not placed in the output text. + +```bash +# Output stream is piped to another command +$ echo -n "I have 3 apples" | grep --color=auto -E '\d' | hexdump -C +00000000 49 20 68 61 76 65 20 33 20 61 70 70 6c 65 73 0a |I have 3 apples.| +00000010 + +# Output stream is redirected to a non-TTY device +$ echo -n "I have 4 apples" | grep --color=auto -E '\d' >> output.txt + +$ hexdump -C output.txt +00000000 49 20 68 61 76 65 20 34 20 61 70 70 6c 65 73 0a |I have 4 apples.| +00000010 +``` + +### Tests + +The tester will execute your program like this: + + +
+$ echo -n "I have 4 cats" | grep --color=auto -E 'cats'
+I have 4 cats
+$ echo -n "I have 5 cats" | grep --color=auto -E 'cats' >> /dev/tty
+I have 5 cats
+
+ + +If the input does not match the pattern, your program must: +- Exit with the code 1 + +If the input text matches the pattern, your program must: +- Exit with the code 0 +- Print the input text to the standard output +- The matched text in the output should be highlighted + +The tester will also execute your program like this: + +```bash +# Redirection to a non-tty device +$ echo -n "I have 3 horses" | grep --color=auto -E '\d' >> file.txt + +# Piping to another command +$ echo -n "He has 9 rabbits" | grep --color=auto -E '\d' | another_command +``` + +For both of these cases, +If the input does not match the pattern, your program must: +- Exit with the code 1 +- Exit with no printed output + +If the input text matches the pattern, your program must exit with the code 0 and +- The input text should be written to the file `file.txt`, or be supplied to another command, depending on the case. +- The ANSI escape sequence for highlighting should not be present inside the file, or supplied to another command, depending on the case. + +### Notes + +- You might find it helpful to use the equivalent of [`isatty()`](https://man7.org/linux/man-pages/man3/isatty.3.html) function in your programming language to check whether the output stream is a TTY device. \ No newline at end of file diff --git a/stage_descriptions/highlighting-05-nd0.md b/stage_descriptions/highlighting-05-nd0.md new file mode 100644 index 0000000..34560f1 --- /dev/null +++ b/stage_descriptions/highlighting-05-nd0.md @@ -0,0 +1,69 @@ +In this stage, you'll implement the `auto` coloring option as the default coloring option when the `--color` flag is not present. + +### The default behavior + +When the `--color` flag is not present, it is equivalent of using grep with the `--color=auto` option. + +Example usage: + + +
+$ echo -n "I have 3 cows" | grep -E 'cows'
+I have 3 cows
+$ echo -n "I have 4 cows" | grep -E 'cows' >> /dev/tty
+I have 4 cows
+
+ + +The output text is highlighted in this case. + +When the output stream is piped to another command, or redirected to a non-TTY device, the ANSI highlighting sequences are not placed in the output text. + +```bash +# Output stream is piped to another command +$ echo -n "I have 3 apples" | grep --color=auto -E '\d' | hexdump -C +00000000 49 20 68 61 76 65 20 33 20 61 70 70 6c 65 73 0a |I have 3 apples.| +00000010 + +# Output stream is redirected to a non-TTY device +$ echo -n "I have 4 apples" | grep --color=auto -E '\d' >> output.txt + +$ hexdump -C output.txt +00000000 49 20 68 61 76 65 20 34 20 61 70 70 6c 65 73 0a |I have 4 apples.| +00000010 +``` + +### Tests + +The tester will execute your program like this: + +```bash +$ echo -n "I have 3 horses" | grep -E '\d' +``` + +If the input does not match the pattern, your program must: +- Exit with the code 1 +- Exit with no printed output + +If the input text matches the pattern, your program must: +- Exit with the code 0 +- Print the input text to the standard output +- The matched text in the output should be highlighted + +The tester will also execute your program like this: + +```bash +# Redirection to a non-tty device +$ echo -n "I have 3 horses" | grep -E '\d' >> file.txt + +# Piping to another command +$ echo -n "He has 9 rabbits" | grep -E '\d' | another_command +``` + +For both of these cases, +If the input does not match the pattern, your program must: +- Exit with the code 1 + +If the input text matches the pattern, your program must exit with the code 0 and +- The input text should be written to the file `file.txt`, or be supplied to another command, depending on the case. +- The ANSI escape sequence for highlighting should not be present inside the file, or supplied to another command, depending on the case. \ No newline at end of file