intent 0.7.1 → 0.8.0

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: 1a78826427e690ed80d21f63d75c009a652d8f7e6152250a0259d21af5ec36d2
4
- data.tar.gz: 04c84e824a0787fed413ca28155143e407d322a8a5dd4dac76e0a14ee569a790
3
+ metadata.gz: eceb2c98af31fff1168ee446ea327a674c510e96d5bcfb948cae895e391a8399
4
+ data.tar.gz: a8225ec76a08ba859b7f8abff5729527e0426e51fff1757c26e00a63f5b5a9af
5
5
  SHA512:
6
- metadata.gz: 61ed11963ba4317356bdfef7d2213fe1f1b2b29153697a34c2d6bd2ce5a09a7f61c12a296c50879909f7f650b556ee7d4f0bce0ce11fc5de891c4a140264f546
7
- data.tar.gz: 79ba7a74906c8607edffeafc5d8555afe5853212d47b7253f8d2788567d13e4a843234a3d6934adfc1118315f3ac513e6567a5056aad1748497b73f74babe452
6
+ metadata.gz: 7151b6b4e09485ade42fc3dc8756aeaf933d72b96acdb5d216764866d9cf52dd04cfacb828bc4f8498e2a5d90397d7db30add5ae44f3370afb0f9c5916f24765
7
+ data.tar.gz: fb6b9209b34d67417a232b68e2a02dea9faf99e822252becc5d1b7dfc5a6fad5c8885ba4050258a587abc6e7afdc366e97afaf10be0ebbb768e45f2ba014987d
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Intent
2
2
 
3
- Automation engine with todo.txt
3
+ > **Automation engine with todo.txt**
4
4
 
5
5
  This tool is mired deep in the obscurity and pedantry of the text-based computing culture that originated in the 1970s and still continues today. You probably don’t want to use this.
6
6
 
@@ -16,6 +16,10 @@ gem install intent
16
16
  intent help
