na 1.2.35 → 1.2.37

Sign up to get free protection for your applications and to get access to all the features.
data/lib/na/todo.rb ADDED
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NA
4
+ class Todo
5
+ attr_accessor :actions, :projects, :files
6
+
7
+ def initialize(options = {})
8
+ @files, @actions, @projects = parse(options)
9
+ end
10
+
11
+ ##
12
+ ## Read a todo file and create a list of actions
13
+ ##
14
+ ## @param options The options
15
+ ##
16
+ ## @option depth [Number] The directory depth to
17
+ ## search for files
18
+ ## @option done [Boolean] include @done actions
19
+ ## @option query [Hash] The todo file query
20
+ ## @option tag [Array] Tags to search for
21
+ ## @option search [String] A search string
22
+ ## @option negate [Boolean] Invert results
23
+ ## @option regex [Boolean] Interpret as regular
24
+ ## expression
25
+ ## @option project [String] The project
26
+ ## @option require_na [Boolean] Require @na tag
27
+ ## @option file_path [String] file path to parse
28
+ ##
29
+ def parse(options)
30
+ defaults = {
31
+ depth: 1,
32
+ done: false,
33
+ file_path: nil,
34
+ negate: false,
35
+ project: nil,
36
+ query: nil,
37
+ regex: false,
38
+ require_na: true,
39
+ search: nil,
40
+ tag: nil
41
+ }
42
+
43
+ settings = defaults.merge(options)
44
+
45
+ actions = NA::Actions.new
46
+ required = []
47
+ optional = []
48
+ negated = []
49
+ required_tag = []
50
+ optional_tag = []
51
+ negated_tag = []
52
+ projects = []
53
+
54
+ NA.notify("{dw}Tags: #{settings[:tag]}", debug:true)
55
+ NA.notify("{dw}Search: #{settings[:search]}", debug:true)
56
+
57
+ settings[:tag]&.each do |t|
58
+ unless t[:tag].nil?
59
+ if settings[:negate]
60
+ optional_tag.push(t) if t[:negate]
61
+ required_tag.push(t) if t[:required] && t[:negate]
62
+ negated_tag.push(t) unless t[:negate]
63
+ else
64
+ optional_tag.push(t) unless t[:negate]
65
+ required_tag.push(t) if t[:required] && !t[:negate]
66
+ negated_tag.push(t) if t[:negate]
67
+ end
68
+ end
69
+ end
70
+
71
+ unless settings[:search].nil? || settings[:search].empty?
72
+ if settings[:regex] || settings[:search].is_a?(String)
73
+ if settings[:negate]
74
+ negated.push(settings[:search])
75
+ else
76
+ optional.push(settings[:search])
77
+ required.push(settings[:search])
78
+ end
79
+ else
80
+ settings[:search].each do |t|
81
+ opt, req, neg = parse_search(t, settings[:negate])
82
+ optional.concat(opt)
83
+ required.concat(req)
84
+ negated.concat(neg)
85
+ end
86
+ end
87
+ end
88
+
89
+ files = if !settings[:file_path].nil?
90
+ [settings[:file_path]]
91
+ elsif settings[:query].nil?
92
+ NA.find_files(depth: settings[:depth])
93
+ else
94
+ NA.match_working_dir(settings[:query])
95
+ end
96
+
97
+ files.each do |file|
98
+ NA.save_working_dir(File.expand_path(file))
99
+ content = file.read_file
100
+ indent_level = 0
101
+ parent = []
102
+ in_action = false
103
+ content.split(/\n/).each.with_index do |line, idx|
104
+ if line.project?
105
+ in_action = false
106
+ proj = line.project
107
+ indent = line.indent_level
108
+
109
+ if indent.zero? # top level project
110
+ parent = [proj]
111
+ elsif indent <= indent_level # if indent level is same or less, split parent before indent level and append
112
+ parent.slice!(indent, parent.count - indent)
113
+ parent.push(proj)
114
+ else # if indent level is greater, append project to parent
115
+ parent.push(proj)
116
+ end
117
+
118
+ projects.push(NA::Project.new(parent.join(':'), indent, idx, idx))
119
+
120
+ indent_level = indent
121
+ elsif line.blank?
122
+ in_action = false
123
+ elsif line.action?
124
+ in_action = false
125
+
126
+ action = line.action
127
+ new_action = NA::Action.new(file, File.basename(file, ".#{NA.extension}"), parent.dup, action, idx)
128
+
129
+ projects[-1].last_line = idx if projects.count.positive?
130
+
131
+ next if line.done? && !settings[:done]
132
+
133
+ next if settings[:require_na] && !line.na?
134
+
135
+ has_search = !optional.empty? || !required.empty? || !negated.empty?
136
+
137
+ next if has_search && !new_action.search_match?(any: optional,
138
+ all: required,
139
+ none: negated)
140
+
141
+ if settings[:project]
142
+ rx = settings[:project].split(%r{[/:]}).join('.*?/')
143
+ next unless parent.join('/') =~ Regexp.new("#{rx}.*?", Regexp::IGNORECASE)
144
+ end
145
+
146
+ has_tag = !optional_tag.empty? || !required_tag.empty? || !negated_tag.empty?
147
+ next if has_tag && !new_action.tags_match?(any: optional_tag,
148
+ all: required_tag,
149
+ none: negated_tag)
150
+
151
+ actions.push(new_action)
152
+ in_action = true
153
+ elsif in_action
154
+ actions[-1].note.push(line.strip) if actions.count.positive?
155
+ projects[-1].last_line = idx if projects.count.positive?
156
+ end
157
+ end
158
+ projects = projects.dup
159
+ end
160
+
161
+ [files, actions, projects]
162
+ end
163
+
164
+ def parse_search(tag, negate)
165
+ required = []
166
+ optional = []
167
+ negated = []
168
+ new_rx = tag[:token].to_s.wildcard_to_rx
169
+
170
+ if negate
171
+ optional.push(new_rx) if tag[:negate]
172
+ required.push(new_rx) if tag[:required] && tag[:negate]
173
+ negated.push(new_rx) unless tag[:negate]
174
+ else
175
+ optional.push(new_rx) unless tag[:negate]
176
+ required.push(new_rx) if tag[:required] && !tag[:negate]
177
+ negated.push(new_rx) if tag[:negate]
178
+ end
179
+
180
+ [optional, required, negated]
181
+ end
182
+ end
183
+ end
data/lib/na/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Na
2
- VERSION = '1.2.35'
2
+ VERSION = '1.2.37'
3
3
  end
