na 1.2.63 → 1.2.64
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +46 -4
- data/bin/commands/move.rb +203 -0
- data/lib/na/next_action.rb +2 -2
- data/lib/na/version.rb +1 -1
- data/src/_README.md +15 -1
- metadata +4 -4
- data/0 +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c2accac212d5f998f830299693f13e3ec27e692b1bc5f460bcd977fb1ce95042
|
|
4
|
+
data.tar.gz: ad75051381180b3d4cc99fe3edb841a591e76ca649eaa051a12752f6066a1ed2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 96a9f0120855bf9569dd5d35f7701c24196185fa0d82a12e143486687072778cca636369264c45b286e0e4030722cb817258f585f399e50929b3f500bdea47f9
|
|
7
|
+
data.tar.gz: bd58a4c3872fb7ad608f15bdc31fd954f8f7581f168c30e7db3c1e11986df884905a964cfcd263d7807a3f583e22d22e33e0f8c9a46842407a5096d5f17b2271
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
_If you're one of the rare people like me who find this useful, feel free to
|
|
10
10
|
[buy me some coffee][donate]._
|
|
11
11
|
|
|
12
|
-
The current version of `na` is 1.2.
|
|
13
|
-
.
|
|
12
|
+
The current version of `na` is 1.2.64.
|
|
14
13
|
|
|
15
14
|
`na` ("next action") is a command line tool designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-formatted files (but any plain text format will do), looking for `@na` tags (or whatever you specify) in todo files in your current folder.
|
|
16
15
|
|
|
@@ -77,14 +76,14 @@ SYNOPSIS
|
|
|
77
76
|
na [global options] command [command options] [arguments...]
|
|
78
77
|
|
|
79
78
|
VERSION
|
|
80
|
-
1.2.
|
|
79
|
+
1.2.64
|
|
81
80
|
|
|
82
81
|
GLOBAL OPTIONS
|
|
83
82
|
-a, --add - Add a next action (deprecated, for backwards compatibility)
|
|
84
83
|
--add_at=POSITION - Add all new/moved entries at [s]tart or [e]nd of target project (default: start)
|
|
85
84
|
--[no-]color - Colorize output (default: enabled)
|
|
86
85
|
--cwd_as=TYPE - Use current working directory as [p]roject, [t]ag, or [n]one (default: none)
|
|
87
|
-
-d, --depth=DEPTH - Recurse to depth (default:
|
|
86
|
+
-d, --depth=DEPTH - Recurse to depth (default: 1)
|
|
88
87
|
--[no-]debug - Display verbose output
|
|
89
88
|
--ext=EXT - File extension to consider a todo file (default: taskpaper)
|
|
90
89
|
-f, --file=PATH - Use a single file as global todo, use initconfig to make permanent (default: none)
|
|
@@ -109,6 +108,7 @@ COMMANDS
|
|
|
109
108
|
help - Shows a list of commands or help for one command
|
|
110
109
|
init, create - Create a new todo file in the current directory
|
|
111
110
|
initconfig - Initialize the config file using current global options
|
|
111
|
+
move - Move an existing action to a different section
|
|
112
112
|
next, show - Show next actions
|
|
113
113
|
open - Open a todo file in the default editor
|
|
114
114
|
projects - Show list of projects for a file
|
|
@@ -264,6 +264,48 @@ EXAMPLES
|
|
|
264
264
|
na init warpspeed
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
+
##### move
|
|
268
|
+
|
|
269
|
+
Move an action between projects. Argument is a search term, if left blank a prompt will allow you to enter terms. If no `--to` project is specified, a menu will be shown of projects in the target file.
|
|
270
|
+
|
|
271
|
+
Examples:
|
|
272
|
+
|
|
273
|
+
- `na move` (enter a search term, select a file/destination)
|
|
274
|
+
- `na move "Bug description"` (find matching action and show a menu of project destinations)
|
|
275
|
+
- `na move "Bug description" --to Bugs (move matching action to Bugs project)
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
NAME
|
|
279
|
+
move - Move an existing action to a different section
|
|
280
|
+
|
|
281
|
+
SYNOPSIS
|
|
282
|
+
|
|
283
|
+
na [global options] move [command options] ACTION
|
|
284
|
+
|
|
285
|
+
DESCRIPTION
|
|
286
|
+
Provides an easy way to move an action. If multiple todo files are found in the current directory, a menu will allow you to pick which file to act on.
|
|
287
|
+
|
|
288
|
+
COMMAND OPTIONS
|
|
289
|
+
--all - Act on all matches immediately (no menu)
|
|
290
|
+
--at=POSITION - When moving task, add at [s]tart or [e]nd of target project (default: none)
|
|
291
|
+
-d, --depth=DEPTH - Search for files X directories deep (default: 1)
|
|
292
|
+
-e, --regex - Interpret search pattern as regular expression
|
|
293
|
+
--file=PATH - Specify the file to search for the task (default: none)
|
|
294
|
+
--from=PROJECT[/SUBPROJECT] - Search for actions in a specific project (default: none)
|
|
295
|
+
--in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
|
|
296
|
+
-n, --note - Prompt for additional notes. Input will be appended to any existing note. If STDIN input (piped) is detected, it will be used as a note.
|
|
297
|
+
-o, --overwrite - Overwrite note instead of appending
|
|
298
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
299
|
+
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
300
|
+
--to=PROJECT - Move action to specific project. If not provided, a menu will be shown (default: none)
|
|
301
|
+
-x, --exact - Match pattern exactly
|
|
302
|
+
|
|
303
|
+
EXAMPLE
|
|
304
|
+
|
|
305
|
+
# Find "A bug in inbox" action and move it to section Bugs
|
|
306
|
+
na move "A bug in inbox" --to Bugs
|
|
307
|
+
```
|
|
308
|
+
|
|
267
309
|
##### next, show
|
|
268
310
|
|
|
269
311
|
Examples:
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class App
|
|
4
|
+
extend GLI::App
|
|
5
|
+
desc 'Move an existing action to a different section'
|
|
6
|
+
long_desc 'Provides an easy way to move an action.
|
|
7
|
+
|
|
8
|
+
If multiple todo files are found in the current directory, a menu will
|
|
9
|
+
allow you to pick which file to act on.'
|
|
10
|
+
arg_name 'ACTION'
|
|
11
|
+
command %i[move] do |c|
|
|
12
|
+
c.example 'na move "A bug in inbox" --to Bugs',
|
|
13
|
+
desc: 'Find "A bug in inbox" action and move it to section Bugs'
|
|
14
|
+
|
|
15
|
+
c.desc 'Prompt for additional notes. Input will be appended to any existing note.
|
|
16
|
+
If STDIN input (piped) is detected, it will be used as a note.'
|
|
17
|
+
c.switch %i[n note], negatable: false
|
|
18
|
+
|
|
19
|
+
c.desc 'Overwrite note instead of appending'
|
|
20
|
+
c.switch %i[o overwrite], negatable: false
|
|
21
|
+
|
|
22
|
+
c.desc 'Move action to specific project. If not provided, a menu will be shown'
|
|
23
|
+
c.arg_name 'PROJECT'
|
|
24
|
+
c.flag %i[to]
|
|
25
|
+
|
|
26
|
+
c.desc 'When moving task, add at [s]tart or [e]nd of target project'
|
|
27
|
+
c.arg_name 'POSITION'
|
|
28
|
+
c.flag %i[at], must_match: /^[sbea].*?$/i
|
|
29
|
+
|
|
30
|
+
c.desc 'Search for actions in a specific project'
|
|
31
|
+
c.arg_name 'PROJECT[/SUBPROJECT]'
|
|
32
|
+
c.flag %i[from]
|
|
33
|
+
|
|
34
|
+
c.desc 'Use a known todo file, partial matches allowed'
|
|
35
|
+
c.arg_name 'TODO_FILE'
|
|
36
|
+
c.flag %i[in todo]
|
|
37
|
+
|
|
38
|
+
c.desc 'Specify the file to search for the task'
|
|
39
|
+
c.arg_name 'PATH'
|
|
40
|
+
c.flag %i[file]
|
|
41
|
+
|
|
42
|
+
c.desc 'Search for files X directories deep'
|
|
43
|
+
c.arg_name 'DEPTH'
|
|
44
|
+
c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
|
|
45
|
+
|
|
46
|
+
c.desc 'Include notes in search'
|
|
47
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
48
|
+
|
|
49
|
+
c.desc 'Match actions containing tag. Allows value comparisons'
|
|
50
|
+
c.arg_name 'TAG'
|
|
51
|
+
c.flag %i[tagged], multiple: true
|
|
52
|
+
|
|
53
|
+
c.desc 'Act on all matches immediately (no menu)'
|
|
54
|
+
c.switch %i[all], negatable: false
|
|
55
|
+
|
|
56
|
+
c.desc 'Interpret search pattern as regular expression'
|
|
57
|
+
c.switch %i[e regex], negatable: false
|
|
58
|
+
|
|
59
|
+
c.desc 'Match pattern exactly'
|
|
60
|
+
c.switch %i[x exact], negatable: false
|
|
61
|
+
|
|
62
|
+
c.action do |global_options, options, args|
|
|
63
|
+
reader = TTY::Reader.new
|
|
64
|
+
|
|
65
|
+
args.concat(options[:search]) unless options[:search].nil?
|
|
66
|
+
|
|
67
|
+
append = options[:at] ? options[:at] =~ /^[ae]/i : global_options[:add_at] =~ /^[ae]/i
|
|
68
|
+
|
|
69
|
+
options[:done] = true
|
|
70
|
+
|
|
71
|
+
action = if args.count.positive?
|
|
72
|
+
args.join(' ').strip
|
|
73
|
+
else
|
|
74
|
+
NA.request_input(options, prompt: 'Enter a task to search for')
|
|
75
|
+
end
|
|
76
|
+
if action
|
|
77
|
+
tokens = nil
|
|
78
|
+
if options[:exact]
|
|
79
|
+
tokens = action
|
|
80
|
+
elsif options[:regex]
|
|
81
|
+
tokens = Regexp.new(action, Regexp::IGNORECASE)
|
|
82
|
+
else
|
|
83
|
+
tokens = []
|
|
84
|
+
all_req = action !~ /[+!-]/ && !options[:or]
|
|
85
|
+
|
|
86
|
+
action.split(/ /).each do |arg|
|
|
87
|
+
m = arg.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
|
88
|
+
tokens.push({
|
|
89
|
+
token: m['tok'],
|
|
90
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
|
91
|
+
negate: !m['req'].nil? && m['req'] =~ /[!-]/ ? true : false
|
|
92
|
+
})
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if (action.nil? || action.empty?) && options[:tagged].empty?
|
|
98
|
+
NA.notify("#{NA.theme[:error]}Empty input, cancelled", exit_code: 1)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
all_req = options[:tagged].join(' ') !~ /[+!-]/ && !options[:or]
|
|
102
|
+
tags = []
|
|
103
|
+
options[:tagged].join(',').split(/ *, */).each do |arg|
|
|
104
|
+
m = arg.match(/^(?<req>[+!-])?(?<tag>[^ =<>$~\^]+?) *(?:(?<op>[=<>~]{1,2}|[*$\^]=) *(?<val>.*?))?$/)
|
|
105
|
+
|
|
106
|
+
tags.push({
|
|
107
|
+
tag: m['tag'].wildcard_to_rx,
|
|
108
|
+
comp: m['op'],
|
|
109
|
+
value: m['val'],
|
|
110
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
|
111
|
+
negate: !m['req'].nil? && m['req'] =~ /[!-]/ ? true : false
|
|
112
|
+
})
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
stdin_note = NA.stdin ? NA.stdin.split("\n") : []
|
|
116
|
+
|
|
117
|
+
line_note = if options[:note] && $stdin.isatty
|
|
118
|
+
puts stdin_note unless stdin_note.nil?
|
|
119
|
+
if TTY::Which.exist?('gum')
|
|
120
|
+
args = ['--placeholder "Enter a note, CTRL-d to save"']
|
|
121
|
+
args << '--char-limit 0'
|
|
122
|
+
args << '--width $(tput cols)'
|
|
123
|
+
gum = TTY::Which.which('gum')
|
|
124
|
+
`#{gum} write #{args.join(' ')}`.strip.split("\n")
|
|
125
|
+
else
|
|
126
|
+
NA.notify("#{NA.theme[:prompt]}Enter a note, {bw}CTRL-d#{NA.theme[:prompt]} to end editing:#{NA.theme[:action]}")
|
|
127
|
+
reader.read_multiline
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
note = stdin_note.empty? ? [] : stdin_note
|
|
132
|
+
note.concat(line_note) unless line_note.nil? || line_note.empty?
|
|
133
|
+
|
|
134
|
+
if options[:file]
|
|
135
|
+
file = File.expand_path(options[:file])
|
|
136
|
+
NA.notify("#{NA.theme[:error]}File not found", exit_code: 1) unless File.exist?(file)
|
|
137
|
+
|
|
138
|
+
targets = [file]
|
|
139
|
+
elsif options[:todo]
|
|
140
|
+
todo = []
|
|
141
|
+
options[:todo].split(/ *, */).each do |a|
|
|
142
|
+
m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
|
143
|
+
todo.push({
|
|
144
|
+
token: m['tok'],
|
|
145
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
|
146
|
+
negate: !m['req'].nil? && m['req'] =~ /[!-]/ ? true : false
|
|
147
|
+
})
|
|
148
|
+
end
|
|
149
|
+
dirs = NA.match_working_dir(todo)
|
|
150
|
+
|
|
151
|
+
if dirs.count == 1
|
|
152
|
+
targets = [dirs[0]]
|
|
153
|
+
elsif dirs.count.positive?
|
|
154
|
+
targets = NA.select_file(dirs, multiple: true)
|
|
155
|
+
NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1) unless targets && targets.count.positive?
|
|
156
|
+
else
|
|
157
|
+
NA.notify("#{NA.theme[:error]}Todo not found", exit_code: 1) unless targets && targets.count.positive?
|
|
158
|
+
|
|
159
|
+
end
|
|
160
|
+
else
|
|
161
|
+
files = NA.find_files_matching({
|
|
162
|
+
depth: options[:depth],
|
|
163
|
+
done: options[:done],
|
|
164
|
+
project: options[:from],
|
|
165
|
+
regex: options[:regex],
|
|
166
|
+
require_na: false,
|
|
167
|
+
search: tokens,
|
|
168
|
+
tag: tags
|
|
169
|
+
})
|
|
170
|
+
NA.notify("#{NA.theme[:error]}No todo file found", exit_code: 1) if files.count.zero?
|
|
171
|
+
|
|
172
|
+
targets = files.count > 1 ? NA.select_file(files, multiple: true) : [files[0]]
|
|
173
|
+
NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1) unless files.count.positive?
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
target_proj = if options[:to]
|
|
177
|
+
options[:to]
|
|
178
|
+
else
|
|
179
|
+
todo = NA::Todo.new(require_na: false, file_path: targets[0])
|
|
180
|
+
projects = todo.projects
|
|
181
|
+
menu = projects.each_with_object([]) { |proj, arr| arr << proj.project }
|
|
182
|
+
|
|
183
|
+
NA.choose_from(menu, prompt: 'Move to: ', multiple: false, sorted: false)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
NA.notify("#{NA.theme[:error]}No target selected", exit_code: 1) unless target_proj
|
|
187
|
+
|
|
188
|
+
NA.notify("#{NA.theme[:error]}No search terms provided", exit_code: 1) if tokens.nil? && options[:tagged].empty?
|
|
189
|
+
|
|
190
|
+
targets.each do |target|
|
|
191
|
+
NA.update_action(target, tokens,
|
|
192
|
+
all: options[:all],
|
|
193
|
+
append: append,
|
|
194
|
+
move: target_proj,
|
|
195
|
+
note: note,
|
|
196
|
+
overwrite: options[:overwrite],
|
|
197
|
+
project: options[:from],
|
|
198
|
+
search_note: options[:search_notes],
|
|
199
|
+
tagged: tags)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
data/lib/na/next_action.rb
CHANGED
|
@@ -425,7 +425,7 @@ module NA
|
|
|
425
425
|
end
|
|
426
426
|
|
|
427
427
|
def project_hierarchy(actions)
|
|
428
|
-
parents = { actions: []}
|
|
428
|
+
parents = { actions: [] }
|
|
429
429
|
actions.each do |a|
|
|
430
430
|
parent = a.parent
|
|
431
431
|
current_parent = parents
|
|
@@ -958,7 +958,7 @@ module NA
|
|
|
958
958
|
end
|
|
959
959
|
|
|
960
960
|
return false if res&.strip&.size&.zero?
|
|
961
|
-
pp NA::Color.uncolor(NA::Color.template(res))
|
|
961
|
+
# pp NA::Color.uncolor(NA::Color.template(res))
|
|
962
962
|
multiple ? NA::Color.uncolor(NA::Color.template(res)).split(/\n/) : NA::Color.uncolor(NA::Color.template(res))
|
|
963
963
|
end
|
|
964
964
|
|
data/lib/na/version.rb
CHANGED
data/src/_README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
_If you're one of the rare people like me who find this useful, feel free to
|
|
10
10
|
[buy me some coffee][donate]._
|
|
11
11
|
|
|
12
|
-
The current version of `na` is <!--VER-->1.2.
|
|
12
|
+
The current version of `na` is <!--VER-->1.2.63<!--END VER-->.
|
|
13
13
|
|
|
14
14
|
`na` ("next action") is a command line tool designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-formatted files (but any plain text format will do), looking for `@na` tags (or whatever you specify) in todo files in your current folder.
|
|
15
15
|
|
|
@@ -112,6 +112,20 @@ Unless `--exact` is specified, search is tokenized and combined with AND, so `na
|
|
|
112
112
|
@cli(bundle exec bin/na help init)
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
##### move
|
|
116
|
+
|
|
117
|
+
Move an action between projects. Argument is a search term, if left blank a prompt will allow you to enter terms. If no `--to` project is specified, a menu will be shown of projects in the target file.
|
|
118
|
+
|
|
119
|
+
Examples:
|
|
120
|
+
|
|
121
|
+
- `na move` (enter a search term, select a file/destination)
|
|
122
|
+
- `na move "Bug description"` (find matching action and show a menu of project destinations)
|
|
123
|
+
- `na move "Bug description" --to Bugs (move matching action to Bugs project)
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
@cli(bundle exec bin/na help move)
|
|
127
|
+
```
|
|
128
|
+
|
|
115
129
|
##### next, show
|
|
116
130
|
|
|
117
131
|
Examples:
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: na
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.64
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brett Terpstra
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-06-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -199,7 +199,6 @@ extra_rdoc_files:
|
|
|
199
199
|
- na.rdoc
|
|
200
200
|
files:
|
|
201
201
|
- ".travis.yml"
|
|
202
|
-
- '0'
|
|
203
202
|
- CHANGELOG.md
|
|
204
203
|
- Gemfile
|
|
205
204
|
- Gemfile.lock
|
|
@@ -216,6 +215,7 @@ files:
|
|
|
216
215
|
- bin/commands/edit.rb
|
|
217
216
|
- bin/commands/find.rb
|
|
218
217
|
- bin/commands/init.rb
|
|
218
|
+
- bin/commands/move.rb
|
|
219
219
|
- bin/commands/next.rb
|
|
220
220
|
- bin/commands/open.rb
|
|
221
221
|
- bin/commands/projects.rb
|
|
@@ -276,7 +276,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
276
276
|
- !ruby/object:Gem::Version
|
|
277
277
|
version: '0'
|
|
278
278
|
requirements: []
|
|
279
|
-
rubygems_version: 3.
|
|
279
|
+
rubygems_version: 3.2.15
|
|
280
280
|
signing_key:
|
|
281
281
|
specification_version: 4
|
|
282
282
|
summary: A command line tool for adding and listing project todos
|
data/0
DELETED
|
File without changes
|