From 8ccbf252e3d3910081de920b2388204e425400c0 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Thu, 7 Apr 2016 16:16:41 +0200 Subject: Implement proper CLI argument handling using `boost::program_options` Became necessary due to the introduction of custom line offset as an additional user-defined parameter. --- CMakeLists.txt | 5 +++ justify.cc | 85 ++++++++++++++++++++++++++++++++++++++++++++----- src/line_accumulator.cc | 10 +++++- src/line_accumulator.h | 3 +- 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce0a332..656fe91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,11 @@ add_executable( src/line_accumulator.cc ) +target_link_libraries( + justify + boost_program_options +) + install( TARGETS justify diff --git a/justify.cc b/justify.cc index b20496c..8120ded 100644 --- a/justify.cc +++ b/justify.cc @@ -1,32 +1,101 @@ #include #include +#include +#include + #include "line_accumulator.h" -int main(int argc, char* argv[]) { +boost::optional input( + int argc, char* argv[]) { + boost::program_options::options_description optionDescription( + "Supported options" + ); + + optionDescription.add_options() + ( + "length", + boost::program_options::value(), + "Output line length" + ) + ( + "offset", + boost::program_options::value(), + "Number of spaces to be prepended on each line" + ) + ; + + boost::program_options::variables_map variables; + + try { + boost::program_options::store( + boost::program_options::parse_command_line( + argc, argv, optionDescription + ), + variables + ); + + boost::program_options::notify(variables); + } + catch ( const std::exception& exception ) { + std::cerr << exception.what() << std::endl; + std::cout << optionDescription << std::endl; + + return boost::optional(); + } + + return boost::make_optional(variables); +} + +bool process(const boost::program_options::variables_map& variables) { std::cout.sync_with_stdio(false); std::cin.sync_with_stdio(false); - std::uint8_t max_line_length = 60; + std::uint8_t line_length = 60; + std::uint8_t line_offset = 0; - if ( argc == 2 ) { - const int user_length = std::stoi(argv[1]); + if ( variables.count("length") ) { + const int user_length = variables["length"].as(); if ( user_length > 1 && user_length < 256 ) { - max_line_length = user_length; + line_length = user_length; } else { std::cerr << "Invalid line length.\n"; - return -1; + return false; } } - justify::LineAccumulator acc{max_line_length}; + if ( variables.count("offset") ) { + const int user_offset = variables["offset"].as(); + + if ( user_offset >= 0 && user_offset < 256 ) { + line_offset = user_offset; + } else { + std::cerr << "Invalid line offset.\n"; + + return false; + } + } + + justify::LineAccumulator acc{line_length, line_offset}; std::string token; while ( std::cin >> token ) { acc(token); } - return 0; + return true; +} + +int main(int argc, char* argv[]) { + if ( auto variables = input(argc, argv) ) { + if ( process(*variables) ) { + return 0; + } else { + return 1; + } + } else { + return 1; + } } diff --git a/src/line_accumulator.cc b/src/line_accumulator.cc index d12ef54..31b8ddc 100644 --- a/src/line_accumulator.cc +++ b/src/line_accumulator.cc @@ -54,8 +54,12 @@ std::size_t getCharacterLength(const std::string& token) { namespace justify { -LineAccumulator::LineAccumulator(const std::uint8_t max_length): +LineAccumulator::LineAccumulator( + const std::uint8_t max_length, + const std::uint8_t offset +): max_length_{max_length}, + offset_{offset}, length_{0}, tokens_{} { } @@ -160,6 +164,10 @@ void LineAccumulator::discharge(const bool full) { this->justify(); } + if ( this->offset_ > 0 ) { + std::cout << std::string(this->offset_, ' '); + } + for ( const auto& token : this->tokens_ ) { std::cout << token.first << std::string(token.second, ' '); diff --git a/src/line_accumulator.h b/src/line_accumulator.h index 2ca271c..69b4c74 100644 --- a/src/line_accumulator.h +++ b/src/line_accumulator.h @@ -9,7 +9,7 @@ namespace justify { class LineAccumulator { public: - LineAccumulator(const std::uint8_t max_length); + LineAccumulator(const std::uint8_t max_length, const std::uint8_t offset); ~LineAccumulator(); std::uint8_t getMissing() const; @@ -18,6 +18,7 @@ class LineAccumulator { private: const std::uint8_t max_length_; + const std::uint8_t offset_; std::uint8_t length_; -- cgit v1.2.3