data/lib/na.rb CHANGED
@@ -13,7 +13,10 @@ require 'na/hash'
13
13
  require 'na/colors'
14
14
  require 'na/string'
15
15
  require 'na/array'
16
+ require 'na/todo'
17
+ require 'na/actions'
16
18
  require 'na/project'
17
19
  require 'na/action'
20
+ require 'na/editor'
18
21
  require 'na/next_action'
19
22
  require 'na/prompt'
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.34<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.2.35<!--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
 
@@ -69,7 +69,7 @@ You can mark todos as complete, delete them, add and remove tags, change priorit
69
69
  ### Usage
70
70
 
71
71
  ```
72
- @cli(bundle exec bin/na help)
72
+ @cli(na help)
73
73
  ```
74
74
 
75
75
  #### Commands
@@ -87,13 +87,13 @@ Use the `--note` switch to add a note. If STDIN (piped) input is present when th
87
87
  Notes are not displayed by the `next/tagged/find` commands unless `--notes` is specified.
88
88
 
89
89
  ```
90
- @cli(bundle exec bin/na help add)
90
+ @cli(na help add)
91
91
  ```
92
92
 
93
93
  ##### edit
94
94
 
95
95
  ```
96
- @cli(bundle exec bin/na help edit)
96
+ @cli(na help edit)
97
97
  ```
98
98
 
99
99
  ##### find
@@ -103,13 +103,13 @@ Example: `na find cool feature idea`
103
103
  Unless `--exact` is specified, search is tokenized and combined with AND, so `na find cool feature idea` translates to `cool AND feature AND idea`, matching any string that contains all of the words. To make a token required and others optional, add a `+` before it (e.g. `cool +feature idea` is `(cool OR idea) AND feature`). Wildcards allowed (`*` and `?`), use `--regex` to interpret the search as a regular expression. Use `-v` to invert the results (display non-matching actions only).
104
104
 
105
105
  ```
106
- @cli(bundle exec bin/na help find)
106
+ @cli(na help find)
107
107
  ```
