| 1 |
#include <unistd.h> |
|---|
| 2 |
#include <cstdlib> |
|---|
| 3 |
#include <cstring> |
|---|
| 4 |
#include <cstdio> |
|---|
| 5 |
#include <sstream> |
|---|
| 6 |
#include <stdexcept> |
|---|
| 7 |
#include "support.h" |
|---|
| 8 |
#include "TodoDB.h" |
|---|
| 9 |
#include "Strings.h" |
|---|
| 10 |
#include "CommandArgs.h" |
|---|
| 11 |
#include "todoterm.h" |
|---|
| 12 |
#include "config.h" |
|---|
| 13 |
#include "todorl.h" |
|---|
| 14 |
|
|---|
| 15 |
using namespace str; |
|---|
| 16 |
static bool nukeonhit = false; |
|---|
| 17 |
|
|---|
| 18 |
Options options; |
|---|
| 19 |
|
|---|
| 20 |
Options::Options() : |
|---|
| 21 |
verbose(0), purgeage(0), mono(false), paranoid(false), global(false), |
|---|
| 22 |
summary(false), timeout(false), comment(false), |
|---|
| 23 |
database(".todo"), |
|---|
| 24 |
priority(Todo::None), |
|---|
| 25 |
mode(TodoDB::View), |
|---|
| 26 |
backups(0), timeoutseconds(0) { |
|---|
| 27 |
|
|---|
| 28 |
// default formatting strings |
|---|
| 29 |
format["date"] = "%c"; |
|---|
| 30 |
format["display"] = "%4>%i%f%[info]%2n.%[priority]%+1T\n"; |
|---|
| 31 |
format["comment-display"] = "%4>%i%f%[info]%2n.%[priority]%+1T\n%+1i%[comment](Comment: %C)\n"; |
|---|
| 32 |
format["verbose-display"] = "%i%[info]%f%2n.%[priority]%+1T\n%+1i%[info]Added: %[normal]%c %[info]Completed: %[normal]%d\n%+1i%[info]Duration: %[normal]%D %[info]Priority: %[normal]%p\n\n"; |
|---|
| 33 |
format["generated"] = "%2>%i-%+1T\n%+1i(added %c, %d, priority %p)\n\n"; |
|---|
| 34 |
format["verbose-generated"] = "%2>%i- %+1T\n\n%+1iAdded: %c Completed: %d\n%+1iDuration: %D Priority: %p\n\n\n"; |
|---|
| 35 |
|
|---|
| 36 |
loaders.push_back("xml"); |
|---|
| 37 |
loaders.push_back("binary"); |
|---|
| 38 |
|
|---|
| 39 |
if (getenv("HOME")) |
|---|
| 40 |
globaldatabase = string(getenv("HOME")) + "/.todo_global"; |
|---|
| 41 |
else |
|---|
| 42 |
globaldatabase = ""; |
|---|
| 43 |
|
|---|
| 44 |
filename = ""; |
|---|
| 45 |
|
|---|
| 46 |
columns = getWidth(); |
|---|
| 47 |
} |
|---|
| 48 |
|
|---|
| 49 |
Options::Filter::Filter() { |
|---|
| 50 |
// defaults for filter |
|---|
| 51 |
childrendir = Equal; |
|---|
| 52 |
children = false; |
|---|
| 53 |
prioritydir = Equal; |
|---|
| 54 |
priority = Todo::None; |
|---|
| 55 |
donedir = Negative; |
|---|
| 56 |
done = true; |
|---|
| 57 |
show = Equal; |
|---|
| 58 |
} |
|---|
| 59 |
|
|---|
| 60 |
void parseSort(string const &arg) { |
|---|
| 61 |
vector<string> keys = str::split(",", arg); |
|---|
| 62 |
struct { |
|---|
| 63 |
const char *str; |
|---|
| 64 |
int key; |
|---|
| 65 |
} table[] = { |
|---|
| 66 |
{ "created", Options::Sort::Created }, |
|---|
| 67 |
{ "completed", Options::Sort::Completed }, |
|---|
| 68 |
{ "text", Options::Sort::Text }, |
|---|
| 69 |
{ "priority", Options::Sort::Priority }, |
|---|
| 70 |
{ "duration", Options::Sort::Duration }, |
|---|
| 71 |
{ "done", Options::Sort::Done }, |
|---|
| 72 |
{ "none", Options::Sort::None }, |
|---|
| 73 |
{ 0, 0 } |
|---|
| 74 |
}; |
|---|
| 75 |
options.sort.clear(); |
|---|
| 76 |
|
|---|
| 77 |
for (vector<string>::iterator i = keys.begin(); i != keys.end(); ++i) { |
|---|
| 78 |
string p = *i; |
|---|
| 79 |
Options::Sort sort; |
|---|
| 80 |
|
|---|
| 81 |
if (p[0] == '-') { |
|---|
| 82 |
sort.dir = Options::Negative; |
|---|
| 83 |
p = p.substr(1); |
|---|
| 84 |
} else { |
|---|
| 85 |
sort.dir = Options::Equal; |
|---|
| 86 |
if (p[0] == '+') p = p.substr(1); |
|---|
| 87 |
} |
|---|
| 88 |
int j; |
|---|
| 89 |
for (j = 0; table[j].str != 0; ++j) |
|---|
| 90 |
if (p == table[j].str) { |
|---|
| 91 |
sort.key = (Options::Sort::Key)table[j].key; |
|---|
| 92 |
break; |
|---|
| 93 |
} |
|---|
| 94 |
if (table[j].str == 0) |
|---|
| 95 |
throw runtime_error("unknown sort key '" + p + "'"); |
|---|
| 96 |
options.sort.push_back(sort); |
|---|
| 97 |
} |
|---|
| 98 |
} |
|---|
| 99 |
|
|---|
| 100 |
void parseFilter(TodoDB &todo, string const &arg) { |
|---|
| 101 |
vector<string> out; |
|---|
| 102 |
|
|---|
| 103 |
out = split(",", arg); |
|---|
| 104 |
for (vector<string>::iterator i = out.begin(); i != out.end(); i++) { |
|---|
| 105 |
Options::Dir dir = Options::Equal; |
|---|
| 106 |
string str = *i; |
|---|
| 107 |
|
|---|
| 108 |
// Search |
|---|
| 109 |
if (str[0] == '/') { |
|---|
| 110 |
options.filter.search = str.c_str() + 1; |
|---|
| 111 |
} else { |
|---|
| 112 |
if (str[0] == '-' || str[0] == '+' || str[0] == '=') { |
|---|
| 113 |
if (str[0] == '-') |
|---|
| 114 |
dir = Options::Negative; |
|---|
| 115 |
else |
|---|
| 116 |
if (str[0] == '+') |
|---|
| 117 |
dir = Options::Positive; |
|---|
| 118 |
else |
|---|
| 119 |
dir = Options::Equal; |
|---|
| 120 |
// singular '-' or '+' sets default display mode |
|---|
| 121 |
if (str.size() == 1) { |
|---|
| 122 |
options.filter.show = dir; |
|---|
| 123 |
continue; |
|---|
| 124 |
} |
|---|
| 125 |
str = str.substr(1); |
|---|
| 126 |
} |
|---|
| 127 |
// must be children? |
|---|
| 128 |
if (str == "children") { |
|---|
| 129 |
options.filter.children = true; |
|---|
| 130 |
options.filter.childrendir = dir; |
|---|
| 131 |
} else |
|---|
| 132 |
// ...or done? |
|---|
| 133 |
if (str == "done") { |
|---|
| 134 |
options.filter.done = true; |
|---|
| 135 |
options.filter.donedir = dir; |
|---|
| 136 |
} else |
|---|
| 137 |
// catch-all, show everything |
|---|
| 138 |
if (str == "all") { |
|---|
| 139 |
options.filter.done = true; |
|---|
| 140 |
options.filter.donedir = Options::Positive; |
|---|
| 141 |
options.filter.children = true; |
|---|
| 142 |
options.filter.childrendir = Options::Positive; |
|---|
| 143 |
} else |
|---|
| 144 |
if (isdigit(str[0])) { |
|---|
| 145 |
vector<string> indices = todo.getIndexList(str); |
|---|
| 146 |
|
|---|
| 147 |
for (vector<string>::iterator i = indices.begin(); i != indices.end(); ++i) { |
|---|
| 148 |
options.filter.item[*i] = dir; |
|---|
| 149 |
if (dir != Options::Negative) |
|---|
| 150 |
options.filter.show = Options::Negative; |
|---|
| 151 |
} |
|---|
| 152 |
} else |
|---|
| 153 |
// is it a priority? |
|---|
| 154 |
try { |
|---|
| 155 |
Todo::Priority n = desymbolisePriority(symbolisePriority(str)); |
|---|
| 156 |
|
|---|
| 157 |
options.filter.priority = n; |
|---|
| 158 |
options.filter.prioritydir = dir; |
|---|
| 159 |
} catch (logic_error&) { |
|---|
| 160 |
throw runtime_error("unexpected symbol '" + str + "' in filter expression"); |
|---|
| 161 |
} |
|---|
| 162 |
} |
|---|
| 163 |
} |
|---|
| 164 |
} |
|---|
| 165 |
|
|---|
| 166 |
static void mergeVectors(vector<string> &out, vector<string> const &in) { |
|---|
| 167 |
for (vector<string>::const_iterator i = in.begin(); i != in.end(); ++i) |
|---|
| 168 |
out.push_back(*i); |
|---|
| 169 |
} |
|---|
| 170 |
|
|---|
| 171 |
/** |
|---|
| 172 |
Parse command line arguments into an associative array of key/value |
|---|
| 173 |
pairs. |
|---|
| 174 |
|
|---|
| 175 |
@param argc argc from main() |
|---|
| 176 |
@param argv argv from main() |
|---|
| 177 |
@return key/value pairs |
|---|
| 178 |
*/ |
|---|
| 179 |
void parseArgs(TodoDB &todo, int argc, char const **argv) { |
|---|
| 180 |
CommandArgs args; |
|---|
| 181 |
string myname = argv[0]; |
|---|
| 182 |
|
|---|
| 183 |
// detect default mode from command name |
|---|
| 184 |
if (myname.rfind("tda") == myname.size() - 3) |
|---|
| 185 |
options.mode = TodoDB::Add; |
|---|
| 186 |
|
|---|
| 187 |
if (myname.rfind("tde") == myname.size() - 3) |
|---|
| 188 |
options.mode = TodoDB::Edit; |
|---|
| 189 |
|
|---|
| 190 |
if (myname.rfind("tdr") == myname.size() - 3) |
|---|
| 191 |
options.mode = TodoDB::Remove; |
|---|
| 192 |
|
|---|
| 193 |
if (myname.rfind("tdd") == myname.size() - 3) |
|---|
| 194 |
options.mode = TodoDB::Done; |
|---|
| 195 |
|
|---|
| 196 |
if (myname.rfind("tdl") == myname.size() - 3) |
|---|
| 197 |
options.mode = TodoDB::Link; |
|---|
| 198 |
|
|---|
| 199 |
enum { Help = -100, Remove, Version, Title, Colour, Mono, ForceColour, |
|---|
| 200 |
Database, GlobalDatabase, DateFormat, DisplayFormat, |
|---|
| 201 |
VerboseDisplayFormat, VerboseGeneratedFormat, |
|---|
| 202 |
GeneratedFormat, Sort, Paranoid, DatabaseLoaders, Backup, |
|---|
| 203 |
Timeout, Format, UseFormat, DumpConfig, Exec, Echo, Stats, Purge }; |
|---|
| 204 |
|
|---|
| 205 |
args.addArgument('a', "add", CommandArgs::Optional); |
|---|
| 206 |
args.setHelp('a', "Add a note (will prompt for a note if one is not supplied)."); |
|---|
| 207 |
args.addArgument('l', "link", CommandArgs::Required); |
|---|
| 208 |
args.setHelp('l', "Links another todo file to this one."); |
|---|
| 209 |
args.addArgument('g', "graft", CommandArgs::Required); |
|---|
| 210 |
args.setHelp('g', "In conjunction with --add or --link, graft the new item to the specified item."); |
|---|
| 211 |
args.addArgument('R', "reparent", CommandArgs::Required); |
|---|
| 212 |
args.setHelp('R', "Change the parent of the first item index to the second item index (seperated by a comma). If no second index is given the item is reparented to the root of the tree. eg. todo -R 1,2"); |
|---|
| 213 |
args.addArgument('p', "priority", CommandArgs::Required); |
|---|
| 214 |
args.setHelp('p', "In conjunction with --add, set the default priority (default|veryhigh|high|medium|low|verylow)."); |
|---|
| 215 |
args.addArgument('e', "edit", CommandArgs::Required); |
|---|
| 216 |
args.setHelp('e', "Edit the note that is indexed by the given number."); |
|---|
| 217 |
args.addArgument(Remove, "remove", CommandArgs::Required); |
|---|
| 218 |
args.setHelp(Remove, "Remove the note that is indexed by the given number."); |
|---|
| 219 |
args.addArgument('d', "done", CommandArgs::Required); |
|---|
| 220 |
args.setHelp('d', "Mark the specified notes (and all children) as done."); |
|---|
| 221 |
args.addArgument('c', "comment"); |
|---|
| 222 |
args.setHelp('c', "Also manipulate finishing comment for item when viewing or marking as done."); |
|---|
| 223 |
args.addArgument('D', "not-done", CommandArgs::Required); |
|---|
| 224 |
args.setHelp('D', "Mark the specified notes (and all children) as not done."); |
|---|
| 225 |
args.addArgument(GlobalDatabase, "global-database", CommandArgs::Required); |
|---|
| 226 |
args.setHelp(GlobalDatabase, "Specify the database to use if the -G (--global) parameter is used."); |
|---|
| 227 |
args.addArgument('G', "global"); |
|---|
| 228 |
args.setHelp('G', "Use the database specified by the --global-database option. Defaults to ~/.todo_global."); |
|---|
| 229 |
args.addArgument(Database, "database", CommandArgs::Required); |
|---|
| 230 |
args.setHelp(Database, "Change the database from the default (.todo) to the filename specified."); |
|---|
| 231 |
args.addArgument('T', "TODO"); |
|---|
| 232 |
args.setHelp('T', "Generate a typical TODO output text file from a Todo DB."); |
|---|
| 233 |
args.addArgument('A', "all"); |
|---|
| 234 |
args.setHelp('A', "Shortcut for the filter '+done,+children' to show all notes."); |
|---|
| 235 |
args.addArgument('f', "filter", CommandArgs::Required); |
|---|
| 236 |
args.setHelp('f', "Display only those notes that pass the filter. A filter is composed of the minimum or maximum priority level, the keywords 'done', 'all' or 'children'. Alternatively, a regular expression search filter can be specified with '/<expression>'. eg. '-low,=done,-children' would show any notes with a priority less than or equal to 'low' that are marked as done and would not show child notes."); |
|---|
| 237 |
args.addArgument('v', "verbose"); |
|---|
| 238 |
args.setHelp('v', "Display verbosely."); |
|---|
| 239 |
args.addArgument(Colour, "colour", CommandArgs::Required); |
|---|
| 240 |
args.setHelp(Colour, "Override default colours of todo items. Multiple colours can be specified, seperated by commas. eg. high=red,medium=white. Items are bolded by prefixing them with a '+'."); |
|---|
| 241 |
args.addArgument(Mono, "mono"); |
|---|
| 242 |
args.setHelp(Mono, "Disable all use of colour."); |
|---|
| 243 |
args.addArgument(ForceColour, "force-colour"); |
|---|
| 244 |
args.setHelp(ForceColour, "Force use of colour."); |
|---|
| 245 |
args.addArgument(Help, "help"); |
|---|
| 246 |
args.setHelp(Help, "Display this help."); |
|---|
| 247 |
args.addArgument(Version, "version"); |
|---|
| 248 |
args.setHelp(Version, "Display version of todo."); |
|---|
| 249 |
args.addArgument(Title, "title", CommandArgs::Optional); |
|---|
| 250 |
args.setHelp(Title, "Set the title of this directory's todo notes."); |
|---|
| 251 |
args.addArgument(DateFormat, "date-format", CommandArgs::Required); |
|---|
| 252 |
args.setHelp(DateFormat, "Format the display of time values. The format is that used by strftime(3)."); |
|---|
| 253 |
args.addArgument(Format, "format", CommandArgs::Required); |
|---|
| 254 |
args.setHelp(Format, "Specify a display format to use. ARG is in the form <key>=<format-string>."); |
|---|
| 255 |
args.addArgument(UseFormat, "use-format", CommandArgs::Required); |
|---|
| 256 |
args.setHelp(UseFormat, "Map one format string to another (eg. --use-format display=my-own-format)."); |
|---|
| 257 |
args.addArgument(DumpConfig, "dump-config"); |
|---|
| 258 |
// Individual formatting strings are deprecated |
|---|
| 259 |
args.addArgument(DisplayFormat, "display-format", CommandArgs::Required); |
|---|
| 260 |
//args.setHelp(DisplayFormat, "Specify the format of items when displaying them to the console."); |
|---|
| 261 |
args.addArgument(VerboseDisplayFormat, "verbose-display-format", CommandArgs::Required); |
|---|
| 262 |
//args.setHelp(VerboseDisplayFormat, "As with --display-format but used when --verbose (-v) is specified."); |
|---|
| 263 |
args.addArgument(GeneratedFormat, "generated-format", CommandArgs::Required); |
|---|
| 264 |
//args.setHelp(GeneratedFormat, "Specify the format of items when generating a TODO file from the database."); |
|---|
| 265 |
args.addArgument(VerboseGeneratedFormat, "verbose-generated-format", CommandArgs::Required); |
|---|
| 266 |
//args.setHelp(VerboseGeneratedFormat, "As with --generated-format but used when --verbose (-v) is specified."); |
|---|
| 267 |
args.addArgument(Sort, "sort", CommandArgs::Required); |
|---|
| 268 |
args.setHelp(Sort, "Sort the database with the specified expression."); |
|---|
| 269 |
args.addArgument(Paranoid, "paranoid"); |
|---|
| 270 |
args.setHelp(Paranoid, "Be paranoid about some settings, including permissions."); |
|---|
| 271 |
args.addArgument(DatabaseLoaders, "database-loaders", CommandArgs::Required); |
|---|
| 272 |
args.setHelp(DatabaseLoaders, "Specify order of database format loaders to use when loading and saving (defaults to 'xml')."); |
|---|
| 273 |
args.addArgument(Backup, "backup", CommandArgs::Optional); |
|---|
| 274 |
args.setHelp(Backup, "Enable backups of the database. The optional argument is the number of backups to keep (defaults to 1)."); |
|---|
| 275 |
args.addArgument('s', "summary"); |
|---|
| 276 |
args.setHelp('s', "Toggle summary mode."); |
|---|
| 277 |
args.addArgument(Timeout, "timeout", CommandArgs::Optional); |
|---|
| 278 |
args.setHelp(Timeout, "Set the number of seconds between database displays and/or conform to this setting (see man page for more information)."); |
|---|
| 279 |
args.addArgument(Purge, "purge", CommandArgs::Optional); |
|---|
| 280 |
args.setHelp(Purge, "Purge items marked as done. Optionally only purge completed items older than ARG days."); |
|---|
| 281 |
args.addArgument(Exec, "exec", CommandArgs::Required); |
|---|
| 282 |
args.addArgument(Echo, "echo", CommandArgs::Required); |
|---|
| 283 |
args.addArgument(Stats, "stats"); |
|---|
| 284 |
|
|---|
| 285 |
for (CommandArgs::iterator i = args.begin(argc, argv); !(i == args.end()); i++) |
|---|
| 286 |
switch (i.option()) { |
|---|
| 287 |
case Help : |
|---|
| 288 |
cout << "usage: " << myname << " [<arguments>]" << endl |
|---|
| 289 |
<< "Where <arguments> can be any of the following:" << endl; |
|---|
| 290 |
args.displayHelp(cout, options.columns); |
|---|
| 291 |
cout << endl |
|---|
| 292 |
<< "In addition, there are five convenience symlinks. These are 'tda', 'tdr'," << endl |
|---|
| 293 |
<< "'tdd', 'tde', and 'tdl'. For 'tde', 'tdd' and 'tdr' supply an index to edit," << endl |
|---|
| 294 |
<< "mark done and remove respectively. For 'tda' supply the text of the todo item" << endl |
|---|
| 295 |
<< "item and optionally the priority. For 'tdl' supply the path to another todo" << endl |
|---|
| 296 |
<< "file to link in to the current todo file." << endl |
|---|
| 297 |
<< "eg. tde 1" << endl; |
|---|
| 298 |
exit(0); |
|---|
| 299 |
break; |
|---|
| 300 |
case Version : |
|---|
| 301 |
cout << VERSION << endl; |
|---|
| 302 |
exit(0); |
|---|
| 303 |
break; |
|---|
| 304 |
case Title : |
|---|
| 305 |
if (i.parameter()) options.text = i.parameter(); |
|---|
| 306 |
options.mode = TodoDB::Title; |
|---|
| 307 |
break; |
|---|
| 308 |
case DateFormat : |
|---|
| 309 |
options.format["date"] = i.parameter(); |
|---|
| 310 |
break; |
|---|
| 311 |
case Mono : |
|---|
| 312 |
options.mono = true; |
|---|
| 313 |
break; |
|---|
| 314 |
case Database : |
|---|
| 315 |
options.database = i.parameter(); |
|---|
| 316 |
break; |
|---|
| 317 |
case Sort : |
|---|
| 318 |
parseSort(i.parameter()); |
|---|
| 319 |
break; |
|---|
| 320 |
case GlobalDatabase : |
|---|
| 321 |
options.globaldatabase = i.parameter(); |
|---|
| 322 |
break; |
|---|
| 323 |
case Backup : |
|---|
| 324 |
if (i.parameter()) { |
|---|
| 325 |
options.backups = destringify<int>(i.parameter()); |
|---|
| 326 |
if (options.backups <= 0) |
|---|
| 327 |
throw runtime_error("can't specify backup revisions <= 0"); |
|---|
| 328 |
} else |
|---|
| 329 |
options.backups = 1; |
|---|
| 330 |
break; |
|---|
| 331 |
case Timeout : |
|---|
| 332 |
if (i.parameter()) { |
|---|
| 333 |
options.timeoutseconds = destringify<int>(i.parameter()); |
|---|
| 334 |
} else { |
|---|
| 335 |
if (options.timeoutseconds == 0) options.timeoutseconds = 10; |
|---|
| 336 |
options.timeout = true; |
|---|
| 337 |
} |
|---|
| 338 |
break; |
|---|
| 339 |
case Purge : |
|---|
| 340 |
if (i.parameter()) |
|---|
| 341 |
options.purgeage = destringify<int>(i.parameter()); |
|---|
| 342 |
options.mode = TodoDB::Purge; |
|---|
| 343 |
break; |
|---|
| 344 |
case Exec : |
|---|
| 345 |
if (options.verbose > 1) |
|---|
| 346 |
cout << "todo: executing '" << i.parameter() << "'" << endl; |
|---|
| 347 |
system(i.parameter()); |
|---|
| 348 |
break; |
|---|
| 349 |
case Echo : |
|---|
| 350 |
cout << i.parameter() << endl; |
|---|
| 351 |
break; |
|---|
| 352 |
case 's' : |
|---|
| 353 |
options.summary = !options.summary; |
|---|
| 354 |
break; |
|---|
| 355 |
case 'G' : |
|---|
| 356 |
options.global = true; |
|---|
| 357 |
break; |
|---|
| 358 |
case Paranoid : |
|---|
| 359 |
options.paranoid = true; |
|---|
| 360 |
break; |
|---|
| 361 |
case DatabaseLoaders : |
|---|
| 362 |
options.loaders = str::split(",", i.parameter()); |
|---|
| 363 |
break; |
|---|
| 364 |
case Colour : { |
|---|
| 365 |
vector<string> colours = str::split(",", i.parameter()); |
|---|
| 366 |
|
|---|
| 367 |
for (vector<string>::iterator j = colours.begin(); j != colours.end(); ++j) { |
|---|
| 368 |
vector<string> component = str::split("=", *j); |
|---|
| 369 |
if (component.size() != 2) |
|---|
| 370 |
throw runtime_error(string("colour values should be in the format <item>=<colour>, not '") + i.parameter() + "'"); |
|---|
| 371 |
todo.setColour(component[0], component[1]); |
|---|
| 372 |
} |
|---|
| 373 |
} |
|---|
| 374 |
break; |
|---|
| 375 |
case ForceColour : |
|---|
| 376 |
term::forceColour(true); |
|---|
| 377 |
break; |
|---|
| 378 |
case Format : { |
|---|
| 379 |
vector<string> comp; |
|---|
| 380 |
|
|---|
| 381 |
if (!strchr(i.parameter(), '=')) |
|---|
| 382 |
throw runtime_error("invalid usage of --format"); |
|---|
| 383 |
string tmp = i.parameter(); |
|---|
| 384 |
comp.push_back(tmp.substr(0, strchr(i.parameter(), '=') - i.parameter())); |
|---|
| 385 |
comp.push_back(tmp.substr(strchr(i.parameter(), '=') - i.parameter() + 1)); |
|---|
| 386 |
options.format[comp[0]] = comp[1]; |
|---|
| 387 |
} |
|---|
| 388 |
break; |
|---|
| 389 |
case UseFormat : { |
|---|
| 390 |
vector<string> mapping = str::split("=", i.parameter()); |
|---|
| 391 |
if (mapping.size() != 2) |
|---|
| 392 |
throw runtime_error("invalid usage of --use-format"); |
|---|
| 393 |
if (options.format.find(mapping[1]) == options.format.end() || |
|---|
| 394 |
options.format.find(mapping[1]) == options.format.end()) |
|---|
| 395 |
throw runtime_error("no such format '" + mapping[1] + "'"); |
|---|
| 396 |
options.format[mapping[0]] = options< |
|---|