Implementation of cat(1) CLI utility from scratch in C following the Build Your Own Cat Tool coding challenge.
It took me ~2hrs to write the program, and over a day to write test :/
To setup and run this project locally, please follow the below steps:
-
C/C++ Compiler: Please make sure that you have a C/C++ compiler installed on your system, preferably gcc or clang.
-
Install make:
If you are using Mac, and have Homebrew installed, use :
brew install make- Clone the project on your machine.
https://github.com/MahendraDani/cat.git
- Build from source
First change directory, cd cat, then
makeThis command will build the project from source, and output the executable bin/cat.
To verify clean installation, try running:
bin/cat data/test.txtYou should be able to see the data/test.txt file printed on the console.
For usage, please read the man page of cat(1). Note that, only -n and -b are supported in the current version.
- Read input from a file
bin/cat file.txt- Read from multiple files and concatenate
bin/cat file1.txt file2.txt file3.txt- Read from stdin
bin/cat -- Show line numbers
bin/cat -n file.txt- Show line numbers (excluding blank lines)
bin/cat -b file.txtAlthough writing tests was not included in the challenge, any program to be called "production-ready" should and must be appropriately tested. So I wrote a few tests in shell scripts to test my code.
Much of the inspiration of writing tests is taken from the git project (as you can see from the names of test files :P) which has a lot of tests written in shell scripts.
This also forced me to learn about shell scripting, unit testing and much more, which is also essential in writing good software.
To run the test suite, simply run :
make testIf you want to specially run a particular test file:
tests/t0001.shThe project itself was meant to complete the coding challenge, which it has full-filled. Though, if found necessary, I might refactor it in the future.
Things that can be improved:
-
namings : struct
configdoesn't not explain what configurations it holds. I mean using nameconfigfor storing the flags specified by the user is really not a config, is it? -
parsing arguments and flags : Supporting two flags with if-else is ok, but not scalable. I would probably use a library to parse flags, but I really want to write my own, as I see myself doing the same thing again and again for all the challenges I will attempt in the future that require building a CLI utility.