108
108
 
109
109
  ##### init, create
110
110
 
111
111
  ```
112
- @cli(bundle exec bin/na help init)
112
+ @cli(na help init)
113
113
  ```
114
114
 
115
115
  ##### next, show
@@ -123,7 +123,7 @@ Examples:
123
123
  To see all next actions across all known todos, use `na next "*"`. You can combine multiple arguments to see actions across multiple todos, e.g. `na next marked nvultra`.
124
124
 
125
125
  ```
126
- @cli(bundle exec bin/na help next)
126
+ @cli(na help next)
127
127
  ```
128
128
 
129
129
  ##### projects
@@ -131,7 +131,7 @@ To see all next actions across all known todos, use `na next "*"`. You can combi
131
131
  List all projects in a file. If arguments are provided, they're used to match a todo file from history, otherwise the todo file(s) in the current directory will be used.
132
132
 
133
133
  ```
134
- @cli(bundle exec bin/na help projects)
134
+ @cli(na help projects)
135
135
  ```
136
136
 
137
137
  ##### saved
@@ -146,7 +146,7 @@ Run `na saved` without an argument to list your saved searches.
146
146
  <!--JEKYLL{:.tip}-->
147
147
 
148
148
  ```
149
- @cli(bundle exec bin/na help saved)
149
+ @cli(na help saved)
150
150
  ```
151
151
 
152
152
  ##### tagged
@@ -160,7 +160,7 @@ You can also perform value comparisons on tags. A value in a TaskPaper tag is ad
160
160
  To perform a string comparison, you can use `*=` (contains), `^=` (starts with), `$=` (ends with), or `=` (matches). E.g. `na tagged "note*=video"`.
161
161
 
162
162
  ```
163
- @cli(bundle exec bin/na help show)
163
+ @cli(na help show)
164
164
  ```
165
165
 
166
166
  ##### todos
@@ -168,7 +168,7 @@ To perform a string comparison, you can use `*=` (contains), `^=` (starts with),
168
168
  List all known todo files from history.
169
169
 
170
170
  ```
171
- @cli(bundle exec bin/na help todos)
171
+ @cli(na help todos)
172
172
  ```
173
173
 
174
174
  ##### update
@@ -206,7 +206,31 @@ Notes are not displayed by the `next/tagged/find` commands unless `--notes` is s
206
206
  See the help output for a list of all available actions.
207
207
 
208
208
  ```
209
- @cli(bundle exec bin/na help update)
209
+ @cli(na help update)
210
+ ```
211
+
212
+ ##### changelog
213
+
214
+ View recent changes with `na changelog` or `na changes`.
215
+
216
+ ```
217
+ @cli(na help changelog)
218
+ ```
219
+
220
+ ##### complete
221
+
222
+ Mark an action as complete, shortcut for `na update --finish`.
223
+
224
+ ```
225
+ @cli(na help complete)
226
+ ```
227
+
228
+ ##### archive
229
+
230
+ Mark an action as complete and move to archive, shortcut for `na update --archive`.
231
+
232
+ ```
233
+ @cli(na help archive)
210
234
  ```
211
235
 
212
236
  ### Configuration
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.35
4
+ version: 1.2.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-30 00:00:00.000000000 Z
11
+ date: 2023-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -222,12 +222,15 @@ files:
222
222
  - bin/commands/saved.rb
223
223
  - bin/commands/tagged.rb
224
224
  - bin/commands/todos.rb
225
+ - bin/commands/undo.rb
225
226
  - bin/commands/update.rb
226
227
  - bin/na
227
228
  - lib/na.rb
228
229
  - lib/na/action.rb
230
+ - lib/na/actions.rb
229
231
  - lib/na/array.rb
230
232
  - lib/na/colors.rb
233
+ - lib/na/editor.rb
231
234
  - lib/na/hash.rb
232
235
  - lib/na/help_monkey_patch.rb
233
236
  - lib/na/next_action.rb
@@ -235,6 +238,7 @@ files:
235
238
  - lib/na/project.rb
236
239
  - lib/na/prompt.rb
237
240
  - lib/na/string.rb
241
+ - lib/na/todo.rb
238
242
  - lib/na/version.rb
239
243
  - na.gemspec
240
244
  - na.rdoc