@beauraines/rtm-cli 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/FUNDING.yml +12 -0
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/build.js +86 -0
- package/config.json +40 -0
- package/package.json +58 -0
- package/screens/ls.png +0 -0
- package/screens/lsd.png +0 -0
- package/screens/lsp.png +0 -0
- package/screens/planner.png +0 -0
- package/src/cli.js +434 -0
- package/src/cmd/add.js +100 -0
- package/src/cmd/addList.js +92 -0
- package/src/cmd/addTags.js +85 -0
- package/src/cmd/archiveList.js +78 -0
- package/src/cmd/comp.js +82 -0
- package/src/cmd/decPri.js +82 -0
- package/src/cmd/due.js +82 -0
- package/src/cmd/edit.js +82 -0
- package/src/cmd/incPri.js +82 -0
- package/src/cmd/lists.js +60 -0
- package/src/cmd/login.js +27 -0
- package/src/cmd/logout.js +31 -0
- package/src/cmd/ls.js +181 -0
- package/src/cmd/lsd.js +193 -0
- package/src/cmd/lsp.js +171 -0
- package/src/cmd/move.js +83 -0
- package/src/cmd/notes.js +150 -0
- package/src/cmd/planner.js +510 -0
- package/src/cmd/postpone.js +82 -0
- package/src/cmd/pri.js +82 -0
- package/src/cmd/remove.js +82 -0
- package/src/cmd/removeList.js +79 -0
- package/src/cmd/removeTags.js +85 -0
- package/src/cmd/renameList.js +80 -0
- package/src/cmd/reset.js +35 -0
- package/src/cmd/setUrl.js +99 -0
- package/src/cmd/tags.js +101 -0
- package/src/cmd/uncomp.js +82 -0
- package/src/cmd/url.js +92 -0
- package/src/cmd/whoami.js +36 -0
- package/src/interactive.js +65 -0
- package/src/utils/config.js +236 -0
- package/src/utils/filter.js +43 -0
- package/src/utils/finish.js +21 -0
- package/src/utils/index.js +10 -0
- package/src/utils/log.js +163 -0
- package/src/utils/login.js +69 -0
- package/src/utils/printIndicator.js +43 -0
- package/src/utils/prompt.js +126 -0
- package/src/utils/sort.js +283 -0
package/src/cli.js
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const readline = require('readline');
|
|
8
|
+
const program = require('commander');
|
|
9
|
+
const info = require('../package.json');
|
|
10
|
+
const log = require('./utils/log.js');
|
|
11
|
+
const config = require('./utils/config.js');
|
|
12
|
+
const finish = require('./utils/finish.js');
|
|
13
|
+
const interactive = require('./interactive.js');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Directory containing command files
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
const CMD_DIR = path.normalize(__dirname + '/cmd/');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// Setup the Program options and commands
|
|
25
|
+
setup();
|
|
26
|
+
|
|
27
|
+
// Parse the CLI arguments and start the program
|
|
28
|
+
start();
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Set up the program arguments, commands and options
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
function setup() {
|
|
39
|
+
|
|
40
|
+
// Set Process Name
|
|
41
|
+
process.title = 'rtm';
|
|
42
|
+
|
|
43
|
+
// Add Program Information
|
|
44
|
+
program
|
|
45
|
+
.version(info.version)
|
|
46
|
+
.usage("[options] <command> [command arguments]");
|
|
47
|
+
|
|
48
|
+
// Add Options
|
|
49
|
+
program
|
|
50
|
+
.option('-p, --plain', 'do not use styled/colored text (overrides --color)')
|
|
51
|
+
.option('-c, --color', 'force the use of styled/colored text')
|
|
52
|
+
.option('-s, --status', 'toggle the display of the status spinner')
|
|
53
|
+
.option('-x, --completed [value]', 'set display of completed tasks (true/false/number of days)')
|
|
54
|
+
.option('-d, --hideDue [value]', 'hide tasks due more than n days from today (false/number of days)')
|
|
55
|
+
.option('-f, --config [file]', 'specify configuration file', function(file) {
|
|
56
|
+
config.reset(file);
|
|
57
|
+
parsePlugins();
|
|
58
|
+
parseAliases();
|
|
59
|
+
})
|
|
60
|
+
.option('-v, --verbose', 'print stack traces on errors');
|
|
61
|
+
|
|
62
|
+
// Add additional Help information
|
|
63
|
+
program.on('--help', function() {
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log(' Documentation:');
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log(' Additional docs can be found in the GitHub repo:');
|
|
69
|
+
console.log(' https://github.com/dwaring87/rtm-cli');
|
|
70
|
+
console.log(' This project uses the RTM API Wrapper for NodeJS:');
|
|
71
|
+
console.log(' https://github.com/dwaring87/rtm-api');
|
|
72
|
+
if ( config.get()._user ) {
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log('');
|
|
75
|
+
console.log(' Logged In As: ' + config.get()._user.username);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Error on Unknown Command
|
|
80
|
+
program.on('command:*', function () {
|
|
81
|
+
console.error('Invalid command: %s\nSee --help for a list of available commands.', program.args.join(' '));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Add Program Commands
|
|
86
|
+
parseCommands();
|
|
87
|
+
|
|
88
|
+
// Add Any Plugins
|
|
89
|
+
parsePlugins();
|
|
90
|
+
|
|
91
|
+
// Parse Aliases
|
|
92
|
+
parseAliases();
|
|
93
|
+
|
|
94
|
+
// Set program to global namespace
|
|
95
|
+
global._program = program;
|
|
96
|
+
|
|
97
|
+
// Set readline interface
|
|
98
|
+
global._rl = readline.createInterface({
|
|
99
|
+
input: process.stdin,
|
|
100
|
+
output: process.stdout,
|
|
101
|
+
completer: function completer(line) {
|
|
102
|
+
let completions = [];
|
|
103
|
+
if ( global._mainPrompt ) {
|
|
104
|
+
completions.push('help');
|
|
105
|
+
for ( let i = 0; i < program.commands.length; i++ ) {
|
|
106
|
+
completions.push(program.commands[i].name());
|
|
107
|
+
}
|
|
108
|
+
completions.push('quit');
|
|
109
|
+
}
|
|
110
|
+
let hits = completions.filter(function(c) { return c.indexOf(line) === 0 });
|
|
111
|
+
return [hits.length ? hits : completions, line]
|
|
112
|
+
}
|
|
113
|
+
}).on('SIGINT', function() {
|
|
114
|
+
process.exit(0);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Catch Thrown Errors
|
|
118
|
+
process.on('uncaughtException', function(err) {
|
|
119
|
+
log.error("ERROR: " + err);
|
|
120
|
+
if ( program.verbose ) {
|
|
121
|
+
console.log(err);
|
|
122
|
+
}
|
|
123
|
+
finish();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
// ===== COMMAND PARSING ===== //
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Parse the commands in the command directory
|
|
135
|
+
* @private
|
|
136
|
+
*/
|
|
137
|
+
function parseCommands() {
|
|
138
|
+
let files = fs.readdirSync(CMD_DIR);
|
|
139
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
140
|
+
let file = path.normalize(CMD_DIR + '/' + files[i]);
|
|
141
|
+
let command = require(file);
|
|
142
|
+
parseCmd(command);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Parse the command file
|
|
149
|
+
* @param {object} command The command object to parse
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
152
|
+
function parseCmd(command) {
|
|
153
|
+
|
|
154
|
+
// Check for existing command name
|
|
155
|
+
let existing = program.commands;
|
|
156
|
+
for ( let i = 0; i < existing.length; i++ ) {
|
|
157
|
+
if ( existing[i].name() === command.command.split(' ')[0] ) {
|
|
158
|
+
log.error("ERROR: Command name (" + command.command.split(' ')[0] + ") already exists");
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Build Command
|
|
164
|
+
let cmd = program.command(command.command);
|
|
165
|
+
cmd.description(command.description);
|
|
166
|
+
cmd.alias(command.alias);
|
|
167
|
+
|
|
168
|
+
// Add Command Options
|
|
169
|
+
if ( command.options ) {
|
|
170
|
+
for ( let i = 0; i < command.options.length; i++ ) {
|
|
171
|
+
let option = command.options[i];
|
|
172
|
+
cmd.option(option.option, option.description);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Add Command Action
|
|
177
|
+
cmd.action(function() {
|
|
178
|
+
|
|
179
|
+
// Process command arguments
|
|
180
|
+
let args = [];
|
|
181
|
+
let env = undefined;
|
|
182
|
+
for ( let i = 0; i < arguments.length; i++ ) {
|
|
183
|
+
let arg = arguments[i];
|
|
184
|
+
if ( typeof arg === 'object' && !Array.isArray(arg) ) {
|
|
185
|
+
env = arg;
|
|
186
|
+
}
|
|
187
|
+
else if ( Array.isArray(arg) && arg.length > 0 ) {
|
|
188
|
+
args.push(arg);
|
|
189
|
+
}
|
|
190
|
+
else if ( !Array.isArray(arg) && arg !== undefined ) {
|
|
191
|
+
args.push(arg);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Skip Login Check
|
|
196
|
+
if ( command.disableLogin ) {
|
|
197
|
+
command.action(args, env);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Check Login Before Running Command
|
|
201
|
+
else {
|
|
202
|
+
config.user(function() {
|
|
203
|
+
command.action(args, env);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
// ===== PLUGIN PARSING ===== //
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Parse the plugins listed in the configuration
|
|
217
|
+
*/
|
|
218
|
+
function parsePlugins() {
|
|
219
|
+
|
|
220
|
+
// Get plugin locations from the configuration
|
|
221
|
+
let locations = config.get().plugins;
|
|
222
|
+
|
|
223
|
+
// Parse each location
|
|
224
|
+
for ( let i = 0; i < locations.length; i++ ) {
|
|
225
|
+
parsePluginLocation(locations[i]);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Parse the specified plugin location
|
|
233
|
+
* @param {string} location Plugin location (file, directory or module name)
|
|
234
|
+
* @private
|
|
235
|
+
*/
|
|
236
|
+
function parsePluginLocation(location) {
|
|
237
|
+
|
|
238
|
+
// Replace {{HOME}} with home directory location
|
|
239
|
+
location = location.replace("{{HOME}}", os.homedir());
|
|
240
|
+
|
|
241
|
+
// Try to load as a module (either directory or file)
|
|
242
|
+
try {
|
|
243
|
+
require.resolve(location);
|
|
244
|
+
parsePluginModule(location);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Not a module...
|
|
248
|
+
catch (err) {
|
|
249
|
+
|
|
250
|
+
// Check to make sure file/directory exists
|
|
251
|
+
if ( fs.existsSync(location) ) {
|
|
252
|
+
|
|
253
|
+
// Check if a directory
|
|
254
|
+
if ( fs.lstatSync(location).isDirectory() ) {
|
|
255
|
+
parsePluginDirectory(location);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Parse the Plugin as a Module
|
|
266
|
+
* @param {string} location Module location (for `require`)
|
|
267
|
+
* @private
|
|
268
|
+
*/
|
|
269
|
+
function parsePluginModule(location) {
|
|
270
|
+
|
|
271
|
+
// Load the module
|
|
272
|
+
let module = require(location);
|
|
273
|
+
|
|
274
|
+
// Check the root module for a command
|
|
275
|
+
_check(module);
|
|
276
|
+
|
|
277
|
+
// Check children objects for a command
|
|
278
|
+
for ( let key in module ) {
|
|
279
|
+
if ( module.hasOwnProperty(key) ) {
|
|
280
|
+
_check(module[key]);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Check the object for the required command properties and parse the
|
|
286
|
+
* object as a command if they are all found
|
|
287
|
+
* @param obj
|
|
288
|
+
* @private
|
|
289
|
+
*/
|
|
290
|
+
function _check(obj) {
|
|
291
|
+
if ( obj.hasOwnProperty('command') && obj.hasOwnProperty('description') && obj.hasOwnProperty('action') ) {
|
|
292
|
+
parseCmd(obj);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Process a plugin directory
|
|
300
|
+
* @param location
|
|
301
|
+
*/
|
|
302
|
+
function parsePluginDirectory(location) {
|
|
303
|
+
|
|
304
|
+
// Check if location exists
|
|
305
|
+
if ( fs.existsSync(location) ) {
|
|
306
|
+
|
|
307
|
+
// Get all files in directory
|
|
308
|
+
let files = fs.readdirSync(location);
|
|
309
|
+
|
|
310
|
+
// Parse each location
|
|
311
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
312
|
+
parsePluginLocation(path.normalize(location + '/' + files[i]));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
// ===== ALIAS PARSING ===== //
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Parse the Alias Commands from the Config Files
|
|
326
|
+
*/
|
|
327
|
+
function parseAliases() {
|
|
328
|
+
|
|
329
|
+
// Remove existing RTM Aliases
|
|
330
|
+
let keep = [];
|
|
331
|
+
let current = program.commands;
|
|
332
|
+
for ( let i = 0; i < current.length; i++ ) {
|
|
333
|
+
let cmd = current[i];
|
|
334
|
+
if ( !cmd._isRTMAlias ) {
|
|
335
|
+
keep.push(cmd);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
program.commands = keep;
|
|
339
|
+
|
|
340
|
+
// Parse aliases in configuration
|
|
341
|
+
if ( config.get().aliases ) {
|
|
342
|
+
for ( let i = 0; i < config.get().aliases.length; i++ ) {
|
|
343
|
+
let alias = config.get().aliases[i];
|
|
344
|
+
|
|
345
|
+
// Check for existing command name
|
|
346
|
+
let found = false;
|
|
347
|
+
let existing = program.commands;
|
|
348
|
+
for ( let j = 0; j < existing.length; j++ ) {
|
|
349
|
+
if ( existing[j].name() === alias.name ) {
|
|
350
|
+
found = true;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Add command to program, if not already added
|
|
355
|
+
if ( !found ) {
|
|
356
|
+
|
|
357
|
+
// Create Command with description
|
|
358
|
+
let cmd = program.command(alias.name);
|
|
359
|
+
cmd.description(alias.description);
|
|
360
|
+
|
|
361
|
+
// Set Command Action
|
|
362
|
+
cmd.action(function () {
|
|
363
|
+
|
|
364
|
+
// Set Initial Args
|
|
365
|
+
let args = [
|
|
366
|
+
process.argv[0],
|
|
367
|
+
process.argv[1],
|
|
368
|
+
alias.command
|
|
369
|
+
];
|
|
370
|
+
|
|
371
|
+
// Add Arguments
|
|
372
|
+
if ( alias.args ) {
|
|
373
|
+
let aa = alias.args.split(' ');
|
|
374
|
+
for ( let j = 0; j < aa.length; j++ ) {
|
|
375
|
+
args.push(aa[j]);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Add CLI arguments
|
|
380
|
+
if ( process.argv.length > 3 ) {
|
|
381
|
+
for ( let j = 3; j < process.argv.length; j++ ) {
|
|
382
|
+
args.push(process.argv[j]);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Parse the command
|
|
387
|
+
global._program.parse(args);
|
|
388
|
+
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Flag command as RTM Alias
|
|
392
|
+
cmd._isRTMAlias = true;
|
|
393
|
+
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
// ===== START FUNCTIONS ===== //
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Parse the CLI arguments and run the specified command
|
|
408
|
+
* or start the interactive mode
|
|
409
|
+
*/
|
|
410
|
+
function start() {
|
|
411
|
+
|
|
412
|
+
// Start interactive mode
|
|
413
|
+
if ( process.argv.length <= 2 ) {
|
|
414
|
+
startInteractive();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Parse the process arguments
|
|
418
|
+
else {
|
|
419
|
+
program.parse(process.argv);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Start the interactive mode
|
|
428
|
+
*/
|
|
429
|
+
function startInteractive() {
|
|
430
|
+
if ( config.get()._user ) {
|
|
431
|
+
log.style("Logged In As: " + config.get()._user.username, "dim", true);
|
|
432
|
+
}
|
|
433
|
+
interactive();
|
|
434
|
+
}
|
package/src/cmd/add.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const log = require('../utils/log.js');
|
|
4
|
+
const config = require('../utils/config.js');
|
|
5
|
+
const { prompt } = require('../utils/prompt.js');
|
|
6
|
+
|
|
7
|
+
const finish = require('../utils/finish.js');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* This command adds 1 or more tasks to the User's account
|
|
12
|
+
* @param args task
|
|
13
|
+
* @param env
|
|
14
|
+
*/
|
|
15
|
+
function action(args, env) {
|
|
16
|
+
|
|
17
|
+
// Prompt for new tasks
|
|
18
|
+
if ( args.length === 0 ) {
|
|
19
|
+
prompt('New Task:', _promptFinished);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Add provided task
|
|
23
|
+
else {
|
|
24
|
+
_process(args[0].join(' '));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Process the returned answers
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
function _promptFinished(answers) {
|
|
35
|
+
for ( let i = 0; i < answers.length; i++ ) {
|
|
36
|
+
let answer = answers[i];
|
|
37
|
+
_process(answer[0], i+1, answers.length);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Process the request
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
function _process(task, count=1, max=1) {
|
|
47
|
+
log.spinner.start("Adding New Task(s)...");
|
|
48
|
+
config.user(function(user) {
|
|
49
|
+
task = _parseTask(task);
|
|
50
|
+
|
|
51
|
+
// Add Task
|
|
52
|
+
user.tasks.add(task, function(err) {
|
|
53
|
+
if ( err ) {
|
|
54
|
+
log.spinner.error("Could not add new Task #" + count + " (" + err.msg + ")");
|
|
55
|
+
}
|
|
56
|
+
_processFinished(count, max);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Request Callback
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
function _processFinished(count, max) {
|
|
66
|
+
log.spinner.start("Adding Task [" + count + "/" + max + "]...");
|
|
67
|
+
if ( count === max ) {
|
|
68
|
+
log.spinner.success("Task(s) Added");
|
|
69
|
+
return finish();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Parse the Task to Add
|
|
76
|
+
*
|
|
77
|
+
* Replace p: with !
|
|
78
|
+
* Replace l: with #
|
|
79
|
+
* Replace t: with #
|
|
80
|
+
* Replace due: with ^
|
|
81
|
+
* @param task
|
|
82
|
+
* @returns {string}
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
function _parseTask(task) {
|
|
86
|
+
task = task.replace(/(\s+)p:([0-4]{1})($|[\s\r\n]+)/, " !$2$3").trim();
|
|
87
|
+
task = task.replace(/(\s+)l:([\w\d]+)/, " #$2").trim();
|
|
88
|
+
task = task.replace(/(\s+)t:([\w\d]+)/g, " #$2").trim();
|
|
89
|
+
task = task.replace(/(\s+)due:([\w\d]+)/, " ^$2").trim();
|
|
90
|
+
return task;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
command: 'add [task...]',
|
|
97
|
+
alias: 'a',
|
|
98
|
+
description: 'Add a new Task',
|
|
99
|
+
action: action
|
|
100
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const log = require('../utils/log.js');
|
|
4
|
+
const config = require('../utils/config.js');
|
|
5
|
+
const { prompt } = require('../utils/prompt.js');
|
|
6
|
+
|
|
7
|
+
const finish = require('../utils/finish.js');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* This command adds 1 or more Lists to the User's account
|
|
12
|
+
* @param args name
|
|
13
|
+
* @param env
|
|
14
|
+
*/
|
|
15
|
+
function action(args, env) {
|
|
16
|
+
let _args = [];
|
|
17
|
+
for ( let i = 0; i < args.length; i++ ) {
|
|
18
|
+
_args = _args.concat(args[i]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Prompt for new lists
|
|
22
|
+
if ( args.length === 0 ) {
|
|
23
|
+
prompt('New List:', _promptFinished);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Add provided task
|
|
27
|
+
else {
|
|
28
|
+
_process(_args.join(' '));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Process the returned answers
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
function _promptFinished(answers) {
|
|
39
|
+
for ( let i = 0; i < answers.length; i++ ) {
|
|
40
|
+
let answer = answers[i];
|
|
41
|
+
_process(answer[0], i+1, answers.length);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Process the request
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
50
|
+
function _process(list, count=1, max=1) {
|
|
51
|
+
log.spinner.start("Adding New List(s)...");
|
|
52
|
+
config.user(function(user) {
|
|
53
|
+
list = list.trim();
|
|
54
|
+
let filter = undefined;
|
|
55
|
+
|
|
56
|
+
// Parse as Smart List
|
|
57
|
+
if ( list.indexOf(':') > -1 ) {
|
|
58
|
+
let colon = list.indexOf(':');
|
|
59
|
+
let divider = list.substring(0, colon).lastIndexOf(' ');
|
|
60
|
+
filter = list.substring(divider+1);
|
|
61
|
+
list = list.substring(0, divider);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add List
|
|
65
|
+
user.lists.add(list, filter, function(err) {
|
|
66
|
+
if ( err ) {
|
|
67
|
+
log.spinner.error("Could not add new List " + list + " (" + err.msg + ")");
|
|
68
|
+
}
|
|
69
|
+
_processFinished(count, max);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Request Callback
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
function _processFinished(count, max) {
|
|
79
|
+
log.spinner.start("Adding List [" + count + "/" + max + "]...");
|
|
80
|
+
if ( count === max ) {
|
|
81
|
+
log.spinner.success("List(s) Added");
|
|
82
|
+
return finish();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
command: 'addList [name] [filter...]',
|
|
89
|
+
alias: 'al',
|
|
90
|
+
description: 'Add a new List or Smart List',
|
|
91
|
+
action: action
|
|
92
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const log = require('../utils/log.js');
|
|
4
|
+
const config = require('../utils/config.js');
|
|
5
|
+
const { prompt } = require('../utils/prompt.js');
|
|
6
|
+
|
|
7
|
+
const finish = require('../utils/finish.js');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* This command adds 1 or more tags to a Task
|
|
12
|
+
* @param args index tags...
|
|
13
|
+
* @param env
|
|
14
|
+
*/
|
|
15
|
+
function action(args, env) {
|
|
16
|
+
|
|
17
|
+
// Prompt for new tags
|
|
18
|
+
if ( args.length < 2 ) {
|
|
19
|
+
prompt('Task:', 'Tags:', _promptFinished);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Add provided tags
|
|
23
|
+
else {
|
|
24
|
+
_process(args[0], args[1]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Process the returned answers
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
function _promptFinished(answers) {
|
|
35
|
+
for ( let i = 0; i < answers.length; i++ ) {
|
|
36
|
+
let answer = answers[i];
|
|
37
|
+
_process(answer[0], answer[1], i+1, answers.length);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Process the request
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
function _process(task, tags, count=1, max=1) {
|
|
47
|
+
log.spinner.start("Adding Tags(s)...");
|
|
48
|
+
config.user(function(user) {
|
|
49
|
+
|
|
50
|
+
// Parse arguments
|
|
51
|
+
task = parseInt(task.trim());
|
|
52
|
+
if ( !Array.isArray(tags) ) {
|
|
53
|
+
tags = tags.trim().split(' ');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Add Tags
|
|
57
|
+
user.tasks.addTags(task, tags, function(err) {
|
|
58
|
+
if ( err ) {
|
|
59
|
+
log.spinner.error("Could not add tags to Task #" + task + " (" + err.msg + ")");
|
|
60
|
+
}
|
|
61
|
+
_processFinished(count, max);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Request Callback
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
function _processFinished(count, max) {
|
|
72
|
+
log.spinner.start("Adding Tags [" + count + "/" + max + "]...");
|
|
73
|
+
if ( count === max ) {
|
|
74
|
+
log.spinner.success("Tag(s) Added");
|
|
75
|
+
return finish();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
command: 'addTags [index] [tags...]',
|
|
82
|
+
alias: 'at',
|
|
83
|
+
description: 'Add one or more tags to a Task',
|
|
84
|
+
action: action
|
|
85
|
+
};
|