na 1.2.28 → 1.2.30

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,56 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- desc 'Mark an action as @done and archive'
4
- arg_name 'ACTION'
5
- command %i[archive] do |c|
6
- c.example 'na archive "An existing task"',
7
- desc: 'Find "An existing task", mark @done if needed, and move to archive'
8
-
9
- c.desc 'Prompt for additional notes. Input will be appended to any existing note.
10
- If STDIN input (piped) is detected, it will be used as a note.'
11
- c.switch %i[n note], negatable: false
12
-
13
- c.desc 'Overwrite note instead of appending'
14
- c.switch %i[o overwrite], negatable: false
15
-
16
- c.desc 'Archive all done tasks'
17
- c.switch %i[done], negatable: false
18
-
19
- c.desc 'Specify the file to search for the task'
20
- c.arg_name 'PATH'
21
- c.flag %i[file]
22
-
23
- c.desc 'Search for files X directories deep'
24
- c.arg_name 'DEPTH'
25
- c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
26
-
27
- c.desc 'Match actions containing tag. Allows value comparisons'
28
- c.arg_name 'TAG'
29
- c.flag %i[tagged], multiple: true
30
-
31
- c.desc 'Act on all matches immediately (no menu)'
32
- c.switch %i[all], negatable: false
33
-
34
- c.desc 'Interpret search pattern as regular expression'
35
- c.switch %i[e regex], negatable: false
36
-
37
- c.desc 'Match pattern exactly'
38
- c.switch %i[x exact], negatable: false
39
-
40
- c.action do |global, options, args|
41
- if options[:done]
42
- options[:tagged] = ['done']
43
- options[:all] = true
3
+ class App
4
+ extend GLI::App
5
+ desc 'Mark an action as @done and archive'
6
+ arg_name 'ACTION'
7
+ command %i[archive] do |c|
8
+ c.example 'na archive "An existing task"',
9
+ desc: 'Find "An existing task", mark @done if needed, and move to archive'
10
+
11
+ c.desc 'Prompt for additional notes. Input will be appended to any existing note.
12
+ If STDIN input (piped) is detected, it will be used as a note.'
13
+ c.switch %i[n note], negatable: false
14
+
15
+ c.desc 'Overwrite note instead of appending'
16
+ c.switch %i[o overwrite], negatable: false
17
+
18
+ c.desc 'Archive all done tasks'
19
+ c.switch %i[done], negatable: false
20
+
21
+ c.desc 'Specify the file to search for the task'
22
+ c.arg_name 'PATH'
23
+ c.flag %i[file]
24
+
25
+ c.desc 'Search for files X directories deep'
26
+ c.arg_name 'DEPTH'
27
+ c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
28
+
29
+ c.desc 'Match actions containing tag. Allows value comparisons'
30
+ c.arg_name 'TAG'
31
+ c.flag %i[tagged], multiple: true
32
+
33
+ c.desc 'Act on all matches immediately (no menu)'
34
+ c.switch %i[all], negatable: false
35
+
36
+ c.desc 'Interpret search pattern as regular expression'
37
+ c.switch %i[e regex], negatable: false
38
+
39
+ c.desc 'Match pattern exactly'
40
+ c.switch %i[x exact], negatable: false
41
+
42
+ c.action do |global, options, args|
43
+ if options[:done]
44
+ options[:tagged] = ['done']
45
+ options[:all] = true
46
+ end
47
+
48
+ options[:done] = true
49
+ options[:finish] = true
50
+ options[:project] = 'Archive'
51
+ options[:archive] = true
52
+ options[:a] = true
53
+
54
+ cmd = commands[:update]
55
+ action = cmd.send(:get_action, nil)
56
+ action.call(global, options, args)
44
57
  end
45
-
46
- options[:done] = true
47
- options[:finish] = true
48
- options[:project] = 'Archive'
49
- options[:archive] = true
50
- options[:a] = true
51
-
52
- cmd = commands[:update]
53
- action = cmd.send(:get_action, nil)
54
- action.call(global, options, args)
55
58
  end
56
59
  end
