Enhancement - #307 show command

- introduced new show command to display configuration settings
- config command is used to just set config values
- modified documentation
- modified some unit tests calling 'task config' to 'task show'
This commit is contained in:
Federico Hernandez 2010-06-07 23:35:58 +02:00
parent f1368d6ac6
commit 51e5a18384
12 changed files with 156 additions and 125 deletions

View file

@ -129,12 +129,16 @@ Shows the task version number
.B help
Shows the long usage text.
.TP show
Shows the current settings in the task configuration file. If a section-name is
specified just the settings for the particular section will be displayed.
Section-names are: alias, calendar, color, general, holiday, report.
.TP
.B config [name [value | '']]
Shows the current settings in the task configuration file. Also supports
directly modifying the .taskrc file. This command either modifies
the 'name' setting with a new value of 'value', or adds a new entry that
is equivalent to 'name=value':
Add, modify and remove settings directly in the task configuration.
This command either modifies the 'name' setting with a new value of 'value',
or adds a new entry that is equivalent to 'name=value':
task config name value

View file

@ -59,6 +59,7 @@
228 version
229 shell
230 config
231 show
# 3xx Attributes - must be sequential
300 project

View file

@ -126,6 +126,7 @@ void Cmd::load ()
commands.push_back (context.stringtable.get (CMD_CALENDAR, "calendar"));
commands.push_back (context.stringtable.get (CMD_COLORS, "colors"));
commands.push_back (context.stringtable.get (CMD_CONFIG, "config"));
commands.push_back (context.stringtable.get (CMD_SHOW, "show"));
commands.push_back (context.stringtable.get (CMD_DELETE, "delete"));
commands.push_back (context.stringtable.get (CMD_DONE, "done"));
commands.push_back (context.stringtable.get (CMD_DUPLICATE, "duplicate"));
@ -211,6 +212,7 @@ bool Cmd::isReadOnlyCommand ()
command == context.stringtable.get (CMD_CALENDAR, "calendar") ||
command == context.stringtable.get (CMD_COLORS, "colors") ||
command == context.stringtable.get (CMD_CONFIG, "config") ||
command == context.stringtable.get (CMD_SHOW, "show") ||
command == context.stringtable.get (CMD_HELP, "help") ||
command == context.stringtable.get (CMD_INFO, "info") ||
command == context.stringtable.get (CMD_PROJECTS, "projects") ||

View file

@ -210,6 +210,7 @@ int Context::dispatch (std::string &out)
else if (cmd.command == "colors") { rc = handleColor (out); }
else if (cmd.command == "version") { rc = handleVersion (out); }
else if (cmd.command == "config") { rc = handleConfig (out); }
else if (cmd.command == "show") { rc = handleShow (out); }
else if (cmd.command == "help") { rc = longUsage (out); }
else if (cmd.command == "stats") { rc = handleReportStats (out); }
else if (cmd.command == "info") { rc = handleInfo (out); }

View file

@ -601,7 +601,7 @@ int handleVersion (std::string &outs)
}
////////////////////////////////////////////////////////////////////////////////
int handleConfig (std::string &outs)
int handleShow (std::string &outs)
{
int rc = 0;
@ -614,114 +614,6 @@ int handleConfig (std::string &outs)
std::vector <std::string> args;
split (args, context.task.get ("description"), ' ');
// Support:
// task config name value # set name to value
// task config name "" # set name to blank
// task config name # remove name
if (args.size () > 0)
{
std::string name = args[0];
std::string value = "";
if (args.size () > 1)
{
for (unsigned int i = 1; i < args.size (); ++i)
{
if (i > 1)
value += " ";
value += args[i];
}
}
if (name != "")
{
bool change = false;
// Read .taskrc (or equivalent)
std::string contents;
File::read (context.config.original_file, contents);
// task config name value
// task config name ""
if (args.size () > 1 ||
context.args[context.args.size () - 1] == "")
{
// Find existing entry & overwrite
std::string::size_type pos = contents.find (name + "=");
if (pos != std::string::npos)
{
std::string::size_type eol = contents.find_first_of ("\r\f\n", pos);
if (eol == std::string::npos)
throw std::string ("Cannot find EOL after entry '") + name + "'";
if (confirm (std::string ("Are you sure you want to change the value of '")
+ name
+ "' from '"
+ context.config.get(name)
+ "' to '"
+ value + "'?"))
{
contents = contents.substr (0, pos)
+ name + "=" + value
+ contents.substr (eol);
change = true;
}
}
// Not found, so append instead.
else
{
if (confirm (std::string ("Are you sure you want to add '") + name + "' with a value of '" + value + "'?"))
{
contents = contents
+ "\n"
+ name + "=" + value
+ "\n";
change = true;
}
}
}
// task config name
else
{
// Remove name
std::string::size_type pos = contents.find (name + "=");
if (pos == std::string::npos)
throw std::string ("No entry named '") + name + "' found";
std::string::size_type eol = contents.find_first_of ("\r\f\n", pos);
if (eol == std::string::npos)
throw std::string ("Cannot find EOL after entry '") + name + "'";
if (confirm (std::string ("Are you sure you want to remove '") + name + "'?"))
{
contents = contents.substr (0, pos) + contents.substr (eol + 1);
change = true;
}
}
// Write .taskrc (or equivalent)
if (change)
{
File::write (context.config.original_file, contents);
out << "Config file "
<< context.config.original_file.data
<< " modified."
<< std::endl;
}
else
out << "No changes made." << std::endl;
}
else
throw std::string ("Specify the name of a config variable to modify.");
outs = out.str ();
return rc;
}
// No arguments - display config values instead.
int width = context.getWidth ();
std::vector <std::string> all;
@ -955,6 +847,131 @@ int handleConfig (std::string &outs)
return rc;
}
////////////////////////////////////////////////////////////////////////////////
int handleConfig (std::string &outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-config-command"))
{
std::stringstream out;
// Obtain the arguments from the description. That way, things like '--'
// have already been handled.
std::vector <std::string> args;
split (args, context.task.get ("description"), ' ');
// Support:
// task config name value # set name to value
// task config name "" # set name to blank
// task config name # remove name
if (args.size () > 0)
{
std::string name = args[0];
std::string value = "";
if (args.size () > 1)
{
for (unsigned int i = 1; i < args.size (); ++i)
{
if (i > 1)
value += " ";
value += args[i];
}
}
if (name != "")
{
bool change = false;
// Read .taskrc (or equivalent)
std::string contents;
File::read (context.config.original_file, contents);
// task config name value
// task config name ""
if (args.size () > 1 ||
context.args[context.args.size () - 1] == "")
{
// Find existing entry & overwrite
std::string::size_type pos = contents.find (name + "=");
if (pos != std::string::npos)
{
std::string::size_type eol = contents.find_first_of ("\r\f\n", pos);
if (eol == std::string::npos)
throw std::string ("Cannot find EOL after entry '") + name + "'";
if (confirm (std::string ("Are you sure you want to change the value of '")
+ name
+ "' from '"
+ context.config.get(name)
+ "' to '"
+ value + "'?"))
{
contents = contents.substr (0, pos)
+ name + "=" + value
+ contents.substr (eol);
change = true;
}
}
// Not found, so append instead.
else
{
if (confirm (std::string ("Are you sure you want to add '") + name + "' with a value of '" + value + "'?"))
{
contents = contents
+ "\n"
+ name + "=" + value
+ "\n";
change = true;
}
}
}
// task config name
else
{
// Remove name
std::string::size_type pos = contents.find (name + "=");
if (pos == std::string::npos)
throw std::string ("No entry named '") + name + "' found";
std::string::size_type eol = contents.find_first_of ("\r\f\n", pos);
if (eol == std::string::npos)
throw std::string ("Cannot find EOL after entry '") + name + "'";
if (confirm (std::string ("Are you sure you want to remove '") + name + "'?"))
{
contents = contents.substr (0, pos) + contents.substr (eol + 1);
change = true;
}
}
// Write .taskrc (or equivalent)
if (change)
{
File::write (context.config.original_file, contents);
out << "Config file "
<< context.config.original_file.data
<< " modified."
<< std::endl;
}
else
out << "No changes made." << std::endl;
}
else
throw std::string ("Specify the name of a config variable to modify.");
outs = out.str ();
context.hooks.trigger ("post-config-command");
}
else
throw std::string ("Specify the name of a config variable to modify.");
}
return rc;
}
////////////////////////////////////////////////////////////////////////////////
int handleDelete (std::string &outs)
{

View file

@ -96,6 +96,7 @@
#define CMD_VERSION 228
#define CMD_SHELL 229
#define CMD_CONFIG 230
#define CMD_SHOW 231
// 3xx Attributes
#define ATT_PROJECT 300

View file

@ -71,6 +71,7 @@ int handleCompletionConfig (std::string &);
int handleCompletionVersion (std::string &);
int handleVersion (std::string &);
int handleConfig (std::string &);
int handleShow (std::string &);
int handleDelete (std::string &);
int handleStart (std::string &);
int handleStop (std::string &);

View file

@ -206,9 +206,13 @@ int shortUsage (std::string &outs)
table.addCell (row, 1, "task version");
table.addCell (row, 2, "Shows the task version number.");
row = table.addRow ();
table.addCell (row, 1, "task show [section-name]");
table.addCell (row, 2, "Shows the task entire configuration or a specific section.");
row = table.addRow ();
table.addCell (row, 1, "task config [name [value | '']]");
table.addCell (row, 2, "Shows the task configuration, or can add, modify and remove settings.");
table.addCell (row, 2, "Add, modify and remove settings in the task configuration.");
row = table.addRow ();
table.addCell (row, 1, "task help");

View file

@ -41,7 +41,7 @@ if (open my $fh, '>', 'color.rc')
}
# Test the add command.
my $output = qx{../task rc:color.rc config};
my $output = qx{../task rc:color.rc show};
like ($output, qr/that use deprecated underscores/ms, 'Deprecated color detected');
# Cleanup.

View file

@ -40,7 +40,7 @@ if (open my $fh, '>', 'obsolete.rc')
}
# Test the add command.
my $output = qx{../task rc:obsolete.rc config};
my $output = qx{../task rc:obsolete.rc show};
like ($output, qr/Your .taskrc file contains these unrecognized variables:\n/,
'unsupported configuration variable');

View file

@ -39,10 +39,10 @@ if (open my $fh, '>', 'rc.rc')
ok (-r 'rc.rc', 'Created rc.rc');
}
my $output = qx{../task rc:rc.rc config};
my $output = qx{../task rc:rc.rc show};
like ($output, qr/\sfoo\s+bar/, 'unmodified');
$output = qx{../task rc:rc.rc rc.foo:baz config};
$output = qx{../task rc:rc.rc rc.foo:baz show};
like ($output, qr/\sfoo\s+baz/, 'overridden');
unlink 'rc.rc';

View file

@ -53,34 +53,34 @@ ok (-d 'foo', 'Created default data directory');
# Add a setting.
qx{echo 'y'|../task rc:foo.rc config must_be_unique old};
my $output = qx{../task rc:foo.rc config};
my $output = qx{../task rc:foo.rc show};
like ($output, qr/^must_be_unique\s+old$/ms, 'config setting a new value');
qx{echo 'y'|../task rc:foo.rc config must_be_unique new};
$output = qx{../task rc:foo.rc config};
$output = qx{../task rc:foo.rc show};
like ($output, qr/^must_be_unique\s+new$/ms, 'config overwriting an existing value');
qx{echo 'y'|../task rc:foo.rc config must_be_unique ''};
$output = qx{../task rc:foo.rc config};
$output = qx{../task rc:foo.rc show};
like ($output, qr/^must_be_unique$/ms, 'config setting a blank value');
qx{echo 'y'|../task rc:foo.rc config must_be_unique};
$output = qx{../task rc:foo.rc config};
$output = qx{../task rc:foo.rc show};
unlike ($output, qr/^must_be_unique/ms, 'config removing a value');
# 'report.:b' is designed to get past the config command checks for recognized
# names.
qx{echo 'y'|../task rc:foo.rc config -- report.:b +c};
$output = qx{../task rc:foo.rc config};
$output = qx{../task rc:foo.rc show};
like ($output, qr/^report\.:b\s+\+c/ms, 'the -- operator is working');
# Make sure the value is accepted if it has multiple words.
qx{echo 'y'|../task rc:foo.rc config must_be_unique 'one two three'};
$output = qx{../task rc:foo.rc config};
$output = qx{../task rc:foo.rc show};
like ($output, qr/^must_be_unique\s+one two three$/ms, 'config allows multi-word quoted values');
qx{echo 'y'|../task rc:foo.rc config must_be_unique one two three};
$output = qx{../task rc:foo.rc config};
$output = qx{../task rc:foo.rc show};
like ($output, qr/^must_be_unique\s+one two three$/ms, 'config allows multi-word unquoted values');
rmtree 'foo', 0, 0;