na 1.2.40 → 1.2.41

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2039d6fb16db44b000517f1f19d0928c5b82124abfe1c5416f98b892f21d88da
4
- data.tar.gz: a21cd96adf698afdbf0ffd55eb43ae9c408c46cbcbec691aeb9d1052f1a55862
3
+ metadata.gz: 817b128da7a400740e7e7ee5f8fb8d50920745290475c83ae9c70f23b2d2638e
4
+ data.tar.gz: ba7c83c4710bd2794ecf0c9d570cbbadf3188dc622c46b7e82afeeff7d8c0f75
5
5
  SHA512:
6
- metadata.gz: a1a9e7ac7341409792174d9ecce9b00379e9fa0a53c75d01d7abf8318d7336b417aa41d1a23d5a00628a8aef9fd1f3c53070b795220b7c94b0c5d8fa12781b63
7
- data.tar.gz: 4033e29443e01ff8ee866f98255f9f2b008619d1a1f1b2e3420201a7efb99837eae612d3383234afb67c6c30fea16a1cad2199a273fd66c7d6ef21275d2aa0a5
6
+ metadata.gz: 6df78d477a696e991210196962c28238dc397de20747fba3e24a54d2e341d06c8194957b0b04a612a7c6f504f77912f541a813b9717fc0886b7cc8d9049b531e
7
+ data.tar.gz: 43d3affb7e8c8e720309b65430d314ae4ab484ad0136c9a2689dacebad28d5703568d0ad01f219ddfd0c85f998b57fd91a5f5bdc6784d95e1f88a04167473191
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ### 1.2.41
2
+
3
+ 2023-09-06 08:13
4
+
5
+ #### NEW
6
+
7
+ - Tag command
8
+
9
+ #### FIXED
10
+
11
+ - Nil error in action.pretty
12
+
1
13
  ### 1.2.40
2
14
 
3
15
  2023-09-06 08:11
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- na (1.2.40)
4
+ na (1.2.41)
5
5
  chronic (~> 0.10, >= 0.10.2)
6
6
  gli (~> 2.21.0)
7
7
  mdless (~> 1.0, >= 1.0.32)
data/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 1.2.40
12
+ The current version of `na` is 1.2.41
13
13
  .
14
14
 
15
15
  `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.
@@ -77,7 +77,7 @@ SYNOPSIS
77
77
  na [global options] command [command options] [arguments...]
78
78
 
79
79
  VERSION
80
- 1.2.40
80
+ 1.2.41
81
81
 
82
82
  GLOBAL OPTIONS
83
83
  -a, --add - Add a next action (deprecated, for backwards compatibility)
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ class App
4
+ extend GLI::App
5
+ desc 'Add tags to matching action(s)'
6
+ long_desc 'Provides an easy way to tag existing actions.
7
+
8
+ Use !tag to remove a tag, use ~tag(new value) to change a tag or add a value.
9
+
10
+ If multiple todo files are found in the current directory, a menu will
11
+ allow you to pick which file to act on, or use --all to apply to all matches.'
12
+ arg_name 'TAG', mutliple: true
13
+ command %i[tag] do |c|
14
+ c.example 'na tag "project(warpspeed)" --search "An existing task"',
15
+ desc: 'Find "An existing task" action and add @project(warpspeed) to it'
16
+ c.example 'na tag "!project1" --tagged project2 --all',
17
+ desc: 'Find all actions tagged @project2 and remove @project1 from them'
18
+ c.example 'na tag "!project2" --all',
19
+ desc: 'Remove @project2 from all actions'
20
+ c.example 'na tag "~project(dirt nap)" --search "An existing task"',
21
+ desc: 'Find "An existing task" and change (or add) its @project tag value to "dirt nap"'
22
+
23
+ c.desc 'Use a known todo file, partial matches allowed'
24
+ c.arg_name 'TODO_FILE'
25
+ c.flag %i[in todo]
26
+
27
+ c.desc 'Include @done actions'
28
+ c.switch %i[done]
29
+
30
+ c.desc 'Specify the file to search for the task'
31
+ c.arg_name 'PATH'
32
+ c.flag %i[file]
33
+
34
+ c.desc 'Search for files X directories deep'
35
+ c.arg_name 'DEPTH'
36
+ c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
37
+
38
+ c.desc 'Match actions containing tag. Allows value comparisons'
39
+ c.arg_name 'TAG'
40
+ c.flag %i[tagged], multiple: true
41
+
42
+ c.desc 'Act on all matches immediately (no menu)'
43
+ c.switch %i[all], negatable: false
44
+
45
+ c.desc 'Filter results using search terms'
46
+ c.arg_name 'QUERY'
47
+ c.flag %i[search find grep], multiple: true
48
+
49
+ c.desc 'Interpret search pattern as regular expression'
50
+ c.switch %i[e regex], negatable: false
51
+
52
+ c.desc 'Match pattern exactly'
53
+ c.switch %i[x exact], negatable: false
54
+
55
+ c.action do |global_options, options, args|
56
+ tags = args.join(',').split(/ *, */)
57
+ options[:remove] = []
58
+ options[:tag] = []
59
+ tags.each do |tag|
60
+ if tag =~ /^[!-]/
61
+ options[:remove] << tag.sub(/^[!-]/, '').sub(/^@/, '')
62
+ elsif tag =~ /^~/
63
+ options[:remove] << tag.sub(/^~/, '').sub(/\(.*?\)$/, '').sub(/^@/, '')
64
+ options[:tag] << tag.sub(/^~/, '').sub(/^@/, '')
65
+ else
66
+ options[:tag] << tag.sub(/^@/, '')
67
+ end
68
+ end
69
+
70
+ if options[:search]
71
+ tokens = nil
72
+ if options[:exact]
73
+ tokens = options[:search]
74
+ elsif options[:regex]
75
+ tokens = Regexp.new(options[:search], Regexp::IGNORECASE)
76
+ else
77
+ action = options[:search].join(' ')
78
+ tokens = []
79
+ all_req = action !~ /[+!-]/ && !options[:or]
80
+
81
+ action.split(/ /).each do |arg|
82
+ m = arg.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
83
+ tokens.push({
84
+ token: m['tok'],
85
+ required: all_req || (!m['req'].nil? && m['req'] == '+'),
86
+ negate: !m['req'].nil? && m['req'] =~ /[!-]/ ? true : false
87
+ })
88
+ end
89
+ end
90
+ end
91
+
92
+ if (tokens.nil? || tokens.empty?) && options[:tagged].empty?
93
+ NA.notify("#{NA.theme[:error]}Empty input, cancelled", exit_code: 1)
94
+ end
95
+
96
+ all_req = options[:tagged].join(' ') !~ /[+!-]/ && !options[:or]
97
+ tags = []
98
+ options[:tagged].join(',').split(/ *, */).each do |arg|
99
+ m = arg.match(/^(?<req>[+!-])?(?<tag>[^ =<>$~\^]+?) *(?:(?<op>[=<>~]{1,2}|[*$\^]=) *(?<val>.*?))?$/)
100
+
101
+ tags.push({
102
+ tag: m['tag'].wildcard_to_rx,
103
+ comp: m['op'],
104
+ value: m['val'],
105
+ required: all_req || (!m['req'].nil? && m['req'] == '+'),
106
+ negate: !m['req'].nil? && m['req'] =~ /[!-]/ ? true : false
107
+ })
108
+ end
109
+
110
+ add_tags = options[:tag] ? options[:tag].join(',').split(/ *, */).map { |t| t.sub(/^@/, '').wildcard_to_rx } : []
111
+ remove_tags = options[:remove] ? options[:remove].join(',').split(/ *, */).map { |t| t.sub(/^@/, '').wildcard_to_rx } : []
112
+
113
+ if options[:file]
114
+ file = File.expand_path(options[:file])
115
+ NA.notify("#{NA.theme[:error]}File not found", exit_code: 1) unless File.exist?(file)
116
+
117
+ targets = [file]
118
+ elsif options[:todo]
119
+ todo = []
120
+ options[:todo].split(/ *, */).each do |a|
121
+ m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
122
+ todo.push({
123
+ token: m['tok'],
124
+ required: all_req || (!m['req'].nil? && m['req'] == '+'),
125
+ negate: !m['req'].nil? && m['req'] =~ /[!-]/ ? true : false
126
+ })
127
+ end
128
+ dirs = NA.match_working_dir(todo)
129
+
130
+ if dirs.count == 1
131
+ targets = [dirs[0]]
132
+ elsif dirs.count.positive?
133
+ targets = NA.select_file(dirs, multiple: true)
134
+ NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1) unless targets && targets.count.positive?
135
+ else
136
+ NA.notify("#{NA.theme[:error]}Todo not found", exit_code: 1) unless targets && targets.count.positive?
137
+
138
+ end
139
+ else
140
+ files = NA.find_files_matching({
141
+ depth: options[:depth],
142
+ done: options[:done],
143
+ regex: options[:regex],
144
+ require_na: false,
145
+ search: tokens,
146
+ tag: tags
147
+ })
148
+ NA.notify("#{NA.theme[:error]}No todo file found", exit_code: 1) if files.count.zero?
149
+
150
+ targets = files.count > 1 ? NA.select_file(files, multiple: true) : [files[0]]
151
+ NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1) unless files.count.positive?
152
+
153
+ end
154
+
155
+ NA.notify("#{NA.theme[:error]}No search terms provided", exit_code: 1) if tokens.nil? && options[:tagged].empty?
156
+
157
+ targets.each do |target|
158
+ NA.update_action(target, tokens,
159
+ add_tag: add_tags,
160
+ all: options[:all],
161
+ done: options[:done],
162
+ remove_tag: remove_tags,
163
+ tagged: tags)
164
+ end
165
+ end
166
+ end
167
+ end
data/lib/na/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Na
2
- VERSION = '1.2.40'
2
+ VERSION = '1.2.41'
3
3
  end
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.39<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.2.40<!--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
 
data/test2.txt ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ comment: 2023
3
+ keywords:
4
+ ---
5
+
6
+ Inbox:
7
+ - Test @na
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: na
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.40
4
+ version: 1.2.41
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
@@ -220,6 +220,7 @@ files:
220
220
  - bin/commands/prompt.rb
221
221
  - bin/commands/restore.rb
222
222
  - bin/commands/saved.rb
223
+ - bin/commands/tag.rb
223
224
  - bin/commands/tagged.rb
224
225
  - bin/commands/todos.rb
225
226
  - bin/commands/undo.rb
@@ -245,6 +246,7 @@ files:
245
246
  - na.rdoc
246
247
  - scripts/fixreadme.rb
247
248
  - src/_README.md
249
+ - test2.txt
248
250
  homepage: https://brettterpstra.com/projects/na/
249
251
  licenses:
250
252
  - MIT