Grep Clone
This tutorial will be all about writing a simple grep clone in arc.
When completed our grep clone will be able to:
- Accept a
PATTERN
to search for - Accept any number of
FILES
to search - Ouptut lines of the
FILES
that match thePATTERN
to stdout, with coloring
1. Setup¶
To begin with we need to scaffold the project
Install arc if you haven't already
And create a file called grep_clone.py
that contains the following:
examples/grep_clone/1_grep_clone.py
This is just some simple scaffolding to get us started. Run it to make sure eveything is in order.
import arc
@arc.command()
def command():
print("hello there!")
command()
$ python grep_clone/1_grep_clone.py
$ python grep_clone/1_grep_clone.py --help
USAGE
1_grep_clone.py [--help] [--version]
OPTIONS
--help (-h) Shows help documentation
--version (-v) Displays the app's current version
2. Arguments¶
Next, we're going to want to add arguments to the command. For now, we'll only be implementing the PATTERN
and FILES
arguments. All of grep's many flags will be left alone for now.
examples/grep_clone/2_grep_clone.py
import re
import arc
from arc import types
@arc.command()
def command(pattern: re.Pattern, files: list[types.File.Read]):
print(pattern)
print(files)
command()
$ python grep_clone/2_grep_clone.py ^[\d+] docs/index.md docs/features.md
Invalid value for files: docs/index.md docs/features.md is not a valid list of files (No file named docs/index.md)
As you can see, we've already got a validated regex pattern, and file handles to each of the specified files.
3. Functionality¶
With type handling / data validation already out of the way, the implentation will be fairly straightfoward.
examples/grep_clone/3_grep_clone.py
Let's run this over a couple of arc's documentation files searching for references to arc
import re
import arc
from arc import color
from arc.types import File
@arc.command()
def grep(pattern: re.Pattern, files: list[File.Read]):
for file in files: # Iterate over all the files
for line in file.readlines(): # Iterate over all the line in the file
if match := pattern.search(line): # check for a match
# If there is a match, highlight it
colored = pattern.sub(
color.fg.RED + match.group() + color.effects.CLEAR,
line,
)
print(colored, end="")
grep()