17
17
  ```
18
18
 
19
+ ## The ledger concept
20
+
21
+ Docs and an essay about managing text-based computational ledgers ‘coming soon’ (eventually).
22
+
19
23
  ## Copyright & License
20
24
 
21
25
  Copyright 2024 Mark Rickerby <https://maetl.net>.
data/bin/project ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ path = __FILE__
3
+ while File.symlink?(path)
4
+ path = File.expand_path(File.readlink(path), File.dirname(path))
5
+ end
6
+ $:.unshift(File.join(File.dirname(File.expand_path(path)), '..', 'lib'))
7
+
8
+ require 'intent'
9
+
10
+ Intent::Dispatcher.exec_command(:project, ARGV.dup)
@@ -0,0 +1,32 @@
1
+ module Intent
2
+ class Args
3
+ def initialize(input)
4
+ @arity = input.length
5
+
6
+ unless empty?
7
+ case @arity
8
+ when 1 then interpret_args_unary(input[0])
9
+ when 2 then interpret_args_binary(input[0], input[1])
10
+ when 3 then interpret_args_ternary(input[0], input[1], input[2])
11
+ end
12
+ end
13
+ end
14
+
15
+ def empty?
16
+ @arity == 0
17
+ end
18
+
19
+ private
20
+
21
+ def interpret_args_unary(arg1)
22
+
23
+ end
24
+
25
+ def interpret_args_binary(arg1, arg2)
26
+ end
27
+
28
+ def interpret_args_ternary(arg1, arg2, arg3)
29
+
30
+ end
31
+ end
32
+ end
@@ -1,8 +1,17 @@
1
1
  module Intent
2
2
  module Commands
3
- class Intent
3
+ class Intent < Base
4
4
  def run(args, output)
5
- output.puts args
5
+ if args.empty?
6
+ print_help(output)
7
+ else
8
+ case args.first.to_sym
9
+ when :help
10
+ print_help(output)
11
+ else
12
+ raise Core::Errors::COMMAND_NOT_FOUND
13
+ end
14
+ end
6
15
  end
7
16
  end
8
17
  end
@@ -1,5 +1,3 @@
1
- require 'tty-reader'
2
-
3
1
  module Intent
4
2
  module Commands
5
3
  class Inventory < Base
@@ -28,6 +26,12 @@ module Intent
28
26
  when :folder then assign_folder(args, output)
29
27
  when :box then assign_box(args, output)
30
28
  end
29
+ # CONCEPT:
30
+ # Verbs::Assign.invoke_rewrite()
31
+ # verbs.assign.invoke_rewrite(documents.inventory, noun)
32
+ when :sync then sync_inventory(args, output)
33
+ else
34
+ raise Errors:COMMAND_NOT_FOUND
31
35
  end
32
36
  end
33
37
  end
@@ -205,6 +209,11 @@ module Intent
205
209
  box.projects.concat(details[:projects])
206
210
  documents.inventory.save!
207
211
  end
212
+
213
+ def sync_inventory(args, output)
214
+ result = documents.inventory.sync!
215
+ output.puts "Sync inventory result: #{result}"
216
+ end
208
217
  end
209
218
  end
210
219
  end
@@ -0,0 +1,91 @@
1
+ module Intent
2
+ module Commands
3
+ class Project < Projects
4
+ def run(args, output)
5
+ if args.empty?
6
+ print_help(output)
7
+ else
8
+ case args.first.to_sym
9
+ when :help
10
+ print_help(output)
11
+ when :link
12
+ if args[1].nil?
13
+ # launch into projects selection?
14
+ raise "Need to link to a noun at this stage, sorry"
15
+ else
16
+ case args[1].to_sym
17
+ when :notes then link_notes(args, output)
18
+ else
19
+ raise "Noun not implemented"
20
+ end
21
+ end
22
+ else
23
+ raise Errors:COMMAND_NOT_FOUND
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def link_notes(args, output, needs_assign=false)
31
+ prompt = TTY::Prompt.new
32
+
33
+ project = if args.last.start_with?('+')
34
+ # args.last
35
+ # if documents.working_directory.is_linked?
36
+ # documents.working_directory.project
37
+ # else
38
+ # end
39
+ raise "Good idea and should work but not implemented properly, sorry"
40
+ else
41
+ # TODO: need to test if working_directory is documents_dir
42
+ #
43
+ if documents.working_directory.is_linked?
44
+ documents.working_directory.project
45
+ else
46
+ needs_assign = true
47
+ p_name = prompt.select('assign directory to project:', documents.projects.all_tokens)
48
+ p_id = prompt.ask('id for this directory:', default: generate_id)
49
+ p_name
50
+ end
51
+ end
52
+
53
+ if needs_assign
54
+ c_id = documents.inventory.local_computer_id
55
+ documents.projects.add_directory!(documents.working_directory.path, p_name, p_id, c_id)
56
+ end
57
+
58
+ project_ref = project.sub('+', '')
59
+
60
+ # Symlink done using maetl local notes convention, this could be improved
61
+ # and made more flexible. Would also be good to delegate this outside
62
+ # of the UI routine link_notes()
63
+ target_path = File.join(Env.documents_dir, project.sub('+', ''), 'notes.md')
64
+
65
+ if File.exist?(target_path)
66
+ # TODO: use directory instance given by input filtering so that
67
+ # operations can work on both working dir and a path provided in the UI
68
+ symbolic_path = File.join(documents.working_directory.path, 'NOTES.md')
69
+ File.symlink(target_path, symbolic_path)
70
+
71
+ # ignore_path = File.join(documents.working_directory.path, '.gitignore')
72
+ # if File.exist?(ignore_path)
73
+ # unless File.read(ignore_path).to_s.include?('NOTES.md')
74
+ # File.write(ignore_path, "NOTES.md\n", mode: 'a+')
75
+ # end
76
+ # end
77
+ else
78
+ output.puts "#{project} does not have notes"
79
+ end
80
+
81
+ # output.puts Dir.pwd
82
+ # output.puts ::Intent::Env.documents_dir
83
+ # output.puts ::Intent::Env.computer_serial
84
+ # Check if current working directory is a linked directory
85
+ #item = documents.projects.linked_directory(Dir.pwd)
86
+ #output.puts item
87
+ #File.symlink("DOCUMENT_DIR/project-name/notes.md", "Projects/project-name/NOTES.md")
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,5 +1,3 @@
1
- require 'readline'
2
-
3
1
  module Intent
4
2
  module Commands
5
3
  class Projects < Base
@@ -14,8 +12,10 @@ module Intent
14
12
  documents.projects.all.each do |task|
15
13
  output.puts task.highlight_as_project
16
14
  end
17
- when :add
18
- add_project(args, output)
15
+ when :add then add_project(args, output)
16
+ when :sync then sync_project(args, output)
17
+ else
18
+ raise Errors:COMMAND_NOT_FOUND
19
19
  end
20
20
  end
21
21
  end
@@ -29,6 +29,11 @@ module Intent
29
29
  name = "+#{name}" unless name.start_with?('+')
30
30
  output.puts name
31
31
  end
32
+
33
+ def sync_project(args, output)
34
+ result = documents.projects.sync!
35
+ output.puts "Sync projects result: #{result}"
36
+ end
32
37
  end
33
38
  end
34
39
  end
@@ -3,7 +3,7 @@ require 'intent/commands/errors'
3
3
  require 'intent/commands/intent'
4
4
  require 'intent/commands/todo'
5
5
  require 'intent/commands/projects'
6
- #require 'intent/commands/project'
6
+ require 'intent/commands/project'
7
7
  #require 'intent/commands/ideas'
8
8
  #require 'intent/commands/idea'
9
9
  require 'intent/commands/inventory'
@@ -0,0 +1,37 @@
1
+ module Intent
2
+ module Core
3
+ class Directory
4
+ attr_reader :path
5
+
6
+ def initialize(path, projects)
7
+ @path = path
8
+ @ledger = projects
9
+ @record = projects.all.find { |d| d.tags[:is] == 'directory' && d.text == @path }
10
+ end
11
+
12
+ def project
13
+ record.projects.first
14
+ end
15
+
16
+ def is_linked?
17
+ !record.nil? && record.projects.any?
18
+ end
19
+
20
+ def assign!(project)
21
+ if record.nil?
22
+ @record = Record.new("#{Date.today} #{@path} is:directory type:#{type} sku:#{sku}")
23
+ ledger.append(record)
24
+ else
25
+ record.projects << project
26
+ end
27
+
28
+ ledger.save!
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :ledger
34
+ attr_reader :record
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module Intent
2
+ module Core
3
+ class Documents
4
+ attr_reader :projects
5
+ attr_reader :inventory
6
+ attr_reader :inbox
7
+ attr_reader :working_directory
8
+
9
+ def initialize
10
+ @projects = Projects.new("#{Intent::Env.documents_dir}/projects.txt")
11
+ @inventory = Inventory.new("#{Intent::Env.documents_dir}/inventory.txt")
12
+ @inbox = Inbox.new("#{Intent::Env.documents_dir}/todo.txt")
13
+ @working_directory = Directory.new(Dir.pwd, @projects)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ module Intent
2
+ module Core
3
+ class Inbox
4
+ attr_reader :list
5
+
6
+ def initialize(db_path)
7
+ @list = List.new(db_path)
8
+ end
9
+
10
+ def all
11
+ @list.by_not_done
12
+ end
13
+
14
+ def focused
15
+ @list.by_context('@focus').by_not_done
16
+ end
17
+
18
+ def focused_projects
19
+ focused.map { |t| t.projects }.flatten.uniq
20
+ end
21
+
22
+ def add_line!(line)
23
+ record = Record.new("#{Date.today} #{line}")
24
+ @list.prepend(record)
25
+ @list.save!
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,101 @@
1
+ module Intent
2
+ module Core
3
+ class Inventory
4
+ attr_reader :list
5
+ attr_reader :ledger_path
6
+
7
+ def initialize(db_path)
8
+ @ledger_path = db_path
9
+ @list = List.new(db_path)
10
+ end
11
+
12
+ def all
13
+ list.by_not_done
14
+ end
15
+
16
+ def folder_by_id(id)
17
+ all.find { |i| i.tags[:is] == 'folder' && i.tags[:id] == id }
18
+ end
19
+
20
+ def folders
21
+ all.filter { |i| i.tags[:is] == 'folder' }
22
+ end
23
+
24
+ def items_in(id)
25
+ all.filter { |i| i.tags[:in] == id }
26
+ end
27
+
28
+ def unassigned_folders
29
+ all.filter { |i| i.tags[:is] == 'folder' && i.projects.empty? }
30
+ end
31
+
32
+ def assigned_folders
33
+ all.filter { |i| i.tags[:is] == 'folder' && i.projects.any? }
34
+ end
35
+
36
+ def boxes
37
+ all.filter { |i| i.tags[:is] == 'box' }
38
+ end
39
+
40
+ def unassigned_boxes
41
+ all.filter { |i| i.tags[:is] == 'box' && i.projects.empty? }
42
+ end
43
+
44
+ def assigned_boxes
45
+ all.filter { |i| i.tags[:is] == 'box' && i.projects.any? }
46
+ end
47
+
48
+ def units_of(noun)
49
+ all.filter { |i| i.tags[:is] == 'unit' && i.tags[:type] == noun.to_s }
50
+ end
51
+
52
+ def local_computer_id
53
+ all.find { |i| i.tags[:is] == 'computer' && i.tags[:serial] == Env.computer_serial }.tags[:id]
54
+ end
55
+
56
+ def add_unit!(description, type, sku)
57
+ record = Record.new("#{Date.today} #{description} is:unit type:#{type} sku:#{sku}")
58
+ @list.append(record)
59
+ @list.save!
60
+ end
61
+
62
+ def add_item!(description, id, type, sku, box=nil)
63
+ description << " in:#{box}" unless box.nil?
64
+ record = Record.new("#{Date.today} #{description} id:#{id} is:#{type} sku:#{sku}")
65
+ @list.append(record)
66
+ @list.save!
67
+ end
68
+
69
+ def add_folder!(description, id, sku, box=nil)
70
+ add_item!(description, id, :folder, sku, box)
71
+ end
72
+
73
+ def add_box!(description, id, sku)
74
+ add_item!(description, id, :box, sku)
75
+ end
76
+
77
+ def save!
78
+ @list.save!
79
+ end
80
+
81
+ def sync!
82
+ ledger_file = File.basename(ledger_path)
83
+
84
+ if repo.status.changed?(ledger_file)
85
+ repo.add(ledger_file)
86
+ repo.commit("Synchronizing inventory [#{Time.new}]")
87
+ repo.push
88
+ true # Result:OK
89
+ else
90
+ false # Result::NO_CHANGES
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def repo
97
+ @repo ||= Git.open(Env.documents_dir, :log => Logger.new(STDERR, level: Logger::INFO))
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,58 @@
1
+ module Intent
2
+ module Core
3
+ class Projects
4
+ attr_reader :list
5
+ attr_reader :ledger_path
6
+
7
+ def initialize(db_path)
8
+ @ledger_path = db_path
9
+ @list = List.new(db_path)
10
+ end
11
+
12
+ def all
13
+ list.by_not_done
14
+ end
15
+
16
+ def all_tokens
17
+ all.map { |item| item.projects.first }.uniq
18
+ end
19
+
20
+ def linked_directory(path)
21
+ all.find { |item| item.text == path && ['repository', 'directory'].include?(item.tags[:is]) }
22
+ end
23
+
24
+ def sync!
25
+ ledger_file = File.basename(ledger_path)
26
+
27
+ if repo.status.changed?(ledger_file)
28
+ repo.add(ledger_file)
29
+ repo.commit("Synchronizing projects [#{Time.new}]")
30
+ repo.push
31
+ true # Result:OK
32
+ else
33
+ false # Result::NO_CHANGES
34
+ end
35
+ end
36
+
37
+ def add_directory!(path, project, id, computer)
38
+ record = Record.new([
39
+ Date.today,
40
+ path,
41
+ project,
42
+ "is:directory",
43
+ "id:#{id}",
44
+ "computer:#{computer}"
45
+ ].join(' '))
46
+
47
+ @list.append(record)
48
+ @list.save!
49
+ end
50
+
51
+ private
52
+
53
+ def repo
54
+ @repo ||= Git.open(Env.documents_dir, :log => Logger.new(STDERR, level: Logger::INFO))
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/intent/core.rb CHANGED
@@ -1,25 +1,25 @@
1
1
  module Intent
2
- module Env
3
- def self.documents_dir
4
- File.expand_path(ENV['INTENT_DOCUMENTS_DIR'] || "").to_s
5
- end
2
+ module Core
3
+ List = ::Todo::List
4
+ Record = ::Todo::Task
6
5
 
7
- def self.inbox_dir
8
- ENV['INTENT_INBOX_DIR']
9
- end
6
+ VERBS = [:add, :assign, :list, :link, :sync]
10
7
 
11
- def self.assets_dir
12
- ENV['INTENT_ARCHIVE_DIR']
13
- end
8
+ NOUNS = {
9
+ inventory: [:unit, :box, :folder, :computer],
10
+ projects: [:project, :directory, :repository],
11
+ todo: [:task]
12
+ }
13
+
14
+ class Action
15
+ attr_reader :verb
16
+ attr_reader :noun
14
17
 
15
- def self.projects_dir
16
- ENV['INTENT_PROJECTS_DIR']
18
+ def initialize(verb_sym, noun_r)
19
+ @verb = Verbs.instance_for(verb_sym)
20
+ @noun = Noun.new(noun_r.type, noun_r.label, noun_r.tags)
21
+ end
17
22
  end
18
- end
19
-
20
- module Core
21
- List = ::Todo::List
22
- Record = ::Todo::Task
23
23
 
24
24
  class Noun
25
25
  def initialize(type, label, tags)
@@ -35,151 +35,11 @@ module Intent
35
35
  p tags
36
36
  end
37
37
  end
38
-
39
- class Projects
40
- attr_reader :list
41
-
42
- def initialize(db_path)
43
- @list = List.new(db_path)
44
- end
45
-
46
- def all
47
- list.by_not_done
48
- end
49
-
50
- def all_tokens
51
- all.map { |project| project.projects.first }
52
- end
53
- end
54
-
55
- class Inventory
56
- attr_reader :list
57
-
58
- def initialize(db_path)
59
- @list = List.new(db_path)
60
- end
61
-
62
- def all
63
- list.by_not_done
64
- end
65
-
66
- def folder_by_id(id)
67
- all.find { |i| i.tags[:is] == 'folder' && i.tags[:id] == id }
68
- end
69
-
70
- def folders
71
- all.filter { |i| i.tags[:is] == 'folder' }
72
- end
73
-
74
- def items_in(id)
75
- all.filter { |i| i.tags[:in] == id }
76
- end
77
-
78
- def unassigned_folders
79
- all.filter { |i| i.tags[:is] == 'folder' && i.projects.empty? }
80
- end
81
-
82
- def assigned_folders
83
- all.filter { |i| i.tags[:is] == 'folder' && i.projects.any? }
84
- end
85
-
86
- def boxes
87
- all.filter { |i| i.tags[:is] == 'box' }
88
- end
89
-
90
- def unassigned_boxes
91
- all.filter { |i| i.tags[:is] == 'box' && i.projects.empty? }
92
- end
93
-
94
- def assigned_boxes
95
- all.filter { |i| i.tags[:is] == 'box' && i.projects.any? }
96
- end
97
-
98
- def units_of(noun)
99
- all.filter { |i| i.tags[:is] == 'unit' && i.tags[:type] == noun.to_s }
100
- end
101
-
102
- def add_unit!(description, type, sku)
103
- record = Record.new("#{Date.today} #{description} is:unit type:#{type} sku:#{sku}")
104
- @list.append(record)
105
- @list.save!
106
- end
107
-
108
- def add_item!(description, id, type, sku, box=nil)
109
- description << " in:#{box}" unless box.nil?
110
- record = Record.new("#{Date.today} #{description} id:#{id} is:#{type} sku:#{sku}")
111
- @list.append(record)
112
- @list.save!
113
- end
114
-
115
- def add_folder!(description, id, sku, box=nil)
116
- add_item!(description, id, :folder, sku, box)
117
- end
118
-
119
- def add_box!(description, id, sku)
120
- add_item!(description, id, :box, sku)
121
- end
122
-
123
- def save!
124
- @list.save!
125
- end
126
- end
127
-
128
- class Inbox
129
- attr_reader :list
130
-
131
- def initialize(db_path)
132
- @list = List.new(db_path)
133
- end
134
-
135
- def all
136
- @list.by_not_done
137
- end
138
-
139
- def focused
140
- @list.by_context('@focus').by_not_done
141
- end
142
-
143
- def focused_projects
144
- focused.map { |t| t.projects }.flatten.uniq
145
- end
146
-
147
- def add_line!(line)
148
- record = Record.new("#{Date.today} #{line}")
149
- @list.prepend(record)
150
- @list.save!
151
- end
152
- end
153
-
154
- class Documents
155
- attr_reader :projects
156
- attr_reader :inventory
157
- attr_reader :inbox
158
-
159
- def initialize
160
- @projects = Projects.new("#{Intent::Env.documents_dir}/projects.txt")
161
- @inventory = Inventory.new("#{Intent::Env.documents_dir}/inventory.txt")
162
- @inbox = Inbox.new("#{Intent::Env.documents_dir}/todo.txt")
163
- end
164
- end
165
- end
166
-
167
- class Dispatcher
168
- def self.exec_command(command, args, output=STDOUT)
169
- command = init_command(command).new
170
- command.run(args, output)
171
- end
172
-
173
- def self.init_command(command)
174
- case command
175
- when :intent then return Commands::Intent
176
- when :inventory then return Commands::Inventory
177
- when :projects then return Commands::Projects
178
- when :project then return Commands::Project
179
- when :todo then return Commands::Todo
180
- else
181
- raise Commands::Errors::COMMAND_NOT_FOUND
182
- end
183
- end
184
38
  end
185
39
  end
40
+
41
+ require 'intent/core/projects'
42
+ require 'intent/core/inventory'
43
+ require 'intent/core/inbox'
44
+ require 'intent/core/directory'
45
+ require 'intent/core/documents'
@@ -1,3 +1,5 @@
1
- require 'pathname'
2
-
3
- require 'intent/desktop/commands'
1
+ require 'intent/verbs/add'
2
+ require 'intent/verbs/assign'
3
+ require 'intent/verbs/link'
4
+ require 'intent/verbs/list'
5
+ require 'intent/verbs/sync'
@@ -0,0 +1,20 @@
1
+ module Intent
2
+ class Dispatcher
3
+ def self.exec_command(command, args, output=STDOUT)
4
+ command = init_command(command).new
5
+ command.run(args, output)
6
+ end
7
+
8
+ def self.init_command(command)
9
+ case command
10
+ when :intent then return Commands::Intent
11
+ when :inventory then return Commands::Inventory
12
+ when :projects then return Commands::Projects
13
+ when :project then return Commands::Project
14
+ when :todo then return Commands::Todo
15
+ else
16
+ raise Commands::Errors::COMMAND_NOT_FOUND
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/intent/env.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Intent
2
+ module Env
3
+ def self.documents_dir
4
+ File.expand_path(ENV['INTENT_DOCUMENTS_DIR'] || "").to_s
5
+ end
6
+
7
+ def self.inbox_dir
8
+ ENV['INTENT_INBOX_DIR']
9
+ end
10
+
11
+ def self.assets_dir
12
+ ENV['INTENT_ARCHIVE_DIR']
13
+ end
14
+
15
+ def self.projects_dir
16
+ ENV['INTENT_PROJECTS_DIR']
17
+ end
18
+
19
+ def self.computer_serial
20
+ # macOS: `system_profiler SPHardwareDataType`
21
+ # Win: `wmic bios get serialnumber`
22
+ # Linux: `ls /sys/devices/virtual/dmi/id`
23
+ ENV['INTENT_COMPUTER_SERIAL']
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,82 @@
1
+ ====================================================================
2
+ Intent . Havin a blast on the command line
3
+ ====================================================================
4
+
5
+ Welcome to the only task manager you will (n)ever need.
6
+
7
+ These docs are not written for a wide audience, but here’s the
8
+ essentials:
9
+
10
+ Verbs
11
+ -----
12
+
13
+ ### `add [noun]`
14
+
15
+ Adds [noun] to the ledger denoted by the given command.
16
+
17
+ ```
18
+ projects add
19
+ projects add project
20
+ projects add directory
21
+ projects add repository
22
+
23
+ project add
24
+
25
+ inventory add
26
+ inventory add folder
27
+ inventory add box
28
+ inventory add unit
29
+ inventory add computer
30
+
31
+ todo add
32
+
33
+ inbox add
34
+ ```
35
+
36
+ ### `assign [noun]`
37
+
38
+ Assigns projects, contexts, tags and associations to ap.
39
+
40
+ ```
41
+ projects assign
42
+
43
+ project assign
44
+
45
+ inventory assign
46
+ ```
47
+
48
+ ### `list [noun]`
49
+
50
+ Lists elements in the ledger.
51
+
52
+ ```
53
+ projects list
54
+
55
+ project list
56
+
57
+ inventory list
58
+
59
+ todo list
60
+
61
+ inbox list
62
+ ```
63
+
64
+ ### `link [noun]`
65
+
66
+ Links elements from a local directory to an assigned project.
67
+
68
+ ```
69
+ project link
70
+ ```
71
+
72
+ ### `sync [noun]`
73
+
74
+ Synchronises changes to the Git origin.
75
+
76
+ ```
77
+ projects sync
78
+
79
+ inventory sync
80
+ ```
81
+
82
+ Documentation is patchy and not always up to date.
@@ -1,3 +1,3 @@
1
1
  module Intent
2
- VERSION = '0.7.1'
2
+ VERSION = '0.8.0'
3
3
  end
data/lib/intent.rb CHANGED
@@ -1,23 +1,37 @@
1
1
  #require 'random'
2
- require 'todo-txt'
2
+ #require 'pathname'
3
+
4
+ # Pastel still required but deprecated
3
5
  require 'pastel'
4
6
  require 'paint'
7
+
8
+ # CLI UI tools
5
9
  require 'tty-prompt'
6
10
  require 'tty-table'
7
11
  require 'tty-tree'
12
+
13
+ # Identifiers
8
14
  require 'nanoid'
15
+ #require 'calyx'
16
+
17
+ # Interact with git repos
18
+ require 'logger'
19
+ require 'git'
20
+
21
+ # todo.txt data structure support
22
+ require 'todo-txt'
9
23
  require 'gem_ext/todo-txt'
10
24
 
11
25
  Todo.customize do |options|
12
26
  options.require_completed_on = false
13
27
  end
14
28
 
29
+ # Intent library
15
30
  require 'intent/version'
31
+ require 'intent/env'
32
+ require 'intent/args'
16
33
  require 'intent/core'
34
+ #require 'intent/verbs'
17
35
  require 'intent/commands'
18
36
  require 'intent/ui/term_color'
19
- # require 'intent/todo'
20
- # require 'intent/review'
21
- # require 'intent/projects'
22
- # require 'intent/desktop'
23
-
37
+ require 'intent/dispatcher'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rickerby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-16 00:00:00.000000000 Z
11
+ date: 2024-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: todo-txt
@@ -268,9 +268,9 @@ email:
268
268
  executables:
269
269
  - intent
270
270
  - inventory
271
+ - project
271
272
  - project_doc
272
273
  - projects
273
- - projects_active
274
274
  - todo
275
275
  - todo_review
276
276
  extensions: []
@@ -283,30 +283,41 @@ files:
283
283
  - Rakefile
284
284
  - bin/intent
285
285
  - bin/inventory
286
+ - bin/project
286
287
  - bin/project_doc
287
288
  - bin/projects
288
- - bin/projects_active
289
289
  - bin/todo
290
290
  - bin/todo_review
291
291
  - intent.gemspec
292
292
  - lib/gem_ext/todo-txt.rb
293
293
  - lib/intent.rb
294
+ - lib/intent/args.rb
294
295
  - lib/intent/commands.rb
295
296
  - lib/intent/commands/base.rb
296
297
  - lib/intent/commands/errors.rb
297
298
  - lib/intent/commands/intent.rb
298
299
  - lib/intent/commands/inventory.rb
300
+ - lib/intent/commands/project.rb
299
301
  - lib/intent/commands/projects.rb
300
302
  - lib/intent/commands/todo.rb
301
303
  - lib/intent/core.rb
304
+ - lib/intent/core/directory.rb
305
+ - lib/intent/core/documents.rb
306
+ - lib/intent/core/inbox.rb
307
+ - lib/intent/core/inventory.rb
308
+ - lib/intent/core/projects.rb
302
309
  - lib/intent/desktop.rb
310
+ - lib/intent/dispatcher.rb
311
+ - lib/intent/env.rb
303
312
  - lib/intent/projects.rb
304
313
  - lib/intent/review.rb
314
+ - lib/intent/text/intent.help.txt
305
315
  - lib/intent/text/inventory.help.txt
306
316
  - lib/intent/text/project.help.txt
307
317
  - lib/intent/text/projects.help.txt
308
318
  - lib/intent/text/todo.help.txt
309
319
  - lib/intent/todo.rb
320
+ - lib/intent/ui/projects_active.rb
310
321
  - lib/intent/ui/term_color.rb
311
322
  - lib/intent/ui/ttyui.rb
312
323
  - lib/intent/verbs/add.rb