DEV Community

Roy J. Wignarajah
Roy J. Wignarajah

Posted on • Updated on

My First Command-Line Tool

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 READMEfile. 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

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. This library contains various methods for working with filesystems, paths, and directories. This library provided me methods and classes for creating and iterating through directories, and checking if a path exists and is a 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 header file, which has a method called getopt(3) 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 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, 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.

Top comments (0)