diff --git a/src/commands/.gitignore b/src/commands/.gitignore index 51c3d028..41aecd8f 100644 --- a/src/commands/.gitignore +++ b/src/commands/.gitignore @@ -1 +1,2 @@ libcommands.a +additional-help.h diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index 3151aab4..cc74ca0e 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -5,6 +5,18 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src/libshared/src ${TIMEW_INCLUDE_DIRS}) +set (ADDITIONAL_HELP_H "additional-help.h") + +ADD_CUSTOM_COMMAND ( + OUTPUT ${ADDITIONAL_HELP_H} + COMMAND /bin/sh src/commands/generate-additional-help.sh >src/commands/${ADDITIONAL_HELP_H} + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/generate-additional-help.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Generating ${ADDITIONAL_HELP_H}") + +ADD_CUSTOM_TARGET (generate_additional_help + DEPENDS ${ADDITIONAL_HELP_H}) + set (commands_SRCS CmdAnnotate.cpp CmdCancel.cpp CmdChart.cpp @@ -38,4 +50,4 @@ set (commands_SRCS CmdAnnotate.cpp CmdUntag.cpp) add_library (commands STATIC ${commands_SRCS}) - +add_dependencies (commands generate_additional_help) diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index 3068c93b..d890663b 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -26,13 +26,67 @@ #include #include +#include +#include #include #include #include +#include + +#include "additional-help.h" + +template +std::string join (const T& strings, size_t indent = 0, size_t max_width = 0) +{ + std::stringstream sstr; + auto it = std::begin (strings); + auto end = std::end (strings); + size_t cur = indent + 2; // account for added '{ ' + std::string part; + const std::string sep (" | "); + + while (it != end) + { + part = *it; + ++it; + + // Make sure we leave room for closing " }" or " |" + if ((max_width > 0) && (cur + part.length () + sep.length ()) > max_width) + { + sstr << "\n" << std::string (indent + 1, ' '); + cur = indent + 1; + sstr << part; + } + else + { + sstr << part; + } + cur += part.length (); + + if (it != end) + { + sstr << sep; + cur += sep.length (); + } + } + return sstr.str (); +} //////////////////////////////////////////////////////////////////////////////// int CmdHelpUsage (const Extensions& extensions) { + std::vector concepts; + + // Any commands will take precedence when using `timew help` and therefore, + // we'll exclude any commands that are also concepts. + std::set_difference (std::begin (documented_concepts), std::end (documented_concepts), + std::begin (documented_commands), std::end (documented_commands), + std::back_inserter (concepts), + [] (const char *a, const char *b) + { + return std::strcmp (a, b) < 0; + }); + std::cout << '\n' << "Usage: timew [--version]\n" << " timew annotate @ [@ ...] \n" @@ -46,7 +100,7 @@ int CmdHelpUsage (const Extensions& extensions) << " timew extensions\n" << " timew gaps [] [ ...]\n" << " timew get [ ...]\n" - << " timew help [ | interval | hints | date | duration]\n" + << " timew help [ | " << join (concepts) << "]\n" << " timew join @ @\n" << " timew lengthen @ [@ ...] \n" << " timew modify (start|end) @ \n" @@ -80,13 +134,13 @@ int CmdHelpUsage (const Extensions& extensions) } std::cout << "Additional help:\n" - << " timew help \n" - << " timew help interval\n" - << " timew help hints\n" - << " timew help date\n" - << " timew help duration\n" - << " timew help dom\n" - << '\n' + << " timew help \n"; + for (auto concept : concepts) + { + std::cout << " timew help " << concept << '\n'; + } + + std::cout << '\n' << "Interval:\n" << " [from] \n" << " [from] to/- \n" diff --git a/src/commands/generate-additional-help.sh b/src/commands/generate-additional-help.sh new file mode 100644 index 00000000..e340a8d9 --- /dev/null +++ b/src/commands/generate-additional-help.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +echo "// Generated file. Do not modify" +echo "static const char * documented_concepts[] = {" +for command in $(/bin/ls doc/man7/*.in | /bin/sed -n 's|doc/man7/timew-\(\w\+\).7.in|\1|p' | /usr/bin/sort); do + echo " \"${command}\"," +done +echo "};" + +echo "static const char * documented_commands[] = {" +for command in $(/bin/ls doc/man1/*.in | /bin/sed -n 's|doc/man1/timew-\(\w\+\).1.in|\1|p' | /usr/bin/sort); do + echo " \"${command}\"," +done +echo "};"