mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-28 13:37:20 +02:00
Enhancement
- Rewrote the code that checks for and creates ~/.taskrc and ~/.task if necessary. - Takes into consideration the following: - rc:<file> - <file>:data.location - <~/.taskrc>:data.location - rc.data.location:<dir>
This commit is contained in:
parent
3072476e53
commit
a23a350b8b
3 changed files with 166 additions and 160 deletions
254
src/Config.cpp
254
src/Config.cpp
|
@ -95,161 +95,141 @@ bool Config::load (const std::string& file)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Config::createDefault (const std::string& home)
|
void Config::createDefaultRC (const std::string& rc, const std::string& data)
|
||||||
{
|
{
|
||||||
// Strip trailing slash off home directory, if necessary.
|
// Create a sample .taskrc file.
|
||||||
std::string terminatedHome = home;
|
std::stringstream contents;
|
||||||
if (home[home.length () - 1] == '/')
|
|
||||||
terminatedHome = home.substr (0, home.length () - 1);
|
|
||||||
|
|
||||||
// Determine default names of init file and task directory.
|
contents << "# ...\n"
|
||||||
std::string rcFile = terminatedHome + "/.taskrc"; // TODO i18n
|
<< "\n"
|
||||||
std::string dataDir = terminatedHome + "/.task"; // TODO i18n
|
<< "data.location=" << data << "\n"
|
||||||
|
<< "confirmation=yes\n"
|
||||||
|
<< "echo.command=yes\n"
|
||||||
|
<< "next=2\n"
|
||||||
|
<< "bulk=2\n"
|
||||||
|
<< "dateformat=m/d/Y\n"
|
||||||
|
<< "#monthsperline=2\n"
|
||||||
|
<< "#defaultwidth=80\n"
|
||||||
|
<< "curses=on\n"
|
||||||
|
<< "color=on\n"
|
||||||
|
<< "due=7\n"
|
||||||
|
<< "nag=You have higher priority tasks.\n"
|
||||||
|
<< "locking=on\n"
|
||||||
|
<< "#editor=vi\n"
|
||||||
|
<< "weekstart=Sunday\n"
|
||||||
|
<< "displayweeknumber=yes\n"
|
||||||
|
|
||||||
// If rcFile is not found, offer to create one.
|
<< "color.overdue=bold_red\n"
|
||||||
if (-1 == access (rcFile.c_str (), F_OK))
|
<< "color.due=bold_yellow\n"
|
||||||
{
|
<< "color.pri.H=bold\n"
|
||||||
if (confirm (
|
<< "#color.pri.M=on_yellow\n"
|
||||||
"A configuration file could not be found in " // TODO i18n
|
<< "#color.pri.L=on_green\n"
|
||||||
+ rcFile
|
<< "#color.pri.none=white on_blue\n"
|
||||||
+ "\n\n" // no i18n
|
<< "color.active=bold_cyan\n"
|
||||||
+ "Would you like a sample .taskrc created, so task can proceed?")) // TODO i18n
|
<< "color.tagged=yellow\n"
|
||||||
{
|
<< "#color.tag.bug=yellow\n"
|
||||||
// Create a sample .taskrc file.
|
<< "#color.project.garden=on_green\n"
|
||||||
FILE* out;
|
<< "#color.keyword.car=on_blue\n"
|
||||||
if ((out = fopen (rcFile.c_str (), "w")))
|
<< "#color.recurring=on_red\n"
|
||||||
{
|
<< "#color.header=bold_green\n"
|
||||||
fprintf (out, "data.location=%s\n", dataDir.c_str ());
|
<< "#color.footnote=bold_green\n"
|
||||||
fprintf (out, "confirmation=yes\n");
|
<< "#color.message=bold_red\n"
|
||||||
fprintf (out, "echo.command=yes\n");
|
<< "\n"
|
||||||
fprintf (out, "next=2\n");
|
<< "# Shadow File Example\n"
|
||||||
fprintf (out, "bulk=2\n");
|
<< "#shadow.file=" << data << "/shadow.txt\n"
|
||||||
fprintf (out, "dateformat=m/d/Y\n");
|
<< "#shadow.command=list\n"
|
||||||
fprintf (out, "#monthsperline=2\n");
|
<< "#shadow.notify=on\n"
|
||||||
fprintf (out, "#defaultwidth=80\n");
|
<< "\n"
|
||||||
fprintf (out, "curses=on\n");
|
<< "#default.project=foo\n"
|
||||||
fprintf (out, "color=on\n");
|
<< "#default.priority=M\n"
|
||||||
fprintf (out, "due=7\n");
|
<< "default.command=list\n"
|
||||||
fprintf (out, "nag=You have higher priority tasks.\n");
|
|
||||||
fprintf (out, "locking=on\n");
|
|
||||||
fprintf (out, "#editor=vi\n");
|
|
||||||
fprintf (out, "weekstart=Sunday\n");
|
|
||||||
fprintf (out, "displayweeknumber=yes\n");
|
|
||||||
|
|
||||||
fprintf (out, "color.overdue=bold_red\n");
|
// Custom reports.
|
||||||
fprintf (out, "color.due=bold_yellow\n");
|
<< "# Fields: id,uuid,project,priority,entry,start,due,recur,age,active,tags,description\n"
|
||||||
fprintf (out, "color.pri.H=bold\n");
|
<< "# description_only\n"
|
||||||
fprintf (out, "#color.pri.M=on_yellow\n");
|
<< "# Description: This report is ...\n"
|
||||||
fprintf (out, "#color.pri.L=on_green\n");
|
<< "# Sort: due+,priority-,project+\n"
|
||||||
fprintf (out, "#color.pri.none=white on_blue\n");
|
<< "# Filter: pro:x pri:H +bug limit:10\n"
|
||||||
fprintf (out, "color.active=bold_cyan\n");
|
|
||||||
fprintf (out, "color.tagged=yellow\n");
|
|
||||||
fprintf (out, "#color.tag.bug=yellow\n");
|
|
||||||
fprintf (out, "#color.project.garden=on_green\n");
|
|
||||||
fprintf (out, "#color.keyword.car=on_blue\n");
|
|
||||||
fprintf (out, "#color.recurring=on_red\n");
|
|
||||||
fprintf (out, "#color.header=bold_green\n");
|
|
||||||
fprintf (out, "#color.footnote=bold_green\n");
|
|
||||||
fprintf (out, "#color.message=bold_red\n");
|
|
||||||
fprintf (out, "#shadow.file=%s/shadow.txt\n", dataDir.c_str ());
|
|
||||||
fprintf (out, "#shadow.command=list\n");
|
|
||||||
fprintf (out, "#shadow.notify=on\n");
|
|
||||||
fprintf (out, "#default.project=foo\n");
|
|
||||||
fprintf (out, "#default.priority=M\n");
|
|
||||||
fprintf (out, "default.command=list\n");
|
|
||||||
|
|
||||||
// Custom reports.
|
<< "report.long.description=Lists all task, all data, matching the specified criteria\n"
|
||||||
fprintf (out, "# Fields: id,uuid,project,priority,entry,start,due,recur,age,active,tags,description\n"); // TODO i18n
|
<< "report.long.columns=id,project,priority,entry,start,due,recur,age,tags,description\n"
|
||||||
fprintf (out, "# description_only\n"); // TODO i18n
|
<< "report.long.labels=ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description\n"
|
||||||
fprintf (out, "# Description: This report is ...\n"); // TODO i18n
|
<< "report.long.sort=due+,priority-,project+\n"
|
||||||
fprintf (out, "# Sort: due+,priority-,project+\n"); // TODO i18n
|
<< "report.long.filter=status:pending\n"
|
||||||
fprintf (out, "# Filter: pro:x pri:H +bug limit:10\n"); // TODO i18n
|
|
||||||
|
|
||||||
fprintf (out, "report.long.description=Lists all task, all data, matching the specified criteria\n"); // TODO i18n
|
<< "report.list.description=Lists all tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.long.columns=id,project,priority,entry,start,due,recur,age,tags,description\n"); // TODO i18n
|
<< "report.list.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.long.labels=ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description\n"); // TODO i18n
|
<< "report.list.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.long.sort=due+,priority-,project+\n"); // TODO i18n
|
<< "report.list.sort=due+,priority-,project+\n"
|
||||||
fprintf (out, "report.long.filter=status:pending\n"); // TODO i18n
|
<< "report.list.filter=status:pending\n"
|
||||||
|
|
||||||
fprintf (out, "report.list.description=Lists all tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.ls.description=Minimal listing of all tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.list.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
<< "report.ls.columns=id,project,priority,description\n"
|
||||||
fprintf (out, "report.list.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
<< "report.ls.labels=ID,Project,Pri,Description\n"
|
||||||
fprintf (out, "report.list.sort=due+,priority-,project+\n"); // TODO i18n
|
<< "report.ls.sort=priority-,project+\n"
|
||||||
fprintf (out, "report.list.filter=status:pending\n"); // TODO i18n
|
<< "report.ls.filter=status:pending\n"
|
||||||
|
|
||||||
fprintf (out, "report.ls.description=Minimal listing of all tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.newest.description=Shows the newest tasks\n"
|
||||||
fprintf (out, "report.ls.columns=id,project,priority,description\n"); // TODO i18n
|
<< "report.newest.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.ls.labels=ID,Project,Pri,Description\n"); // TODO i18n
|
<< "report.newest.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.ls.sort=priority-,project+\n"); // TODO i18n
|
<< "report.newest.sort=id-\n"
|
||||||
fprintf (out, "report.ls.filter=status:pending\n"); // TODO i18n
|
<< "report.newest.filter=status:pending limit:10\n"
|
||||||
|
|
||||||
fprintf (out, "report.newest.description=Shows the newest tasks\n"); // TODO i18n
|
<< "report.oldest.description=Shows the oldest tasks\n"
|
||||||
fprintf (out, "report.newest.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
<< "report.oldest.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.newest.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
<< "report.oldest.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.newest.sort=id-\n"); // TODO i18n
|
<< "report.oldest.sort=id+\n"
|
||||||
fprintf (out, "report.newest.filter=status:pending limit:10\n"); // TODO i18n
|
<< "report.oldest.filter=status:pending limit:10\n"
|
||||||
|
|
||||||
fprintf (out, "report.oldest.description=Shows the oldest tasks\n"); // TODO i18n
|
<< "report.overdue.description=Lists overdue tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.oldest.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
<< "report.overdue.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.oldest.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
<< "report.overdue.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.oldest.sort=id+\n"); // TODO i18n
|
<< "report.overdue.sort=due+,priority-,project+\n"
|
||||||
fprintf (out, "report.oldest.filter=status:pending limit:10\n"); // TODO i18n
|
<< "report.overdue.filter=status:pending due.before:today\n"
|
||||||
|
|
||||||
fprintf (out, "report.overdue.description=Lists overdue tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.active.description=Lists active tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.overdue.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
<< "report.active.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.overdue.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
<< "report.active.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.overdue.sort=due+,priority-,project+\n"); // TODO i18n
|
<< "report.active.sort=due+,priority-,project+\n"
|
||||||
fprintf (out, "report.overdue.filter=status:pending due.before:today\n"); // TODO i18n
|
<< "report.active.filter=status:pending start.any:\n"
|
||||||
|
|
||||||
fprintf (out, "report.active.description=Lists active tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.completed.description=Lists completed tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.active.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
<< "report.completed.columns=end,project,priority,age,description\n"
|
||||||
fprintf (out, "report.active.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
<< "report.completed.labels=Complete,Project,Pri,Age,Description\n"
|
||||||
fprintf (out, "report.active.sort=due+,priority-,project+\n"); // TODO i18n
|
<< "report.completed.sort=end+,priority-,project+\n"
|
||||||
fprintf (out, "report.active.filter=status:pending start.any:\n"); // TODO i18n
|
<< "report.completed.filter=status:completed\n"
|
||||||
|
|
||||||
fprintf (out, "report.completed.description=Lists completed tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.recurring.description=Lists recurring tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.completed.columns=end,project,priority,age,description\n"); // TODO i18n
|
<< "report.recurring.columns=id,project,priority,due,recur,active,age,description\n"
|
||||||
fprintf (out, "report.completed.labels=Complete,Project,Pri,Age,Description\n"); // TODO i18n
|
<< "report.recurring.labels=ID,Project,Pri,Due,Recur,Active,Age,Description\n"
|
||||||
fprintf (out, "report.completed.sort=end+,priority-,project+\n"); // TODO i18n
|
<< "report.recurring.sort=due+,priority-,project+\n"
|
||||||
fprintf (out, "report.completed.filter=status:completed\n"); // TODO i18n
|
<< "report.recurring.filter=status:pending parent.any:\n"
|
||||||
|
|
||||||
fprintf (out, "report.recurring.description=Lists recurring tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.waiting.description=Lists all waiting tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.recurring.columns=id,project,priority,due,recur,active,age,description\n"); // TODO i18n
|
<< "report.waiting.columns=id,project,priority,wait,age,description\n"
|
||||||
fprintf (out, "report.recurring.labels=ID,Project,Pri,Due,Recur,Active,Age,Description\n"); // TODO i18n
|
<< "report.waiting.labels=ID,Project,Pri,Wait,Age,Description\n"
|
||||||
fprintf (out, "report.recurring.sort=due+,priority-,project+\n"); // TODO i18n
|
<< "report.waiting.sort=wait+,priority-,project+\n"
|
||||||
fprintf (out, "report.recurring.filter=status:pending parent.any:\n"); // TODO i18n
|
<< "report.waiting.filter=status:waiting\n"
|
||||||
|
|
||||||
fprintf (out, "report.waiting.description=Lists all waiting tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.all.description=Lists all tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.waiting.columns=id,project,priority,wait,age,description\n"); // TODO i18n
|
<< "report.all.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.waiting.labels=ID,Project,Pri,Wait,Age,Description\n"); // TODO i18n
|
<< "report.all.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.waiting.sort=wait+,priority-,project+\n"); // TODO i18n
|
<< "report.all.sort=due+,priority-,project+\n"
|
||||||
fprintf (out, "report.waiting.filter=status:waiting\n"); // TODO i18n
|
|
||||||
|
|
||||||
fprintf (out, "report.all.description=Lists all tasks matching the specified criteria\n"); // TODO i18n
|
<< "report.next.description=Lists all tasks matching the specified criteria\n"
|
||||||
fprintf (out, "report.all.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
<< "report.next.columns=id,project,priority,due,active,age,description\n"
|
||||||
fprintf (out, "report.all.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
<< "report.next.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||||
fprintf (out, "report.all.sort=due+,priority-,project+\n"); // TODO i18n
|
<< "report.next.sort=due+,priority-,project+\n"
|
||||||
|
<< "report.next.filter=status:pending\n";
|
||||||
|
|
||||||
fprintf (out, "report.next.description=Lists all tasks matching the specified criteria\n"); // TODO i18n
|
spit (rc, contents.str ());
|
||||||
fprintf (out, "report.next.columns=id,project,priority,due,active,age,description\n"); // TODO i18n
|
}
|
||||||
fprintf (out, "report.next.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n
|
|
||||||
fprintf (out, "report.next.sort=due+,priority-,project+\n"); // TODO i18n
|
|
||||||
fprintf (out, "report.next.filter=status:pending\n"); // TODO i18n
|
|
||||||
|
|
||||||
fclose (out);
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Config::createDefaultData (const std::string& data)
|
||||||
std::cout << "Done." << std::endl; // TODO i18n
|
{
|
||||||
}
|
if (access (data.c_str (), F_OK))
|
||||||
}
|
mkdir (data.c_str (), S_IRWXU);
|
||||||
}
|
|
||||||
|
|
||||||
this->load (rcFile);
|
|
||||||
|
|
||||||
// Get the data.location value from the (potentially newly created) .taskrc
|
|
||||||
// file.
|
|
||||||
dataDir = this->get ("data.location", dataDir); // no i18n
|
|
||||||
if (-1 == access (dataDir.c_str (), F_OK))
|
|
||||||
mkdir (dataDir.c_str (), S_IRWXU);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -41,7 +41,8 @@ public:
|
||||||
Config& operator= (const Config&);
|
Config& operator= (const Config&);
|
||||||
|
|
||||||
bool load (const std::string&);
|
bool load (const std::string&);
|
||||||
void createDefault (const std::string&);
|
void createDefaultRC (const std::string&, const std::string&);
|
||||||
|
void createDefaultData (const std::string&);
|
||||||
void setDefaults ();
|
void setDefaults ();
|
||||||
|
|
||||||
const std::string get (const char*);
|
const std::string get (const char*);
|
||||||
|
|
|
@ -293,39 +293,63 @@ std::string Context::canonicalize (const std::string& input) const
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Context::loadCorrectConfigFile ()
|
void Context::loadCorrectConfigFile ()
|
||||||
{
|
{
|
||||||
bool needNewConfig = true;
|
// Set up default locations.
|
||||||
|
struct passwd* pw = getpwuid (getuid ());
|
||||||
|
if (!pw)
|
||||||
|
throw std::string (
|
||||||
|
stringtable.get (
|
||||||
|
SHELL_READ_PASSWD,
|
||||||
|
"Could not read home directory from the passwd file."));
|
||||||
|
|
||||||
|
std::string home = pw->pw_dir;
|
||||||
|
std::string rc = home + "/.taskrc";
|
||||||
|
std::string data = home + "/.task";
|
||||||
|
|
||||||
|
// Is there an override for rc?
|
||||||
foreach (arg, args)
|
foreach (arg, args)
|
||||||
{
|
|
||||||
if (arg->substr (0, 3) == "rc:")
|
if (arg->substr (0, 3) == "rc:")
|
||||||
{
|
{
|
||||||
std::string file = arg->substr (3, std::string::npos);
|
rc = arg->substr (3, std::string::npos);
|
||||||
if (access (file.c_str (), F_OK))
|
|
||||||
throw std::string ("Could not read configuration file '") + file + "'";
|
|
||||||
|
|
||||||
header (std::string ("Using alternate .taskrc file ") + file); // TODO i18n
|
|
||||||
config.clear (); // Dump current values.
|
|
||||||
config.setDefaults (); // Add in the custom reports.
|
|
||||||
config.load (file); // Load new file.
|
|
||||||
needNewConfig = false;
|
|
||||||
|
|
||||||
// No need to handle it again.
|
|
||||||
args.erase (arg);
|
args.erase (arg);
|
||||||
|
header ("Using alternate .taskrc file " + rc); // TODO i18n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (needNewConfig)
|
// Load rc file.
|
||||||
|
config.clear (); // Dump current values.
|
||||||
|
config.setDefaults (); // Add in the custom reports.
|
||||||
|
config.load (rc); // Load new file.
|
||||||
|
|
||||||
|
if (config.get ("data.location") != "")
|
||||||
|
data = config.get ("data.location");
|
||||||
|
|
||||||
|
// Is there an override for data?
|
||||||
|
foreach (arg, args)
|
||||||
|
if (arg->substr (0, 17) == "rc.data.location:")
|
||||||
|
{
|
||||||
|
data = arg->substr (17, std::string::npos);
|
||||||
|
header ("Using alternate data.location " + data); // TODO i18n
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we need to create a default rc?
|
||||||
|
if (access (rc.c_str (), F_OK) &&
|
||||||
|
confirm ("A configuration file could not be found in " // TODO i18n
|
||||||
|
+ home
|
||||||
|
+ "\n\n"
|
||||||
|
+ "Would you like a sample .taskrc created, so task can proceed?"))
|
||||||
{
|
{
|
||||||
struct passwd* pw = getpwuid (getuid ());
|
config.createDefaultRC (rc, data);
|
||||||
if (!pw)
|
|
||||||
throw std::string (
|
|
||||||
stringtable.get (SHELL_READ_PASSWD,
|
|
||||||
"Could not read home directory from the passwd file."));
|
|
||||||
|
|
||||||
config.createDefault (pw->pw_dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create data location, if necessary.
|
||||||
|
config.createDefaultData (data);
|
||||||
|
|
||||||
|
// Load rc file.
|
||||||
|
config.clear (); // Dump current values.
|
||||||
|
config.setDefaults (); // Add in the custom reports.
|
||||||
|
config.load (rc); // Load new file.
|
||||||
|
|
||||||
// Apply overrides of type: "rc.name:value"
|
// Apply overrides of type: "rc.name:value"
|
||||||
std::vector <std::string> filtered;
|
std::vector <std::string> filtered;
|
||||||
foreach (arg, args)
|
foreach (arg, args)
|
||||||
|
@ -351,6 +375,7 @@ void Context::loadCorrectConfigFile ()
|
||||||
}
|
}
|
||||||
|
|
||||||
args = filtered;
|
args = filtered;
|
||||||
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue