My First Command-Line Tool
Tags: opensource, beginners
Published: 2023-09-18 04:37:49

## Ctil - My own "Today I learned" Command-Line Tool
As part of my Open Source Development class, we were tasked with creating a Markdown-to-HTML converter that helps users author "Today I Learned" posts. Today I Learned, or TIL's, are posts in which the author shares something new they learned, and are often used for authors to share notes with themselves and others about concepts they've discovered. The converter is meant to be built as a command-line tool to be used in the terminal, for users to convert Markdown files (as `.txt`) into `.html` files.

I chose to write my implementation in **C++** as it's the language I'm most familiar with. Many of my classmates wrote their implementation in **JavaScript** or **Python**, both of which I'm not very comfortable programming in. My implementation, which I've called Ctil (for Today-I-Learned in C++), can be found on https://github.com/rjwignar/ctil.

## How to Run
Ctil is published as a Visual Studio C++ Project. After cloning the repository, one can either run the app directly from the C++ solution file, or compile it using the g++ compiler using the `c++17 standard`. Instructions for both methods are available on the repository `README `file. However, it is important to note that g++ doesn't come out-of-box with Windows, and must be installed through MinGW (Minimalist GNU for Windows, found on https://sourceforge.net/projects/mingw/). It is also important to note that I have only tried compiling Ctil on Windows, and I cannot confirm whether compilation will succeed using g++ on Linux.

## My Implementation
Currently my implementation has the following features:

- Conversion of single text files to HTML (mandatory feature)
 - Paragraph Parsing (mandatory feature)
 - Title Parsing (optional feature)
- Conversion of all text files in a directory to HTML (non-recursive, mandatory feature)

Usage examples for the current features are shown below:

![Sample Usages](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vemq4n26oq11ha8xj27.png)


As of today I have prepared the skeleton code for but was unable to fully implement the following features:
- Flag options
 - Version (-v, --version), mandatory
 - Help (-h , --help), mandatory
 - Output (-o, --output), optional

I plan to have these features implemented in a future release.

## Lessons - The C++ Filesystem Library
Though it's not complete, I really enjoyed working on this project.  To implement the above features, I had to refresh my C++ skills and learn how to use new libraries. One new and important library I had to research was the [C++ Filesystem library](https://en.cppreference.com/w/cpp/filesystem). This library contains various methods for working with filesystems, paths, and directories. This library provided me methods and classes for [creating](https://en.cppreference.com/w/cpp/filesystem/create_directory) and [iterating](https://en.cppreference.com/w/cpp/filesystem/recursive_directory_iterator) through directories, and checking if a [path exists](https://en.cppreference.com/w/cpp/filesystem/exists) and is a [directory ](https://en.cppreference.com/w/cpp/filesystem/is_directory) vs a file, which is necessary for my program to apply directory or text file-specific logic.

## Lessons - Command Argument Processing
All of the features I was unable to implement all involved flags (or options) that modify a program/command's behaviour. Although previous classes in C++ have taught me how to work with command-line arguments, I never learned how to implement my own flag and argument parser. The POSIX standard has the [**unistd.h**](https://en.wikipedia.org/wiki/Unistd.h) header file, which has a method called [getopt(3)](https://man7.org/linux/man-pages/man3/getopt.3.html) that parses command-line arguments and would have been very useful for this project. However, the unistd.h library is not native to Windows systems or Visual Studio, and although open-source libraries like [libunistd](https://github.com/robinrowe/libunistd) are a solution, I wanted to try and implement one myself.

Though the logic is incomplete, I was able to draft a skeleton of the flag parsing, by referring to [Randomizer by Matt Early](https://github.com/mattearly/Randomizer), a command-line tool that  simulates dice rolls and calculates odds and percentages. **Randomizer** implements a flag parser without unistd.h or other external libraries, and I was able to adapt it to fit my usage requirements. In future releases, I would like to finish adding logic for each flag.