mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Expression
- Added configurable 'abbreviation.minimum' (default:2) setting to control how auto-completion works.
This commit is contained in:
parent
a6fadaee67
commit
197524a5fc
16 changed files with 139 additions and 52 deletions
2
NEWS
2
NEWS
|
@ -56,6 +56,8 @@ New configuration options in taskwarrior 2.0.0
|
|||
- New 'exit.on.missing.db' control causes an exit if the ~/.task directory
|
||||
(or override) is missing.
|
||||
- New 'color.completed' and 'color.deleted' color rules.
|
||||
- New 'abbreviation.minimum' setting controls how short an abbreviated
|
||||
command or value may be.
|
||||
|
||||
Newly deprecated features in taskwarrior 2.0.0
|
||||
|
||||
|
|
|
@ -387,6 +387,11 @@ of the longer-term rate. The calculation is as follows:
|
|||
|
||||
rate = (long-term-rate * (1 - bias)) + (short-term-rate * bias)
|
||||
|
||||
.TP
|
||||
.B abbreviation.minimum=2
|
||||
Minimum length of any abbreviated command/value. This means that "ve", "ver",
|
||||
"vers", "versi", "versio" will all equate to "version", but "v" will not.
|
||||
Default is 2.
|
||||
.TP
|
||||
.B debug=off
|
||||
Taskwarrior has a debug mode that causes diagnostic output to be displayed.
|
||||
|
|
|
@ -798,7 +798,10 @@ bool Arguments::is_command (
|
|||
std::string& command)
|
||||
{
|
||||
std::vector <std::string> matches;
|
||||
if (autoComplete (command, keywords, matches) == 1)
|
||||
if (autoComplete (command,
|
||||
keywords,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum")) == 1)
|
||||
{
|
||||
command = matches[0];
|
||||
return true;
|
||||
|
@ -1090,7 +1093,10 @@ bool Arguments::is_attribute (const std::string& input, std::string& canonical)
|
|||
}
|
||||
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (input, candidates, matches);
|
||||
autoComplete (input,
|
||||
candidates,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum"));
|
||||
|
||||
if (matches.size () == 1)
|
||||
{
|
||||
|
@ -1116,7 +1122,10 @@ bool Arguments::is_modifier (const std::string& input)
|
|||
}
|
||||
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (input, candidates, matches);
|
||||
autoComplete (input,
|
||||
candidates,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum"));
|
||||
|
||||
if (matches.size () == 1)
|
||||
return true;
|
||||
|
|
15
src/Att.cpp
15
src/Att.cpp
|
@ -301,7 +301,10 @@ bool Att::validNameValue (
|
|||
candidates.push_back (modifiableNames[i]);
|
||||
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (name, candidates, matches);
|
||||
autoComplete (name,
|
||||
candidates,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum"));
|
||||
|
||||
if (matches.size () == 0)
|
||||
return false;
|
||||
|
@ -327,7 +330,10 @@ bool Att::validNameValue (
|
|||
candidates.push_back (modifierNames[i]);
|
||||
|
||||
matches.clear ();
|
||||
autoComplete (mod, candidates, matches);
|
||||
autoComplete (mod,
|
||||
candidates,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum"));
|
||||
|
||||
if (matches.size () == 0)
|
||||
throw std::string ("Unrecognized modifier '") + mod + "'.";
|
||||
|
@ -454,7 +460,10 @@ bool Att::validNameValue (
|
|||
candidates.push_back ("deleted");
|
||||
candidates.push_back ("recurring");
|
||||
candidates.push_back ("waiting");
|
||||
autoComplete (value, candidates, matches);
|
||||
autoComplete (value,
|
||||
candidates,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum"));
|
||||
|
||||
if (matches.size () == 1)
|
||||
value = matches[0];
|
||||
|
|
|
@ -102,6 +102,7 @@ std::string Config::defaults =
|
|||
"expressions=on # Support for algebraic expressions\n"
|
||||
"patterns=on # Support for regex patterns\n"
|
||||
"json.array=off # Enclose JSON output in [ ]\n"
|
||||
"abbreviation.minimum=2 # Shortest allowed abbreviation\n"
|
||||
"\n"
|
||||
"# Dates\n"
|
||||
"dateformat=m/d/Y # Preferred input and display date format\n"
|
||||
|
|
23
src/DOM.cpp
23
src/DOM.cpp
|
@ -27,7 +27,6 @@
|
|||
|
||||
#define L10N // Localization complete.
|
||||
|
||||
#include <iostream> // TODO Remove
|
||||
#include <sstream>
|
||||
#include <Context.h>
|
||||
#include <Nibbler.h>
|
||||
|
@ -192,16 +191,16 @@ const std::string DOM::get (const std::string& name)
|
|||
// TODO <uuid>.recur
|
||||
// TODO <uuid>.depends
|
||||
//
|
||||
// {.entry,.start,.end,.due,.until,.wait}
|
||||
// .description
|
||||
// .project
|
||||
// .priority
|
||||
// .parent
|
||||
// .status
|
||||
// .tags
|
||||
// .urgency
|
||||
// .recur
|
||||
// .depends
|
||||
// {entry,start,end,due,until,wait}
|
||||
// description
|
||||
// project
|
||||
// priority
|
||||
// parent
|
||||
// status
|
||||
// tags
|
||||
// urgency
|
||||
// recur
|
||||
// depends
|
||||
//
|
||||
const std::string DOM::get (const std::string& name, const Task& task)
|
||||
{
|
||||
|
@ -295,7 +294,6 @@ bool DOM::is_literal (std::string& input)
|
|||
if (Date::valid (input, context.config.get ("dateformat")))
|
||||
{
|
||||
input = Date (input).toEpochString ();
|
||||
std::cout << "# DOM::is_literal '" << input << "' --> date\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -323,7 +321,6 @@ bool DOM::is_literal (std::string& input)
|
|||
if (n.getInt (i) && n.depleted ())
|
||||
return true;
|
||||
|
||||
// std::cout << "# DOM::is_literal '" << input << "' --> unknown\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
13
src/Date.cpp
13
src/Date.cpp
|
@ -27,6 +27,7 @@
|
|||
|
||||
#define L10N // Localization complete.
|
||||
|
||||
#include <iostream> // TODO Remove.
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <time.h>
|
||||
|
@ -175,17 +176,18 @@ void Date::toMDY (int& m, int& d, int& y)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const std::string Date::toString (const std::string& format /*= "m/d/Y" */) const
|
||||
const std::string Date::toString (
|
||||
const std::string& format /*= "m/d/Y" */) const
|
||||
{
|
||||
// Making this local copy seems to fix a bug. Remove the local copy and you'll
|
||||
// see segmentation faults and all kinds of gibberish.
|
||||
// Making this local copy seems to fix a bug. Remove the local copy and
|
||||
// you'll see segmentation faults and all kinds of gibberish.
|
||||
std::string localFormat = format;
|
||||
|
||||
char buffer[12];
|
||||
std::string formatted;
|
||||
for (unsigned int i = 0; i < localFormat.length (); ++i)
|
||||
{
|
||||
char c = localFormat[i];
|
||||
int c = localFormat[i];
|
||||
switch (c)
|
||||
{
|
||||
case 'm': sprintf (buffer, "%d", this->month ()); break;
|
||||
|
@ -794,8 +796,9 @@ bool Date::isRelativeDate (const std::string& input)
|
|||
supported.push_back ("later");
|
||||
supported.push_back ("someday");
|
||||
|
||||
// Hard-coded 3, despite rc.abbreviation.minimum.
|
||||
std::vector <std::string> matches;
|
||||
if (autoComplete (in, supported, matches) == 1)
|
||||
if (autoComplete (in, supported, matches, 3) == 1)
|
||||
{
|
||||
std::string found = matches[0];
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Context.h>
|
||||
#include <text.h>
|
||||
#include <util.h>
|
||||
#include <i18n.h>
|
||||
|
@ -91,6 +92,8 @@ static const char* durations[] =
|
|||
|
||||
#define NUM_DURATIONS (sizeof (durations) / sizeof (durations[0]))
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Duration::Duration ()
|
||||
: mSecs (0)
|
||||
|
@ -339,7 +342,10 @@ bool Duration::valid (const std::string& input)
|
|||
supported.push_back (durations[i]);
|
||||
|
||||
std::vector <std::string> matches;
|
||||
if (autoComplete (units, supported, matches) == 1)
|
||||
if (autoComplete (units,
|
||||
supported,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum")) == 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -376,7 +382,10 @@ void Duration::parse (const std::string& input)
|
|||
|
||||
mSecs = 0;
|
||||
std::vector <std::string> matches;
|
||||
if (autoComplete (units, supported, matches) == 1)
|
||||
if (autoComplete (units,
|
||||
supported,
|
||||
matches,
|
||||
context.config.getInteger ("abbreviation.minimum")) == 1)
|
||||
{
|
||||
std::string match = matches[0];
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ void Expression::eval (const Task& task, std::vector <Variant>& value_stack)
|
|||
right._raw_type = value_stack.back ()._raw_type;
|
||||
}
|
||||
value_stack.pop_back ();
|
||||
// std::cout << "# right raw=" << right._raw << " type=" << right._type << " value=" << right._string << "\n";
|
||||
// std::cout << "# right variant " << right.dump () << "\n";
|
||||
|
||||
// lvalue (dom).
|
||||
Variant left (value_stack.back ());
|
||||
|
@ -185,7 +185,7 @@ void Expression::eval (const Task& task, std::vector <Variant>& value_stack)
|
|||
left._raw_type = value_stack.back ()._raw_type;
|
||||
}
|
||||
value_stack.pop_back ();
|
||||
// std::cout << "# left raw=" << left._raw << " type=" << left._type << " value=" << left._string << "\n";
|
||||
// std::cout << "# left variant " << left.dump () << "\n";
|
||||
|
||||
// Now the binary operators.
|
||||
if (arg->_first == "and")
|
||||
|
@ -463,7 +463,7 @@ void Expression::create_variant (
|
|||
const std::string& value,
|
||||
const std::string& type)
|
||||
{
|
||||
// std::cout << "# operand '" << value << "' as " << type << "\n";
|
||||
// std::cout << "# create_variant " << value << "/" << type << "\n";
|
||||
|
||||
// DOM references are not resolved until the operator is processed. This
|
||||
// preserves the original name, which helps determine how to apply the
|
||||
|
|
|
@ -41,6 +41,12 @@ Variant::Variant ()
|
|||
: _type (v_unknown)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (false)
|
||||
, _integer (0)
|
||||
, _double (0.0)
|
||||
, _string ("")
|
||||
, _date (0)
|
||||
, _duration (0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -66,44 +72,86 @@ Variant::Variant (const Variant& other)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant (const bool input)
|
||||
: _type (v_boolean)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (input)
|
||||
, _integer (0)
|
||||
, _double (0.0)
|
||||
, _string ("")
|
||||
, _date (0)
|
||||
, _duration (0)
|
||||
{
|
||||
_type = v_boolean;
|
||||
_bool = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant (const int input)
|
||||
: _type (v_integer)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (false)
|
||||
, _integer (input)
|
||||
, _double (0.0)
|
||||
, _string ("")
|
||||
, _date (0)
|
||||
, _duration (0)
|
||||
{
|
||||
_type = v_integer;
|
||||
_integer = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant (const double& input)
|
||||
: _type (v_double)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (false)
|
||||
, _integer (0)
|
||||
, _double (input)
|
||||
, _string ("")
|
||||
, _date (0)
|
||||
, _duration (0)
|
||||
{
|
||||
_type = v_double;
|
||||
_double = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant (const std::string& input)
|
||||
: _type (v_string)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (false)
|
||||
, _integer (0)
|
||||
, _double (0.0)
|
||||
, _string (input)
|
||||
, _date (0)
|
||||
, _duration (0)
|
||||
{
|
||||
_type = v_string;
|
||||
_string = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant (const Date& input)
|
||||
: _type (v_date)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (false)
|
||||
, _integer (0)
|
||||
, _double (0.0)
|
||||
, _string ("")
|
||||
, _date (input)
|
||||
, _duration (0)
|
||||
{
|
||||
_type = v_date;
|
||||
_date = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant (const Duration& input)
|
||||
: _type (v_duration)
|
||||
, _raw ("")
|
||||
, _raw_type ("")
|
||||
, _bool (false)
|
||||
, _integer (0)
|
||||
, _double (0.0)
|
||||
, _string ("")
|
||||
, _date (0)
|
||||
, _duration (input)
|
||||
{
|
||||
_type = v_duration;
|
||||
_duration = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -123,11 +123,11 @@ int CmdCalendar::execute (std::string& output)
|
|||
for (arg = args.begin (); arg != args.end (); ++arg)
|
||||
{
|
||||
// Some version of "calendar".
|
||||
if (autoComplete (lowerCase (*arg), commandNames, matches) == 1)
|
||||
if (autoComplete (lowerCase (*arg), commandNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
|
||||
continue;
|
||||
|
||||
// "due".
|
||||
else if (autoComplete (lowerCase (*arg), keywordNames, matches) == 1)
|
||||
else if (autoComplete (lowerCase (*arg), keywordNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
|
||||
getpendingdate = true;
|
||||
|
||||
// "y".
|
||||
|
@ -147,7 +147,7 @@ int CmdCalendar::execute (std::string& output)
|
|||
}
|
||||
|
||||
// "January" etc.
|
||||
else if (autoComplete (lowerCase (*arg), monthNames, matches) == 1)
|
||||
else if (autoComplete (lowerCase (*arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
|
||||
{
|
||||
argMonth = Date::monthOfYear (matches[0]);
|
||||
if (argMonth == -1)
|
||||
|
|
|
@ -67,6 +67,7 @@ int CmdShow::execute (std::string& output)
|
|||
// Note that there is a leading and trailing space, to make it easier to
|
||||
// search for whole words.
|
||||
std::string recognized =
|
||||
" abbreviation.minimum"
|
||||
" active.indicator"
|
||||
" annotations"
|
||||
" avoidlastcolumn"
|
||||
|
|
|
@ -74,7 +74,7 @@ void initializeColorRules ()
|
|||
{
|
||||
// Add the leading "color." string.
|
||||
std::string rule = "color." + *p;
|
||||
autoComplete (rule, rules, results);
|
||||
autoComplete (rule, rules, results, 3); // Hard-coded 3.
|
||||
|
||||
std::vector <std::string>::iterator r;
|
||||
for (r = results.begin (); r != results.end (); ++r)
|
||||
|
|
|
@ -482,7 +482,8 @@ void guess (
|
|||
std::string& candidate)
|
||||
{
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (candidate, options, matches);
|
||||
autoComplete (candidate, options, matches,
|
||||
context.config.getInteger ("abbreviation.minimum"));
|
||||
if (1 == matches.size ())
|
||||
candidate = matches[0];
|
||||
|
||||
|
|
12
src/util.cpp
12
src/util.cpp
|
@ -75,7 +75,7 @@ bool confirm (const std::string& question)
|
|||
std::getline (std::cin, answer);
|
||||
answer = std::cin.eof() ? STRING_UTIL_CONFIRM_NO : lowerCase (trim (answer));
|
||||
|
||||
autoComplete (answer, options, matches);
|
||||
autoComplete (answer, options, matches, 1); // Hard-coded 1.
|
||||
}
|
||||
while (matches.size () != 1);
|
||||
|
||||
|
@ -109,7 +109,7 @@ int confirm3 (const std::string& question)
|
|||
|
||||
std::getline (std::cin, answer);
|
||||
answer = trim (answer);
|
||||
autoComplete (answer, options, matches);
|
||||
autoComplete (answer, options, matches, 1); // Hard-coded 1.
|
||||
}
|
||||
while (matches.size () != 1);
|
||||
|
||||
|
@ -150,7 +150,7 @@ int confirm4 (const std::string& question)
|
|||
|
||||
std::getline (std::cin, answer);
|
||||
answer = trim (answer);
|
||||
autoComplete (answer, options, matches);
|
||||
autoComplete (answer, options, matches, 1); // Hard-coded 1.
|
||||
}
|
||||
while (matches.size () != 1);
|
||||
|
||||
|
@ -190,7 +190,8 @@ std::string formatBytes (size_t bytes)
|
|||
int autoComplete (
|
||||
const std::string& partial,
|
||||
const std::vector<std::string>& list,
|
||||
std::vector<std::string>& matches)
|
||||
std::vector<std::string>& matches,
|
||||
int minimum/* = 2*/)
|
||||
{
|
||||
matches.clear ();
|
||||
|
||||
|
@ -211,7 +212,8 @@ int autoComplete (
|
|||
}
|
||||
|
||||
// Maintain a list of partial matches.
|
||||
else if (length <= item->length () &&
|
||||
else if (length >= (unsigned) minimum &&
|
||||
length <= item->length () &&
|
||||
partial == item->substr (0, length))
|
||||
matches.push_back (*item);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ int confirm3 (const std::string&);
|
|||
int confirm4 (const std::string&);
|
||||
void delay (float);
|
||||
std::string formatBytes (size_t);
|
||||
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
|
||||
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&, int minimum = 1);
|
||||
|
||||
#if defined(HAVE_UUID) && !defined(HAVE_UUID_UNPARSE_LOWER)
|
||||
void uuid_unparse_lower (uuid_t uu, char *out);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue