From 1ef7b0c43abdefede71990054f6a31a513b4069b Mon Sep 17 00:00:00 2001
From: Paul Beckingham
Date: Wed, 25 Jun 2008 01:29:42 -0400
Subject: [PATCH] - Now allows rc: override of ~/.taskrc file.
---
ChangeLog | 2 +
TUTORIAL | 88 +++++++++++++++++++++++++++-----------------
html/task.html | 99 +++++++++++++++++++++++++++++++-------------------
src/parse.cpp | 86 +++++++++++++++++++++++--------------------
src/task.cpp | 39 +++++++++++++++-----
5 files changed, 195 insertions(+), 119 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 93a597d23..bc73770bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,10 +11,12 @@ represents a feature release, and the Z represents a patch.
- Dependencies
- Recurring tasks
+
1.4.0 ()
+ "task undelete" can now undelete erroneously deleted tasks, provided no
reports have been run (and therefore TDB::gc run)
+ Added averages to the "task history" report
+ + Added ability to override ~/.taskrc with rc:
+ Bug: Fixed where Esc[0m sequences were being emitted for no good reason
+ Bug: Fixed underlined table headers when color is turned off
diff --git a/TUTORIAL b/TUTORIAL
index 6bfe53abe..e3f4448d1 100644
--- a/TUTORIAL
+++ b/TUTORIAL
@@ -576,39 +576,6 @@ with no arguments will generate a help message that lists all these commands.
-Interacting with the Shell
---------------------------
-
- Certain characters are interpreted by the shell. For example, the "&". If
- you wish to include the & in a task description, you need to escape it, so
- the shell doesn't interpret it. For example:
-
- % task add Buy bread & milk
-
- This command is an error because of the &. The shell will consider this to
- be two commands:
-
- % task add Buy bread &
- % milk
-
- The shell treats the & character as an indicator that the command is complete
- and should be run in the background. Then the shell considers "milk" to be a
- command all by itself. Which it is not. One way to get around this is to
- individually escape the & character:
-
- % task add Buy bread \& milk
-
- Another is to quote the entire description, with either ' or " characters:
-
- % task add "Buy bread & milk"
-
- Task itself interprets the commands, and it too can make mistakes. For
- example, any colon : character will be interpreted by task as a delimiter
- between an attribute name and its value. Currently there is no workaround
- for this.
-
-
-
% task fg:... bg:...
-------------------------
@@ -645,6 +612,61 @@ Interacting with the Shell
+% task rc: ...
+--------------------
+
+ By specifying rc:, it is possible to force task to use an alternate
+ .taskrc file. By default, task looks in your home directory, so these two
+ commands are essentially identical:
+
+ % task list
+ % task rc:~/.taskrc list
+
+ What this override allows, is the possibility of keeping your task lists
+ completely separate, say for work and home. This can be accomplished with
+ the following commands (valid for bash):
+
+ % alias htask="task rc:/home/me/.taskrc_home"
+ % alias wtask="task rc:/home/me/.taskrc_work"
+ % htask list
+ ...
+ % wtask list
+ ...
+
+
+
+Interacting with the Shell
+--------------------------
+
+ Certain characters are interpreted by the shell. For example, the "&". If
+ you wish to include the & in a task description, you need to escape it, so
+ the shell doesn't interpret it. For example:
+
+ % task add Buy bread & milk
+
+ This command is an error because of the &. The shell will consider this to
+ be two commands:
+
+ % task add Buy bread &
+ % milk
+
+ The shell treats the & character as an indicator that the command is complete
+ and should be run in the background. Then the shell considers "milk" to be a
+ command all by itself. Which it is not. One way to get around this is to
+ individually escape the & character:
+
+ % task add Buy bread \& milk
+
+ Another is to quote the entire description, with either ' or " characters:
+
+ % task add "Buy bread & milk"
+
+ Task itself interprets the commands, and it too can make mistakes. For
+ example, any colon : character will be interpreted by task as a delimiter
+ between an attribute name and its value. Currently there is no workaround
+ for this.
+
+
Configuring Task
----------------
diff --git a/html/task.html b/html/task.html
index 094a19b24..d77bf4102 100644
--- a/html/task.html
+++ b/html/task.html
@@ -39,7 +39,7 @@
Download the
latest version
- of the task source code (1.4.0, ????????????????????????????????????????????????).
+ of the task source code (1.4.0, ????????????????????).
@@ -51,6 +51,8 @@
Added "task undelete" feature to restore a (very) recently deleted
task
Added averages to the "task history" report
+ Added support for rc:<file> to allow override of the default
+ ~/.taskrc file
Fixed bug where Esc[0m sequences were being emitted for no good reason
Fixed bug where table headers are underlined when color is turned off
@@ -711,6 +713,65 @@ ID Project Pri Description
all the current configuration settings, as read from the .taskrc
file.
+
+ % task rc:<file> ...
+
+ By specifying rc:, it is possible to force task to use an alternate
+ .taskrc file. By default, task looks in your home directory, so these two
+ commands are essentially identical:
+
+
+ % task list
+% task rc:~/.taskrc list
+
+
+ What this override allows, is the possibility of keeping your task lists
+ completely separate, say for work and home. This can be accomplished with
+ the following commands (valid for bash):
+
+
+ % alias htask="task rc:/home/me/.taskrc_home"
+% alias wtask="task rc:/home/me/.taskrc_work"
+% htask list
+...
+% wtask list
+...
+
+ % task <id> fg:... bg:...
+
+ Not strictly a command, the setting of the fg and bg (foreground
+ and background) attributes determines the colors used to represent
+ the task. Valid foreground colors are:
+
+
+ bold underline bold_underline
+black bold_black underline_black bold_underline_black
+red bold_red underline_red bold_underline_red
+green bold_green underline_green bold_underline_green
+yellow bold_yellow underline_yellow bold_underline_yellow
+blue bold_blue underline_blue bold_underline_blue
+magenta bold_magenta underline_magenta bold_underline_magenta
+cyan bold_cyan underline_cyan bold_underline_cyan
+white bold_white underline_white bold_underline_white
+
+
+ Note that these are not just colors, but combinations of colors and
+ attributes. Valid background colors are:
+
+
+ on_black on_bright_black
+on_red on_bright_red
+on_green on_bright_green
+on_yellow on_bright_yellow
+on_blue on_bright_blue
+on_magenta on_bright_magenta
+on_cyan on_bright_cyan
+on_white on_bright_white
+
+
+ Note also that this capability does depend on whether your terminal
+ program can display these colors.
+
@@ -756,42 +817,6 @@ ID Project Pri Description
delimiter between an attribute name and its value. Currently there
is no workaround for this.
-
- % task <id> fg:... bg:...
-
- Not strictly a command, the setting of the fg and bg (foreground
- and background) attributes determines the colors used to represent
- the task. Valid foreground colors are:
-
-
- bold underline bold_underline
-black bold_black underline_black bold_underline_black
-red bold_red underline_red bold_underline_red
-green bold_green underline_green bold_underline_green
-yellow bold_yellow underline_yellow bold_underline_yellow
-blue bold_blue underline_blue bold_underline_blue
-magenta bold_magenta underline_magenta bold_underline_magenta
-cyan bold_cyan underline_cyan bold_underline_cyan
-white bold_white underline_white bold_underline_white
-
-
- Note that these are not just colors, but combinations of colors and
- attributes. Valid background colors are:
-
-
- on_black on_bright_black
-on_red on_bright_red
-on_green on_bright_green
-on_yellow on_bright_yellow
-on_blue on_bright_blue
-on_magenta on_bright_magenta
-on_cyan on_bright_cyan
-on_white on_bright_white
-
-
- Note also that this capability does depend on whether your terminal
- program can display these colors.
-
diff --git a/src/parse.cpp b/src/parse.cpp
index 8408ce535..207c950b4 100644
--- a/src/parse.cpp
+++ b/src/parse.cpp
@@ -346,54 +346,60 @@ void parse (
for (size_t i = 0; i < args.size (); ++i)
{
std::string arg (args[i]);
- size_t colon; // Pointer to colon in argument.
- std::string from;
- std::string to;
- // An id is the first argument found that contains all digits.
- if (command != "add" && // "add" doesn't require an ID
- task.getId () == 0 &&
- validId (arg))
- task.setId (::atoi (arg.c_str ()));
-
- // Tags begin with + or - and contain arbitrary text.
- else if (validTag (arg))
+ // Ignore any argument that is "rc:...", because that is the command line
+ // specified rc file.
+ if (arg.substr (0, 3) != "rc:")
{
- if (arg[0] == '+')
- task.addTag (arg.substr (1, std::string::npos));
- else if (arg[0] == '-')
- task.addRemoveTag (arg.substr (1, std::string::npos));
- }
+ size_t colon; // Pointer to colon in argument.
+ std::string from;
+ std::string to;
- // Attributes contain a constant string followed by a colon, followed by a
- // value.
- else if ((colon = arg.find (":")) != std::string::npos)
- {
- std::string name = arg.substr (0, colon);
- std::string value = arg.substr (colon + 1, std::string::npos);
+ // An id is the first argument found that contains all digits.
+ if (command != "add" && // "add" doesn't require an ID
+ task.getId () == 0 &&
+ validId (arg))
+ task.setId (::atoi (arg.c_str ()));
- if (validAttribute (name, value, conf))
- task.setAttribute (name, value);
- }
+ // Tags begin with + or - and contain arbitrary text.
+ else if (validTag (arg))
+ {
+ if (arg[0] == '+')
+ task.addTag (arg.substr (1, std::string::npos));
+ else if (arg[0] == '-')
+ task.addRemoveTag (arg.substr (1, std::string::npos));
+ }
- // Substitution of description text.
- else if (validSubstitution (arg, from, to))
- {
- task.setSubstitution (from, to);
- }
+ // Attributes contain a constant string followed by a colon, followed by a
+ // value.
+ else if ((colon = arg.find (":")) != std::string::npos)
+ {
+ std::string name = arg.substr (0, colon);
+ std::string value = arg.substr (colon + 1, std::string::npos);
- // Command.
- else if (command == "")
- {
- if (!isCommand (arg))
+ if (validAttribute (name, value, conf))
+ task.setAttribute (name, value);
+ }
+
+ // Substitution of description text.
+ else if (validSubstitution (arg, from, to))
+ {
+ task.setSubstitution (from, to);
+ }
+
+ // Command.
+ else if (command == "")
+ {
+ if (!isCommand (arg))
+ descCandidate += std::string (arg) + " ";
+ else if (validCommand (arg))
+ command = arg;
+ }
+
+ // Anything else is just considered description.
+ else
descCandidate += std::string (arg) + " ";
- else if (validCommand (arg))
- command = arg;
}
-
- // Anything else is just considered description.
- else
- descCandidate += std::string (arg) + " ";
}
if (validDescription (descCandidate))
diff --git a/src/task.cpp b/src/task.cpp
index 74b592834..654247f2e 100644
--- a/src/task.cpp
+++ b/src/task.cpp
@@ -45,7 +45,7 @@
#endif
////////////////////////////////////////////////////////////////////////////////
-void shortUsage (Config& conf)
+static void shortUsage (Config& conf)
{
Table table;
int width = conf.get ("defaultwidth", 80);
@@ -193,7 +193,7 @@ void shortUsage (Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
-void longUsage (Config& conf)
+static void longUsage (Config& conf)
{
shortUsage (conf);
@@ -210,6 +210,7 @@ void longUsage (Config& conf)
<< " due: Due date" << "\n"
<< " fg: Foreground color" << "\n"
<< " bg: Background color" << "\n"
+ << " rc: Alternate .taskrc file" << "\n"
<< "\n"
<< "Any command or attribute name may be abbreviated if still unique:" << "\n"
<< " task list project:Home" << "\n"
@@ -224,6 +225,32 @@ void longUsage (Config& conf)
<< std::endl;
}
+////////////////////////////////////////////////////////////////////////////////
+void loadConfFile (int argc, char** argv, Config& conf)
+{
+ for (int i = 1; i < argc; ++i)
+ {
+ if (! strncmp (argv[i], "rc:", 3))
+ {
+ if (! access (&(argv[i][3]), F_OK))
+ {
+ std::string file = &(argv[i][3]);
+ conf.load (file);
+ return;
+ }
+ else
+ throw std::string ("Could not read configuration file '") + &(argv[i][3]) + "'";
+ }
+ }
+
+ struct passwd* pw = getpwuid (getuid ());
+ if (!pw)
+ throw std::string ("Could not read home directory from passwd file.");
+
+ std::string file = pw->pw_dir;
+ conf.createDefault (file);
+}
+
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
@@ -242,13 +269,7 @@ int main (int argc, char** argv)
// Load the config file from the home directory. If the file cannot be
// found, offer to create a sample one.
Config conf;
- struct passwd* pw = getpwuid (getuid ());
- if (!pw)
- throw std::string ("Could not read home directory from passwd file.");
-
- // Create a default config file and data directory if necessary.
- std::string home = pw->pw_dir;
- conf.createDefault (home);
+ loadConfFile (argc, argv, conf);
TDB tdb;
tdb.dataDirectory (conf.get ("data.location"));