taskwarrior/src/commands/CmdHelp.cpp

232 lines
9.9 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2021, Tomas Babej, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// https://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
// cmake.h include header must come first
#include <CmdHelp.h>
#include <Context.h>
#include <Table.h>
#include <format.h>
#include <shared.h>
#include <util.h>
#include <algorithm>
////////////////////////////////////////////////////////////////////////////////
CmdHelp::CmdHelp() {
_keyword = "help";
_usage = "task help ['usage']";
_description = "Displays this usage help text";
_read_only = true;
_displays_id = false;
_needs_gc = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
_accepts_miscellaneous = true;
_category = Command::Category::misc;
}
////////////////////////////////////////////////////////////////////////////////
int CmdHelp::execute(std::string& output) {
auto words = Context::getContext().cli2.getWords();
if (words.size() == 1 && closeEnough("usage", words[0]))
output = '\n' + composeUsage() + '\n';
else
output =
'\n' + composeUsage() + '\n' +
"Documentation for Taskwarrior can be found using 'man task', 'man taskrc', 'man "
"task-color', 'man task-sync' or at https://taskwarrior.org\n"
"\n"
"The general form of commands is:\n"
" task [<filter>] <command> [<mods>]\n"
"\n"
"The <filter> consists of zero or more restrictions on which tasks to select, "
"such as:\n"
" task <command> <mods>\n"
" task 28 <command> <mods>\n"
" task +weekend <command> <mods>\n"
" task project:Home due.before:today <command> <mods>\n"
" task ebeeab00-ccf8-464b-8b58-f7f2d606edfb <command> <mods>\n"
"\n"
"By default, filter elements are combined with an implicit 'and' operator, but "
"'or' and 'xor' may also be used, provided parentheses are included:\n"
" task '(/[Cc]at|[Dd]og/ or /[0-9]+/)' <command> <mods>\n"
"\n"
"A filter may target specific tasks using ID or UUID numbers. To specify "
"multiple tasks use one of these forms:\n"
" task 1,2,3 delete\n"
" task 1-3 info\n"
" task 1,2-5,19 modify pri:H\n"
" task 4-7 ebeeab00-ccf8-464b-8b58-f7f2d606edfb info\n"
"\n"
"The <mods> consist of zero or more changes to apply to the selected tasks, "
"such as:\n"
" task <filter> <command> project:Home\n"
" task <filter> <command> +weekend +garden due:tomorrow\n"
" task <filter> <command> Description/annotation text\n"
" task <filter> <command> /from/to/ <- replace first match\n"
" task <filter> <command> /from/to/g <- replace all matches\n"
"\n"
"Tags are arbitrary words, any quantity:\n"
" +tag The + means add the tag\n"
" -tag The - means remove the tag\n"
"\n"
"Built-in attributes are:\n"
" description: Task description text\n"
" status: Status of task - pending, completed, deleted, waiting\n"
" project: Project name\n"
" priority: Priority\n"
" due: Due date\n"
" recur: Recurrence frequency\n"
" until: Expiration date of a task\n"
" limit: Desired number of rows in report, or 'page'\n"
" wait: Date until task becomes pending\n"
" entry: Date task was created\n"
" end: Date task was completed/deleted\n"
" start: Date task was started\n"
" scheduled: Date task is scheduled to start\n"
" modified: Date task was last modified\n"
" depends: Other tasks that this task depends upon\n"
"\n"
"Attribute modifiers make filters more precise. Supported modifiers are:\n"
"\n"
" Modifiers Example Equivalent Meaning\n"
" ---------------- ----------------- ------------------- -------------------------\n"
" due:today due = today Fuzzy match\n"
" not due.not:today due != today Fuzzy non-match\n"
" before, below due.before:today due < today Exact date comparison\n"
" after, above due.after:today due >= tomorrow Exact date comparison\n"
" none project.none: project == '' Empty\n"
" any project.any: project !== '' Not empty\n"
" is, equals project.is:x project == x Exact match\n"
" isnt project.isnt:x project !== x Exact non-match\n"
" has, contains desc.has:Hello desc ~ Hello Pattern match\n"
" hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n"
" startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n"
" endswith, right desc.right:llo desc ~ 'llo$' End match\n"
" word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n"
" noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n"
"\n"
"Alternately algebraic expressions support:\n"
" and or xor Logical operators\n"
" < <= = != >= > Relational operators\n"
" ( ) Precedence\n"
"\n"
" task due.before:eom priority.not:L list\n"
" task '(due < eom and priority != L)' list\n"
"\n"
"The default .taskrc file can be overridden with:\n"
" task ... rc:<alternate file> ...\n"
" task ... rc:~/.alt_taskrc ...\n"
"\n"
"The values in .taskrc (or alternate) can be overridden with:\n"
" task ... rc.<name>=<value> ...\n"
" task rc.color=off list\n"
"\n"
"Any command or attribute name may be abbreviated if still unique:\n"
" task list project:Home\n"
" task li pro:Home\n"
"\n"
"Some task descriptions need to be escaped because of the shell:\n"
" task add \"quoted ' quote\"\n"
" task add escaped \\' quote\n"
"\n"
"The argument -- tells Taskwarrior to treat all other args as description, even "
"if they would otherwise be attributes or tags:\n"
" task add -- project:Home needs scheduling\n"
"\n"
"Many characters have special meaning to the shell, including:\n"
" $ ! ' \" ( ) ; \\ ` * ? { } [ ] < > | & % # ~\n"
"\n";
/*
TODO To be included later, before the 'precedence' line.
" + - Addition, Subtraktion\n" \
" ! Negation\n" \
" ~ !~ Treffer, kein Treffer\n" \
*/
return 0;
}
////////////////////////////////////////////////////////////////////////////////
std::string CmdHelp::composeUsage() const {
Table view;
view.width(Context::getContext().getWidth());
view.add("");
view.add("");
view.add("");
// Static first row.
auto row = view.addRow();
view.set(row, 0, "Usage:");
view.set(row, 1, "task");
view.set(row, 2, "Runs rc.default.command, if specified.");
// Obsolete method of getting a list of all commands.
std::vector<std::string> all;
for (auto& cmd : Context::getContext().commands) all.push_back(cmd.first);
// Sort alphabetically by usage.
std::sort(all.begin(), all.end());
// Add the regular commands.
for (auto& name : all) {
if (name[0] != '_') {
row = view.addRow();
view.set(row, 1, Context::getContext().commands[name]->usage());
view.set(row, 2, Context::getContext().commands[name]->description());
}
}
// Add the helper commands.
for (auto& name : all) {
if (name[0] == '_') {
row = view.addRow();
view.set(row, 1, Context::getContext().commands[name]->usage());
view.set(row, 2, Context::getContext().commands[name]->description());
}
}
// Add the aliases commands.
row = view.addRow();
view.set(row, 1, " ");
for (auto& alias : Context::getContext().config) {
if (alias.first.substr(0, 6) == "alias.") {
row = view.addRow();
view.set(row, 1, alias.first.substr(6));
view.set(row, 2, format("Aliased to '{1}'", alias.second));
}
}
return view.render();
}
////////////////////////////////////////////////////////////////////////////////