diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..80ea917 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,116 @@ +# Copyright (c) 2019 Álvaro Ceballos +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + + +cmake_minimum_required(VERSION 3.11) + + +set(detail_header_files + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/arg_value_holder.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/call_status_holder.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/help_generation_helpers.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/is_flag_aliases_naming_valid.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/is_in_string_vector.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/join_all_parser_flags.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/make_flag_aliases_list.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/multiple_flag_arg_values_holder.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/multiple_flag_getters_maker.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/name_of_arg_type.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/parser_helper.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/parser_runtime_data_holder.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/remove_zeroes_from_string.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/set_values_from_strings.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/detail/string_parsing_helper.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/preprocessor/detail/flag_argument_helpers.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/preprocessor/detail/get_argument_helpers.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/preprocessor/detail/pp_concat.hpp +) + + +set(header_files + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/config.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/preprocessor/pp_flag.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/preprocessor/pp_flag_arguments.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/preprocessor/pp_parser.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/argument_type.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/argument_types_list.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/finish_at.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/flag.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/flag_arguments.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/generate_list_of_flags.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/get_as_tuple.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/help_parameters.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/is_switch.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/number_of_flag_args.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/parser.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/parser_parameters.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/start_at.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/exceptions/bad_argument_parsing.hpp + ${PROJECT_SOURCE_DIR}/include/cynodelic/metaflags/fwd/parser_fwd.hpp +) + + +# Gets the version +file(READ include/cynodelic/metaflags/config.hpp _ver_impl) + +string(REGEX MATCH "#define CYNODELIC_METAFLAGS_VERSION_MAJOR ([0-9]+)(.*)" _ ${_ver_impl}) +set(cynodelic_metaflags_ver_major ${CMAKE_MATCH_1}) + +string(REGEX MATCH "#define CYNODELIC_METAFLAGS_VERSION_MINOR ([0-9]+)(.*)" _ ${_ver_impl}) +set(cynodelic_metaflags_ver_minor ${CMAKE_MATCH_1}) + +string(REGEX MATCH "#define CYNODELIC_METAFLAGS_VERSION_PATCH ([0-9]+)(.*)" _ ${_ver_impl}) +set(cynodelic_metaflags_ver_patch ${CMAKE_MATCH_1}) + +set(cynodelic_metaflags_ver_string "${cynodelic_metaflags_ver_major}.${cynodelic_metaflags_ver_minor}.${cynodelic_metaflags_ver_patch}") + +message("Cynodelic::Metaflags, version ${cynodelic_metaflags_ver_string}") + + +# Project name and version +project(cynodelic_metaflags VERSION ${cynodelic_metaflags_ver_string} LANGUAGES CXX) + + +# Options +option(CYNODELIC_METAFLAGS_BUILD_EXAMPLES "Builds the examples" OFF) +option(CYNODELIC_METAFLAGS_BUILD_DOC "Builds the corresponding documentation" OFF) +option(CYNODELIC_METAFLAGS_BUILD_TEST "Builds the unit tests" ON) +set(CMAKE_CXX_STANDARD 14) + +# Path to Mulinum doc directory +set(CYNODELIC_METAFLAGS_MULINUM_DOC_DIR "" CACHE PATH "Path of Mulinum\'s \"doc\" directory") + + +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic") +endif() + + +# Library operations +add_library(metaflags INTERFACE) +target_sources(metaflags INTERFACE $) +target_include_directories(metaflags INTERFACE $) + +install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/cynodelic" DESTINATION include) + + +# Builds unit tests +if (CYNODELIC_METAFLAGS_BUILD_TEST) + enable_testing() + add_subdirectory(test) +endif() + + +# Builds examples +if (CYNODELIC_METAFLAGS_BUILD_EXAMPLES) + add_subdirectory(example) +endif() + + +# Builds documentation +if (CYNODELIC_METAFLAGS_BUILD_DOC) + add_subdirectory(doc) +endif() diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d0b18b5 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Metaflags + +A header-only, C++14 library for parsing command-line arguments, which is based on template metaprogramming and magic statics. + +## Requirements + +- A C++14-compatible compiler +- [Mulinum](https://github.com/cynodelic/mulinum) + +## Building and installation + +This library is header-only, so no building is necessary for installing it. However, the examples, unit tests and documentation need to be built, using [CMake](http://cmake.org/). + +Run `mkdir build && cd build && cmake [options] .. && make` (or your equivalent) for building. + +### Building the examples + +Use the `-DCYNODELIC_METAFLAGS_BUILD_EXAMPLES=1` option for building the examples. + +### Building and running the tests + +Use the `-DCYNODELIC_METAFLAGS_BUILD_TEST=1` option for building the unit tests. + +Run the tests using `make test`. + +### Building the documentation + +The documentation is generated with [Doxygen](http://www.doxygen.nl/), if avaliable. + +Use the `-DCYNODELIC_METAFLAGS_BUILD_DOC=1` for allowing its generation. + +#### Linking with Mulinum's documentation + +To link with Mulinum's documentation, set the path to it using the `-DCYNODELIC_METAFLAGS_MULINUM_DOC_DIR=/path/to/your/mulinum/doc` option. + +### Installing the library + +The installation path is set using the `-DCMAKE_INSTALL_PREFIX=path/to/your/libraries` option. + +Run `make install` to install the library, as well as its documentation. + +The documentation will be installed in `path/to/your/libraries/doc/cynodelic/metaflags`. + +## License +This library is licensed under the Boost Software License. diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..5741706 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2019 Álvaro Ceballos +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + + +find_package(Doxygen REQUIRED) + +if(NOT DOXYGEN_FOUND) + message(WARNING "Doxygen was not found; the documentation files will not be built.") + return() +endif() + + +set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}) +set(DOXYGEN_OUTPUT_DIR ${PROJECT_BINARY_DIR}/doc/cynodelic/metaflags) + + +configure_file(${PROJECT_SOURCE_DIR}/doc/Doxyfile.in ${PROJECT_SOURCE_DIR}/doc/Doxyfile @ONLY) +add_custom_target(doc ALL + COMMAND ${CMAKE_COMMAND} -E echo_append "Building documentation..." + COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR} + COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_SOURCE_DIR}/doc/Doxyfile + COMMAND ${CMAKE_COMMAND} -E echo "Done." + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} +) + +install(DIRECTORY ${DOXYGEN_OUTPUT_DIR} + DESTINATION ${CMAKE_INSTALL_PREFIX}/doc/cynodelic + COMPONENT doc +) + +install(FILES ${PROJECT_SOURCE_DIR}/doc/cynodelic_metaflags_tagfile.tag + DESTINATION ${CMAKE_INSTALL_PREFIX}/doc/cynodelic/metaflags +) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..ffeebf2 --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,14 @@ +PROJECT_NAME = Metaflags +PROJECT_NUMBER = @PROJECT_VERSION@ +OUTPUT_DIRECTORY = @DOXYGEN_OUTPUT_DIR@ +OUTPUT_LANGUAGE = English +EXTRACT_ALL = YES +ENABLE_PREPROCESSING = YES +PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS +INPUT = @DOXYGEN_INPUT_DIR@/doc/doxygen_defs.hpp @DOXYGEN_INPUT_DIR@/include/cynodelic/metaflags/ @DOXYGEN_INPUT_DIR@/include/cynodelic/metaflags/exceptions/ @DOXYGEN_INPUT_DIR@/include/cynodelic/metaflags/preprocessor/ +RECURSIVE = NO +PDF_HYPERLINKS = YES +USE_PDFLATEX = NO +HAVE_DOT = YES +TAGFILES = @CYNODELIC_METAFLAGS_MULINUM_DOC_DIR@/cynodelic/mulinum/cynodelic_mulinum_tagfile.tag=file://@CYNODELIC_METAFLAGS_MULINUM_DOC_DIR@/cynodelic/mulinum/html +GENERATE_TAGFILE = @DOXYGEN_INPUT_DIR@/doc/cynodelic_metaflags_tagfile.tag \ No newline at end of file diff --git a/doc/doxygen_defs.hpp b/doc/doxygen_defs.hpp new file mode 100644 index 0000000..2e64e29 --- /dev/null +++ b/doc/doxygen_defs.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + + +/** + * @defgroup configuration_ Configuration utilities + * + * Utilities for the configurations of this library. + */ + +/** + * @defgroup types Types + * + * The types used in this library. + */ + +/** + * @defgroup flags Flag types + * @ingroup types + * + * The types corresponding to the command-line flags. + */ + +/** + * @defgroup flagargs Flag arguments + * @ingroup types + * + * The types corresponding to the flag arguments, used in `flag`. + */ + +/** + * @defgroup parsing Parsing + * + * Stuff related to the parsing of the command-line arguments. + */ + +/** + * @defgroup parsingparams Parameters for parsing + * @ingroup parsing + * + * Parameters related to the position of the first and last arguments to be + * parsed. + * + * Used in `parser_parameters`. + */ + +/** + * @defgroup startatparams "Start-at" parameters + * @ingroup parsingparams + * + * Parameters related to the first argument to parse. + */ + +/** + * @defgroup finishatparams "Finish-at" parameters + * @ingroup parsingparams + * + * Parameters related to the last argument to parse. + */ + +/** + * @defgroup helpgeneration Help generation + * + * Stuff for help generation. + */ + +/** + * @defgroup helpparams Holders for help generation parameters + * @ingroup helpgeneration + * + * Types used for holding the help generation parameters. + */ + +/** + * @defgroup helpparamsargs Parameters for help generation + * @ingroup helpparams + * + * Arguments used in `help_parameters` for the generation of help. + */ + +/** + * @defgroup typetraits_ Type traits + * + * Type traits and operations. + */ diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 0000000..f9aa582 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2019 Álvaro Ceballos +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + + +set(example_names + custom_help_parameters + get_as_tuple + runtime_start_at + switches + two_parsers +) + +foreach(example_nm ${example_names}) + add_executable(${example_nm} ${example_nm}.cpp) + target_include_directories(${example_nm} PUBLIC ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include ${image_libs_libraries}) +endforeach() diff --git a/example/custom_help_parameters.cpp b/example/custom_help_parameters.cpp new file mode 100644 index 0000000..16586d5 --- /dev/null +++ b/example/custom_help_parameters.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#include +#include + + +namespace mln = cynodelic::mulinum; +namespace mfl = cynodelic::metaflags; + + +#ifndef STRING_ +#define STRING_ CYNODELIC_METAFLAGS_STRING +#endif + +#ifndef FLAG_ +#define FLAG_ CYNODELIC_METAFLAGS_FLAG +#endif + +#ifndef SWITCH_ +#define SWITCH_ CYNODELIC_METAFLAGS_SWITCH +#endif + +#ifndef WAS_CALLED +#define WAS_CALLED CYNODELIC_METAFLAGS_WAS_CALLED +#endif + +#ifndef I32_ARG +#define I32_ARG CYNODELIC_METAFLAGS_I32_ARG +#endif + +#ifndef STR_ARG +#define STR_ARG CYNODELIC_METAFLAGS_STR_ARG +#endif + + +using my_parser = mfl::parser< + mfl::parser_parameters< + mfl::help_parameters< + mfl::flag_tabulation<8>, /* <-- Spaces from the left to the flag aliases */ + mfl::flag_help_tabulation<2>, /* <-- Spaces from the flag aliases to their descriptions */ + mfl::usage_format, /* <-- it will be "Usage: the_program [the options...]" */ + mfl::flag_aliases_delimiter<';'>, /* <-- "--flag;-f" instead of "--flag/-f" */ + mfl::flags_list_header, + mfl::help_flag, /* <-- to call the help with "--usage/-u" */ + mfl::print_help_if_no_arguments /* <-- Displays the help if no arguments were set */ + > + >, + FLAG_("test_a,ta","A test flag.",I32_ARG("first"),I32_ARG("second"),I32_ARG("third")), + FLAG_("test_b,tb","Another test flag.",I32_ARG("argument 1"),I32_ARG("argument 2")), + SWITCH_("thing,t","A test switch.") +>; + + +int main(int argc,char *argv[]) +{ + // Use "--usage/-u" instead of "--help/-h" + my_parser::parse(argc,argv); +} + diff --git a/example/get_as_tuple.cpp b/example/get_as_tuple.cpp new file mode 100644 index 0000000..34c26a3 --- /dev/null +++ b/example/get_as_tuple.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace mln = cynodelic::mulinum; +namespace mfl = cynodelic::metaflags; + + +#ifndef STRING_ +#define STRING_ CYNODELIC_METAFLAGS_STRING +#endif + +#ifndef FLAG_ +#define FLAG_ CYNODELIC_METAFLAGS_FLAG +#endif + +#ifndef SWITCH_ +#define SWITCH_ CYNODELIC_METAFLAGS_SWITCH +#endif + +#ifndef WAS_CALLED +#define WAS_CALLED CYNODELIC_METAFLAGS_WAS_CALLED +#endif + +#ifndef GET_ARGUMENT +#define GET_ARGUMENT CYNODELIC_METAFLAGS_GET_ARGUMENT +#endif + + +using my_parser = mfl::parser< + FLAG_("flag1,f1","Flag 1",mfl::str_arg<>,mfl::i64_arg<>), + FLAG_("flag2,f2","Flag 2",mfl::flt_arg<>,mfl::bln_arg<>,mfl::u8_arg<>) +>; + +using flag1_args_t = mfl::argument_types_list; +using flag2_args_t = mfl::argument_types_list; + + +int main(int argc,char *argv[]) +{ + my_parser::parse(argc,argv); + + flag1_args_t flag1_content = mfl::get_as_tuple({"nothing",0}); + flag2_args_t flag2_content = mfl::get_as_tuple(); + + std::cout + << "Content from --flag1: " + << std::get<0>(flag1_content) << ", " + << std::get<1>(flag1_content) << "\n"; + + std::cout + << "Content from --flag2: " + << std::get<0>(flag2_content) << ", " + << std::get<1>(flag2_content) << ", " + << static_cast(std::get<2>(flag2_content)) << "\n"; +} diff --git a/example/runtime_start_at.cpp b/example/runtime_start_at.cpp new file mode 100644 index 0000000..3208737 --- /dev/null +++ b/example/runtime_start_at.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace mln = cynodelic::mulinum; +namespace mfl = cynodelic::metaflags; + + +#ifndef STRING_ +#define STRING_ CYNODELIC_METAFLAGS_STRING +#endif + +#ifndef FLAG_ +#define FLAG_ CYNODELIC_METAFLAGS_FLAG +#endif + +#ifndef SWITCH_ +#define SWITCH_ CYNODELIC_METAFLAGS_SWITCH +#endif + +#ifndef WAS_CALLED +#define WAS_CALLED CYNODELIC_METAFLAGS_WAS_CALLED +#endif + +#ifndef GET_ARGUMENT +#define GET_ARGUMENT CYNODELIC_METAFLAGS_GET_ARGUMENT +#endif + + +using my_parser = mfl::parser< + mfl::parser_parameters< + mfl::help_parameters< + mfl::usage_format + >, + mfl::runtime_start_at + >, + FLAG_("flag1,f1","Flag 1",mfl::i64_arg<>,mfl::i64_arg<>,mfl::i64_arg<>), + FLAG_("flag2,f2","Flag 2",mfl::i64_arg<>,mfl::i64_arg<>,mfl::i64_arg<>), + FLAG_("flag3,f3","Flag 3",mfl::i64_arg<>,mfl::i64_arg<>,mfl::i64_arg<>) +>; + + +int main(int argc,char *argv[]) +{ + std::size_t start_at_pos = 1; + bool skip_two_was_set = false; + std::string skip_two_arg; + + if (argc > 1) + { + if (!std::strcmp(argv[1],"skip_one")) + { + start_at_pos = 2; + } + else if (!std::strcmp(argv[1],"skip_two")) + { + start_at_pos = 3; + skip_two_was_set = true; + skip_two_arg = argv[2]; + } + } + + my_parser::set_start(start_at_pos); + + my_parser::parse(argc,argv); + + std::cout << "Parsing started at position " << my_parser::starts_at() << "\n\n"; + + if (skip_two_was_set) + { + std::cout << "Argument after \"skip_two\": " << skip_two_arg << "\n"; + } + + std::cout + << "Content of --flag1/-f1: " << "{" + << my_parser::template get(0) << "," + << my_parser::template get(0) << "," + << my_parser::template get(0) + << "}\n"; + + std::cout + << "Content of --flag2/-f2: " << "{" + << GET_ARGUMENT(my_parser,"--flag2",0,0) << "," + << GET_ARGUMENT(my_parser,"--flag2",1,0) << "," + << GET_ARGUMENT(my_parser,"--flag2",2,0) + << "}\n"; +} diff --git a/example/switches.cpp b/example/switches.cpp new file mode 100644 index 0000000..f0306c4 --- /dev/null +++ b/example/switches.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#include +#include + + +namespace mln = cynodelic::mulinum; +namespace mfl = cynodelic::metaflags; + + +#ifndef STRING_ +#define STRING_ CYNODELIC_METAFLAGS_STRING +#endif + +#ifndef FLAG_ +#define FLAG_ CYNODELIC_METAFLAGS_FLAG +#endif + +#ifndef SWITCH_ +#define SWITCH_ CYNODELIC_METAFLAGS_SWITCH +#endif + +#ifndef WAS_CALLED +#define WAS_CALLED CYNODELIC_METAFLAGS_WAS_CALLED +#endif + + +using my_parser = mfl::parser< + mfl::flag, + SWITCH_("switch2,s2","Switch 2"), + SWITCH_("switch3,s3","Switch 3"), + SWITCH_("switch4,s4","Switch 4") +>; + + +int main(int argc, char *argv[]) +{ + my_parser::parse(argc,argv); + + if (my_parser::template was_called()) + { + std::cout << "Switch 1 set.\n"; + } + + if (WAS_CALLED(my_parser,"--switch2")) + { + std::cout << "Switch 2 set.\n"; + } + + if (WAS_CALLED(my_parser,"--switch3")) + { + std::cout << "Switch 3 set.\n"; + } + + if (WAS_CALLED(my_parser,"--switch4")) + { + std::cout << "Switch 4 set.\n"; + } +} + diff --git a/example/two_parsers.cpp b/example/two_parsers.cpp new file mode 100644 index 0000000..45adeca --- /dev/null +++ b/example/two_parsers.cpp @@ -0,0 +1,206 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + + +namespace mln = cynodelic::mulinum; +namespace mfl = cynodelic::metaflags; + + +#ifndef STRING_ +#define STRING_ CYNODELIC_METAFLAGS_STRING +#endif + +#ifndef FLAG_ +#define FLAG_ CYNODELIC_METAFLAGS_FLAG +#endif + +#ifndef SWITCH_ +#define SWITCH_ CYNODELIC_METAFLAGS_SWITCH +#endif + +#ifndef WAS_CALLED +#define WAS_CALLED CYNODELIC_METAFLAGS_WAS_CALLED +#endif + + +using options_prsr = mfl::parser< + mfl::parser_parameters< + mfl::disable_help_in_parser + >, + FLAG_("display-mode,dm","Sets how the switches' statuses are displayed (default: grid).\nModes:\n vertical/v\n horizontal/h\n grid/g\n named/n",mfl::str_arg<>), + SWITCH_("help,h","Displays this help and exits the program.") +>; + +using switches_prsr = mfl::parser< + mfl::parser_parameters< + mfl::disable_help_in_parser, + mfl::runtime_start_at + >, + SWITCH_("switch-00,s00","Switch 0,0"), + SWITCH_("switch-01,s01","Switch 0,1"), + SWITCH_("switch-02,s02","Switch 0,2"), + SWITCH_("switch-10,s10","Switch 1,0"), + SWITCH_("switch-11,s11","Switch 1,1"), + SWITCH_("switch-12,s12","Switch 1,2"), + SWITCH_("switch-20,s20","Switch 2,0"), + SWITCH_("switch-21,s21","Switch 2,1"), + SWITCH_("switch-22,s22","Switch 2,2") +>; + + +using opts_list = mfl::generate_list_of_flags< + mfl::help_parameters< + mfl::flags_list_header, + mfl::add_help_flags_to_list + >, + options_prsr +>; + +using sws_list = mfl::generate_list_of_flags< + mfl::help_parameters< + mfl::flags_list_header, + mfl::add_help_flags_to_list + >, + switches_prsr +>; + +// The outputs are Mulinum strings, so they can be concatenated using `concat` +using compound_list = mln::concat; + + +void print_help_and_exit(char *argv[]) +{ + std::cout << "Usage: " << argv[0] << "[options...] [switches...]\n\n"; + + std::cout << compound_list::c_str() << "\n"; + + std::exit(EXIT_SUCCESS); +} + + +int main(int argc,char *argv[]) +{ + options_prsr::parse(argc,argv); + + if (argc == 2 && WAS_CALLED(options_prsr,"--help")) + { + print_help_and_exit(argv); + } + + switches_prsr::set_start(options_prsr::last_parsed_argument_position()); + switches_prsr::parse(argc,argv); + + std::string disp_mode = options_prsr::template get("grid"); + + if (disp_mode == std::string("vertical") || disp_mode == std::string("v")) + { + std::cout << "0,0: [" << (WAS_CALLED(switches_prsr,"-s00") ? '*' : ' ') << "]\n"; + std::cout << "0,1: [" << (WAS_CALLED(switches_prsr,"-s01") ? '*' : ' ') << "]\n"; + std::cout << "0,2: [" << (WAS_CALLED(switches_prsr,"-s02") ? '*' : ' ') << "]\n"; + + std::cout << "1,0: [" << (WAS_CALLED(switches_prsr,"-s10") ? '*' : ' ') << "]\n"; + std::cout << "1,1: [" << (WAS_CALLED(switches_prsr,"-s11") ? '*' : ' ') << "]\n"; + std::cout << "1,2: [" << (WAS_CALLED(switches_prsr,"-s12") ? '*' : ' ') << "]\n"; + + std::cout << "2,0: [" << (WAS_CALLED(switches_prsr,"-s20") ? '*' : ' ') << "]\n"; + std::cout << "2,1: [" << (WAS_CALLED(switches_prsr,"-s21") ? '*' : ' ') << "]\n"; + std::cout << "2,2: [" << (WAS_CALLED(switches_prsr,"-s22") ? '*' : ' ') << "]\n"; + } + else if (disp_mode == std::string("horizontal") || disp_mode == std::string("h")) + { + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s00") ? '*' : ' ') << "]"; + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s01") ? '*' : ' ') << "]"; + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s02") ? '*' : ' ') << "]"; + + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s10") ? '*' : ' ') << "]"; + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s11") ? '*' : ' ') << "]"; + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s12") ? '*' : ' ') << "]"; + + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s20") ? '*' : ' ') << "]"; + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s21") ? '*' : ' ') << "]"; + std::cout << "[" << (WAS_CALLED(switches_prsr,"-s22") ? '*' : ' ') << "]"; + + std::cout << "\n"; + } + else if (disp_mode == std::string("grid") || disp_mode == std::string("g")) + { + std::cout + << "[" + << (WAS_CALLED(switches_prsr,"-s00") ? '*' : ' ') << "][" + << (WAS_CALLED(switches_prsr,"-s01") ? '*' : ' ') << "][" + << (WAS_CALLED(switches_prsr,"-s02") ? '*' : ' ') << "]\n"; + + std::cout + << "[" + << (WAS_CALLED(switches_prsr,"-s10") ? '*' : ' ') << "][" + << (WAS_CALLED(switches_prsr,"-s11") ? '*' : ' ') << "][" + << (WAS_CALLED(switches_prsr,"-s12") ? '*' : ' ') << "]\n"; + + std::cout + << "[" + << (WAS_CALLED(switches_prsr,"-s20") ? '*' : ' ') << "][" + << (WAS_CALLED(switches_prsr,"-s21") ? '*' : ' ') << "][" + << (WAS_CALLED(switches_prsr,"-s22") ? '*' : ' ') << "]\n"; + } + else if (disp_mode == std::string("named") || disp_mode == std::string("n")) + { + if (WAS_CALLED(switches_prsr,"--switch-00")) + { + std::cout << "--switch-00 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-01")) + { + std::cout << "--switch-01 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-02")) + { + std::cout << "--switch-02 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-10")) + { + std::cout << "--switch-10 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-11")) + { + std::cout << "--switch-11 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-12")) + { + std::cout << "--switch-12 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-20")) + { + std::cout << "--switch-20 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-21")) + { + std::cout << "--switch-21 was called.\n"; + } + + if (WAS_CALLED(switches_prsr,"--switch-22")) + { + std::cout << "--switch-22 was called.\n"; + } + } +} + diff --git a/include/cynodelic/metaflags/argument_type.hpp b/include/cynodelic/metaflags/argument_type.hpp new file mode 100644 index 0000000..a407d7f --- /dev/null +++ b/include/cynodelic/metaflags/argument_type.hpp @@ -0,0 +1,73 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +/** + * @file argument_type.hpp + * + * @brief Defines the `argument_type` type operation + */ + + +#ifndef CYNODELIC_METAFLAGS_ARGUMENT_TYPE_HPP +#define CYNODELIC_METAFLAGS_ARGUMENT_TYPE_HPP + + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +namespace cynodelic { namespace metaflags +{ + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +struct argument_type_impl; + + +template +struct argument_type_impl,mulinum::string,ArgIdx> +{ + using type = decltype(detail::multiple_flags_data_helper::get(mulinum::string{},mulinum::size_c{})); +}; + + +template +struct argument_type_impl,Flags...>,mulinum::string,ArgIdx> +{ + using type = decltype(detail::multiple_flags_data_helper::get(mulinum::string{},mulinum::size_c{})); +}; + +#endif // DOXYGEN_SHOULD_SKIP_THIS + + +/** + * @ingroup typetraits_ + * @brief Obtains the type of the argument of a flag + * + * Obtains the type of the `ArgIdx`-th argument of a given flag. + * + * @tparam Parser An instance of @ref parser. + * @tparam FlagString A @link cynodelic::mulinum::string string@endlink + * containing the alias of the desired flag. + * @tparam ArgIdx The position of the desired argument. + */ +template +using argument_type = typename argument_type_impl::type; + + +}} // end of "cynodelic::metaflags" namespace + + +#endif // CYNODELIC_METAFLAGS_ARGUMENT_TYPE_HPP diff --git a/include/cynodelic/metaflags/argument_types_list.hpp b/include/cynodelic/metaflags/argument_types_list.hpp new file mode 100644 index 0000000..3c4a1b7 --- /dev/null +++ b/include/cynodelic/metaflags/argument_types_list.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2019 Álvaro Ceballos +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +/** + * @file argument_types_list.hpp + * + * @brief Defines the `argument_types_list` type operation + */ + + +#ifndef CYNODELIC_METAFLAGS_ARGUMENT_TYPES_LIST_HPP +#define CYNODELIC_METAFLAGS_ARGUMENT_TYPES_LIST_HPP + + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace cynodelic { namespace metaflags +{ + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template