@@ -1,19 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- desc 'Display the changelog'
4
- command %i[changes changelog] do |c|
5
- c.action do |_, _, _|
6
- changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', 'CHANGELOG.md'))
7
- pagers = [
8
- 'mdless',
9
- 'mdcat',
10
- 'bat',
11
- ENV['PAGER'],
12
- 'less -FXr',
13
- ENV['GIT_PAGER'],
14
- 'more -r'
15
- ]
16
- pager = pagers.find { |cmd| TTY::Which.exist?(cmd.split.first) }
17
- system %(#{pager} "#{changelog}")
3
+ class App
4
+ extend GLI::App
5
+ desc 'Display the changelog'
6
+ command %i[changes changelog] do |c|
7
+ c.action do |_, _, _|
8
+ changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', 'CHANGELOG.md'))
9
+ pagers = [
10
+ 'mdless',
11
+ 'mdcat',
12
+ 'bat',
13
+ ENV['PAGER'],
14
+ 'less -FXr',
15
+ ENV['GIT_PAGER'],
16
+ 'more -r'
17
+ ]
18
+ pager = pagers.find { |cmd| TTY::Which.exist?(cmd.split.first) }
19
+ system %(#{pager} "#{changelog}")
20
+ end
18
21
  end
19
22
  end
@@ -1,51 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- desc 'Find and mark an action as @done'
4
- arg_name 'ACTION'
5
- command %i[complete finish] do |c|
6
- c.example 'na complete "An existing task"',
7
- desc: 'Find "An existing task" and mark @done'
8
- c.example 'na finish "An existing task"',
9
- desc: 'Alias for complete'
10
-
11
- c.desc 'Prompt for additional notes. Input will be appended to any existing note.
12
- If STDIN input (piped) is detected, it will be used as a note.'
13
- c.switch %i[n note], negatable: false
14
-
15
- c.desc 'Overwrite note instead of appending'
16
- c.switch %i[o overwrite], negatable: false
17
-
18
- c.desc 'Add a @done tag to action and move to Archive'
19
- c.switch %i[a archive], negatable: false
20
-
21
- c.desc 'Specify the file to search for the task'
22
- c.arg_name 'PATH'
23
- c.flag %i[file]
24
-
25
- c.desc 'Search for files X directories deep'
26
- c.arg_name 'DEPTH'
27
- c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
28
-
29
- c.desc 'Match actions containing tag. Allows value comparisons'
30
- c.arg_name 'TAG'
31
- c.flag %i[tagged], multiple: true
32
-
33
- c.desc 'Act on all matches immediately (no menu)'
34
- c.switch %i[all], negatable: false
35
-
36
- c.desc 'Interpret search pattern as regular expression'
37
- c.switch %i[e regex], negatable: false
38
-
39
- c.desc 'Match pattern exactly'
40
- c.switch %i[x exact], negatable: false
41
-
42
- c.action do |global, options, args|
43
- options[:finish] = true
44
- options[:f] = true
45
- options[:project] = 'Archive' if options[:archive]
46
-
47
- cmd = commands[:update]
48
- action = cmd.send(:get_action, nil)
49
- action.call(global, options, args)
3
+ class App
4
+ extend GLI::App
5
+ desc 'Find and mark an action as @done'
6
+ arg_name 'ACTION'
7
+ command %i[complete finish] do |c|
8
+ c.example 'na complete "An existing task"',
9
+ desc: 'Find "An existing task" and mark @done'
10
+ c.example 'na finish "An existing task"',
11
+ desc: 'Alias for complete'
12
+
13
+ c.desc 'Prompt for additional notes. Input will be appended to any existing note.
14
+ If STDIN input (piped) is detected, it will be used as a note.'
15
+ c.switch %i[n note], negatable: false
16
+
17
+ c.desc 'Overwrite note instead of appending'
18
+ c.switch %i[o overwrite], negatable: false
19
+
20
+ c.desc 'Add a @done tag to action and move to Archive'
21
+ c.switch %i[a archive], negatable: false
22
+
23
+ c.desc 'Specify the file to search for the task'
24
+ c.arg_name 'PATH'
25
+ c.flag %i[file]
26
+
27
+ c.desc 'Search for files X directories deep'
28
+ c.arg_name 'DEPTH'
29
+ c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
30
+
31
+ c.desc 'Match actions containing tag. Allows value comparisons'
32
+ c.arg_name 'TAG'
33
+ c.flag %i[tagged], multiple: true
34
+
35
+ c.desc 'Act on all matches immediately (no menu)'
36
+ c.switch %i[all], negatable: false
37
+
38
+ c.desc 'Interpret search pattern as regular expression'
39
+ c.switch %i[e regex], negatable: false
40
+
41
+ c.desc 'Match pattern exactly'
42
+ c.switch %i[x exact], negatable: false
43
+
44
+ c.action do |global, options, args|
45
+ options[:finish] = true
46
+ options[:f] = true
47
+ options[:project] = 'Archive' if options[:archive]
48
+
49
+ cmd = commands[:update]
50
+ action = cmd.send(:get_action, nil)
51
+ action.call(global, options, args)
52
+ end
50
53
  end
51
54
  end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ class App
4
+ extend GLI::App
5
+ desc 'Display completed actions'
6
+ long_desc 'Search tokens are separated by spaces. Actions matching all tokens in the pattern will be shown
7
+ (partial matches allowed). Add a + before a token to make it required, e.g. `na completed +feature +maybe`,
8
+ add a - or ! to ignore matches containing that token.'
9
+ arg_name 'PATTERN', optional: true, multiple: true
10
+ command %i[completed finished] do |c|
11
+ c.example 'na completed', desc: 'display completed actions'
12
+ c.example 'na completed --before "2 days ago"',
13
+ desc: 'display actions completed more than two days ago'
14
+ c.example 'na completed --on yesterday',
15
+ desc: 'display actions completed yesterday'
16
+ c.example 'na completed --after "1 week ago"',
17
+ desc: 'display actions completed in the last week'
18
+ c.example 'na completed feature',
19
+ desc: 'display completed actions matcning "feature"'
20
+
21
+ c.desc 'Display actions completed before (natural language) date string'
22
+ c.arg_name 'DATE_STRING'
23
+ c.flag %i[b before]
24
+
25
+ c.desc 'Display actions completed on (natural language) date string'
26
+ c.arg_name 'DATE_STRING'
27
+ c.flag %i[on]
28
+
29
+ c.desc 'Display actions completed after (natural language) date string'
30
+ c.arg_name 'DATE_STRING'
31
+ c.flag %i[a after]
32
+
33
+ c.desc 'Combine before, on, and/or after with OR, displaying actions matching ANY of the ranges'
34
+ c.switch %i[o or], negatable: false
35
+
36
+ c.desc 'Recurse to depth'
37
+ c.arg_name 'DEPTH'
38
+ c.flag %i[d depth], type: :integer, must_match: /^\d+$/
39
+
40
+ c.desc 'Show actions from a specific todo file in history. May use wildcards (* and ?)'
41
+ c.arg_name 'TODO_PATH'
42
+ c.flag %i[in]
43
+
44
+ c.desc 'Include notes in output'
45
+ c.switch %i[notes], negatable: true, default_value: false
46
+
47
+ c.desc 'Show actions from a specific project'
48
+ c.arg_name 'PROJECT[/SUBPROJECT]'
49
+ c.flag %i[proj project]
50
+
51
+ c.desc 'Match actions containing tag. Allows value comparisons'
52
+ c.arg_name 'TAG'
53
+ c.flag %i[tagged], multiple: true
54
+
55
+ c.desc 'Output actions nested by file'
56
+ c.switch %[nest], negatable: false
57
+
58
+ c.desc 'Output actions nested by file and project'
59
+ c.switch %[omnifocus], negatable: false
60
+
61
+ c.desc 'Save this search for future use'
62
+ c.arg_name 'TITLE'
63
+ c.flag %i[save]
64
+
65
+ c.action do |_global_options, options, args|
66
+ tag_string = []
67
+ if options[:before] || options[:on] || options[:after]
68
+ tag_string << "done<#{options[:before]}" if options[:before]
69
+ tag_string << "done=#{options[:on]}" if options[:on]
70
+ tag_string << "done>#{options[:after]}" if options[:after]
71
+ else
72
+ tag_string << 'done'
73
+ end
74
+
75
+ tag_string.concat(options[:tagged]) if options[:tagged]
76
+
77
+ if args.empty?
78
+ cmd_string = %(tagged --done "#{tag_string.join(',')}")
79
+ else
80
+ cmd_string = %(find --tagged "#{tag_string.join(',')}" --done #{args.join(' ')})
81
+ end
82
+
83
+ cmd_string += ' --or' if options[:or]
84
+ cmd_string += %( --in "#{options[:in]}") if options[:in]
85
+ cmd_string += %( --project "#{options[:project]}") if options[:project]
86
+ cmd_string += %( --depth #{options[:depth]}) if options[:depth]
87
+ cmd_string += ' --nest' if options[:nest]
88
+ cmd_string += ' --omnifocus' if options[:omnifocus]
89
+ cmd_string += " --#{options[:notes] ? 'notes' : 'no-notes' }"
90
+
91
+ if options[:save]
92
+ title = options[:save].gsub(/[^a-z0-9]/, '_').gsub(/_+/, '_')
93
+ NA.save_search(title, cmd_string)
94
+ end
95
+
96
+ exit run(Shellwords.shellsplit(cmd_string))
97
+ end
98
+ end
99
+ end
data/bin/commands/edit.rb CHANGED
@@ -1,45 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- desc 'Open a todo file in the default editor'
4
- long_desc 'Let the system choose the defualt, (e.g. TaskPaper), or specify a command line utility (e.g. vim).
5
- If more than one todo file is found, a menu is displayed.'
6
- command %i[edit] do |c|
7
- c.example 'na edit', desc: 'Open the main todo file in the default editor'
8
- c.example 'na edit -d 3 -a vim', desc: 'Display a menu of all todo files three levels deep from the
9
- current directory, open selection in vim.'
3
+ class App
4
+ extend GLI::App
5
+ desc 'Open a todo file in the default editor'
6
+ long_desc 'Let the system choose the defualt, (e.g. TaskPaper), or specify a command line utility (e.g. vim).
7
+ If more than one todo file is found, a menu is displayed.'
8
+ command %i[edit] do |c|
9
+ c.example 'na edit', desc: 'Open the main todo file in the default editor'
10
+ c.example 'na edit -d 3 -a vim', desc: 'Display a menu of all todo files three levels deep from the
11
+ current directory, open selection in vim.'
10
12
 
11
- c.desc 'Recurse to depth'
12
- c.arg_name 'DEPTH'
13
- c.default_value 1
14
- c.flag %i[d depth], type: :integer, must_match: /^\d+$/
13
+ c.desc 'Recurse to depth'
14
+ c.arg_name 'DEPTH'
15
+ c.default_value 1
16
+ c.flag %i[d depth], type: :integer, must_match: /^\d+$/
15
17
 
16
- c.desc 'Specify an editor CLI'
17
- c.arg_name 'EDITOR'
18
- c.flag %i[e editor]
18
+ c.desc 'Specify an editor CLI'
19
+ c.arg_name 'EDITOR'
20
+ c.flag %i[e editor]
19
21
 
20
- c.desc 'Specify a Mac app'
21
- c.arg_name 'EDITOR'
22
- c.flag %i[a app]
22
+ c.desc 'Specify a Mac app'
23
+ c.arg_name 'EDITOR'
24
+ c.flag %i[a app]
23
25
 
24
- c.action do |global_options, options, args|
25
- depth = if global_options[:recurse] && options[:depth].nil? && global_options[:depth] == 1
26
- 3
27
- else
28
- options[:depth].nil? ? global_options[:depth].to_i : options[:depth].to_i
29
- end
30
- files = NA.find_files(depth: depth)
31
- files.delete_if { |f| f !~ /.*?(#{args.join('|')}).*?.#{NA.extension}/ } if args.count.positive?
26
+ c.action do |global_options, options, args|
27
+ depth = if global_options[:recurse] && options[:depth].nil? && global_options[:depth] == 1
28
+ 3
29
+ else
30
+ options[:depth].nil? ? global_options[:depth].to_i : options[:depth].to_i
31
+ end
32
+ files = NA.find_files(depth: depth)
33
+ files.delete_if { |f| f !~ /.*?(#{args.join('|')}).*?.#{NA.extension}/ } if args.count.positive?
32
34
 
33
- file = if files.count > 1
34
- NA.select_file(files)
35
- else
36
- files[0]
37
- end
35
+ file = if files.count > 1
36
+ NA.select_file(files)
37
+ else
38
+ files[0]
39
+ end
38
40
 
39
- if options[:editor]
40
- system options[:editor], file
41
- else
42
- NA.edit_file(file: file, app: options[:app])
41
+ if options[:editor]
42
+ system options[:editor], file
43
+ else
44
+ NA.edit_file(file: file, app: options[:app])
45
+ end
43
46
  end
44
47
  end
45
48
  end