intent 0.6.0 → 0.7.0
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/.gitignore +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +23 -0
- data/bin/{review → intent} +1 -2
- data/bin/inventory +12 -0
- data/bin/projects +1 -1
- data/bin/todo +1 -1
- data/intent.gemspec +10 -1
- data/lib/gem_ext/todo-txt.rb +26 -2
- data/lib/intent/commands/base.rb +40 -0
- data/lib/intent/commands/errors.rb +7 -0
- data/lib/intent/commands/intent.rb +9 -0
- data/lib/intent/commands/inventory.rb +174 -0
- data/lib/intent/commands/projects.rb +34 -0
- data/lib/intent/commands/todo.rb +51 -0
- data/lib/intent/commands.rb +9 -0
- data/lib/intent/core.rb +184 -0
- data/lib/intent/desktop.rb +3 -0
- data/lib/intent/projects.rb +1 -1
- data/lib/intent/review.rb +10 -1
- data/lib/intent/text/inventory.help.txt +6 -0
- data/lib/intent/text/project.help.txt +7 -0
- data/lib/intent/text/projects.help.txt +9 -0
- data/lib/intent/text/todo.help.txt +15 -0
- data/lib/intent/todo.rb +3 -1
- data/lib/intent/verbs/add.rb +21 -0
- data/lib/intent/verbs/cite.rb +14 -0
- data/lib/intent/verbs/install.rb +20 -0
- data/lib/intent/verbs/review.rb +131 -0
- data/lib/intent/{todo/manager.rb → verbs/todo.rb} +3 -16
- data/lib/intent/version.rb +1 -1
- data/lib/intent.rb +20 -3
- metadata +155 -12
- data/.travis.yml +0 -4
- data/lib/intent/projects/manager.rb +0 -20
- data/lib/intent/review/manager.rb +0 -17
- /data/lib/intent/{projects → verbs}/status.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a80e9d9082642b1f2325b40629ff95ffb096cdba644d0f2d5aa2af25541c2d2b
|
4
|
+
data.tar.gz: 90ed06f5afbf84636fbeb70e6fab66a4868dc0d485b751178b2ff31568315237
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4a23b8d4882af953e2d330c26388c91bb86513c1881192952998f6f74b5f49b682f4b609566ea18b0b6f0ad7517020ac15ccc22ce8756edc001ac5fc25c455b
|
7
|
+
data.tar.gz: cfc14324613fc505a6ec0a591e73f667dd3360b4ec1d8ee7f05d86813fcbaf5e645f12b917579adc6b046223dbc251f665f65b0cd70087dac39d59cc7adfdccf
|
data/.gitignore
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2016 Mark Rickerby
|
3
|
+
Copyright (c) 2016-2024 Mark Rickerby <https://maetl.net>
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Intent
|
2
|
+
|
3
|
+
Automation engine with todo.txt
|
4
|
+
|
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
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install intent
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
```
|
16
|
+
intent help
|
17
|
+
```
|
18
|
+
|
19
|
+
## Copyright & License
|
20
|
+
|
21
|
+
Copyright 2024 Mark Rickerby <https://maetl.net>.
|
22
|
+
|
23
|
+
All documentation and modelling concepts are **CC BY-NC**. Source code and command line tools are MIT.
|
data/bin/{review → intent}
RENAMED
@@ -1,5 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
2
|
path = __FILE__
|
4
3
|
while File.symlink?(path)
|
5
4
|
path = File.expand_path(File.readlink(path), File.dirname(path))
|
@@ -8,4 +7,4 @@ $:.unshift(File.join(File.dirname(File.expand_path(path)), '..', 'lib'))
|
|
8
7
|
|
9
8
|
require 'intent'
|
10
9
|
|
11
|
-
Intent::
|
10
|
+
Intent::Dispatcher.exec_command(:intent, ARGV.dup)
|
data/bin/inventory
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
path = __FILE__
|
3
|
+
|
4
|
+
while File.symlink?(path)
|
5
|
+
path = File.expand_path(File.readlink(path), File.dirname(path))
|
6
|
+
end
|
7
|
+
|
8
|
+
$:.unshift(File.join(File.dirname(File.expand_path(path)), '..', 'lib'))
|
9
|
+
|
10
|
+
require 'intent'
|
11
|
+
|
12
|
+
Intent::Dispatcher.exec_command(:inventory, ARGV.dup)
|
data/bin/projects
CHANGED
data/bin/todo
CHANGED
data/intent.gemspec
CHANGED
@@ -20,9 +20,18 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "todo-txt", "~> 0.12"
|
22
22
|
spec.add_runtime_dependency "pastel", "~> 0.8"
|
23
|
-
spec.add_runtime_dependency "git", "~> 1.
|
23
|
+
spec.add_runtime_dependency "git", "~> 1.19.1"
|
24
24
|
spec.add_runtime_dependency "terminal-notifier", "~> 2.0"
|
25
25
|
spec.add_runtime_dependency "ghost", "~> 1.0.0"
|
26
|
+
spec.add_runtime_dependency "unicode_plot", "0.0.5"
|
27
|
+
spec.add_runtime_dependency "kdl", "1.0.3"
|
28
|
+
spec.add_runtime_dependency "sorted_set", "1.0.3"
|
29
|
+
spec.add_runtime_dependency "strings-ansi", "0.2.0"
|
30
|
+
spec.add_runtime_dependency "bibtex-ruby", "6.1.0"
|
31
|
+
spec.add_runtime_dependency "tty-prompt", "~> 0.23.1"
|
32
|
+
spec.add_runtime_dependency "tty-table", "~> 0.12.0"
|
33
|
+
spec.add_runtime_dependency "tty-tree", "~> 0.4.0"
|
34
|
+
spec.add_runtime_dependency "nanoid", "~> 2.0.0"
|
26
35
|
|
27
36
|
spec.add_development_dependency "bundler"
|
28
37
|
spec.add_development_dependency "rake"
|
data/lib/gem_ext/todo-txt.rb
CHANGED
@@ -10,13 +10,37 @@ class Todo::Task
|
|
10
10
|
# Completed tasks are rendered with a strikethrough
|
11
11
|
pastel.strikethrough(to_s)
|
12
12
|
else
|
13
|
-
|
14
|
-
|
13
|
+
[
|
14
|
+
pastel.red(print_priority),
|
15
|
+
pastel.yellow(created_on.to_s),
|
16
|
+
text,
|
17
|
+
pastel.bold.magenta(print_contexts),
|
18
|
+
pastel.bold.blue(print_projects),
|
19
|
+
pastel.bold.cyan(print_tags)
|
20
|
+
].reject { |item| !item || item.nil? || item.empty? }.join(' ')
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
24
|
+
def highlight_as_project
|
25
|
+
return to_s unless STDOUT.tty?
|
26
|
+
|
27
|
+
pastel = Pastel.new
|
28
|
+
[
|
29
|
+
pastel.bold.cyan(print_projects),
|
30
|
+
pastel.red(print_project_context)
|
31
|
+
].reject { |item| !item || item.nil? || item.empty? }.join(' ')
|
32
|
+
end
|
33
|
+
|
34
|
+
def text=(label)
|
35
|
+
@text = label
|
36
|
+
end
|
37
|
+
|
18
38
|
private
|
19
39
|
|
40
|
+
def print_project_context
|
41
|
+
'active' if contexts.include?('@active')
|
42
|
+
end
|
43
|
+
|
20
44
|
def print_open_task(pastel)
|
21
45
|
[
|
22
46
|
pastel.red(print_priority),
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Intent
|
2
|
+
module Commands
|
3
|
+
class Base
|
4
|
+
attr_reader :identity
|
5
|
+
attr_reader :documents
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@identity = strip_classname
|
9
|
+
@documents = ::Intent::Core::Documents.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_help(output)
|
13
|
+
output.puts(File.read(help_txt_path))
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_id
|
17
|
+
Nanoid.generate(size: 8, alphabet: ID_ALPHABET)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
T_CLASS_PREFIX = 'Intent::Commands::'
|
23
|
+
|
24
|
+
ID_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
25
|
+
|
26
|
+
def strip_classname
|
27
|
+
self.class.to_s.sub(T_CLASS_PREFIX, '').downcase
|
28
|
+
end
|
29
|
+
|
30
|
+
def help_txt_path
|
31
|
+
# TODO: does this work on Windows?
|
32
|
+
"#{__dir__}/../text/#{identity}.help.txt"
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_noun(type, label, tags)
|
36
|
+
Intent::Core::Noun.new(type, label, tags)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'tty-reader'
|
2
|
+
|
3
|
+
module Intent
|
4
|
+
module Commands
|
5
|
+
class Inventory < Base
|
6
|
+
def run(args, output)
|
7
|
+
if args.empty?
|
8
|
+
print_help(output)
|
9
|
+
else
|
10
|
+
case args.first.to_sym
|
11
|
+
when :help
|
12
|
+
print_help(output)
|
13
|
+
when :list
|
14
|
+
tree = TTY::Tree.new(inventory_tree)
|
15
|
+
output.puts(tree.render)
|
16
|
+
when :add
|
17
|
+
noun = args[1].to_sym
|
18
|
+
case noun
|
19
|
+
when :folder then add_folder(args, output)
|
20
|
+
when :box then add_box(args, output)
|
21
|
+
when :stock then add_stock(args, output)
|
22
|
+
else
|
23
|
+
raise "Noun not found"
|
24
|
+
end
|
25
|
+
when :assign
|
26
|
+
noun = args[1].to_sym
|
27
|
+
case noun
|
28
|
+
when :folder then assign_folder(args, output)
|
29
|
+
when :box then assign_box(args, output)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def inventory_tree
|
38
|
+
pastel = Pastel.new
|
39
|
+
root = {}
|
40
|
+
documents.inventory.boxes.each do |box|
|
41
|
+
color_code = case box.tags[:id][0].downcase.to_sym
|
42
|
+
when :g then :green
|
43
|
+
when :y then :yellow
|
44
|
+
when :b then :blue
|
45
|
+
when :r then :red
|
46
|
+
else
|
47
|
+
:white
|
48
|
+
end
|
49
|
+
box_key = "#{pastel.decorate(box.tags[:id], :bold, color_code)} #{box.text}"
|
50
|
+
child_items = documents.inventory.items_in(box.tags[:id]).map do |item|
|
51
|
+
"#{pastel.decorate(item.tags[:id], :bold, color_code)} #{item.text}"
|
52
|
+
end
|
53
|
+
root[box_key] = child_items
|
54
|
+
end
|
55
|
+
root
|
56
|
+
end
|
57
|
+
|
58
|
+
def inventory_units_of(type)
|
59
|
+
documents.inventory.units_of(type).map do |unit|
|
60
|
+
[unit.text, unit.tags[:sku]]
|
61
|
+
end.to_h
|
62
|
+
end
|
63
|
+
|
64
|
+
def inventory_unassigned_folders
|
65
|
+
folder_types = documents.inventory.units_of(:folder)
|
66
|
+
documents.inventory.unassigned_folders.map do |folder|
|
67
|
+
unit_label = folder_types.find { |f| f.tags[:sku] == folder.tags[:sku] }
|
68
|
+
["#{folder.text} #{folder.tags[:id]} (#{unit_label.text})", folder.tags[:id]]
|
69
|
+
end.to_h
|
70
|
+
end
|
71
|
+
|
72
|
+
def inventory_unassigned_boxes
|
73
|
+
box_types = documents.inventory.units_of(:box)
|
74
|
+
documents.inventory.unassigned_boxes.map do |box|
|
75
|
+
unit_label = box_types.find { |f| f.tags[:sku] == box.tags[:sku] }
|
76
|
+
["#{box.text} #{box.tags[:id]} (#{unit_label.text})", box.tags[:id]]
|
77
|
+
end.to_h
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_stock(args, output)
|
81
|
+
prompt = TTY::Prompt.new
|
82
|
+
type = prompt.select('type of stock:', [:folder, :box])
|
83
|
+
ref = self
|
84
|
+
|
85
|
+
unit = prompt.collect do
|
86
|
+
key(:sku).ask('sku:', default: ref.generate_id)
|
87
|
+
key(:label).ask('label:', default: "[Undocumented #{type.capitalize}]")
|
88
|
+
key(:qty).ask('quantity:', default: 1, convert: :int)
|
89
|
+
end
|
90
|
+
|
91
|
+
documents.inventory.add_unit!(unit[:label], type, unit[:sku])
|
92
|
+
|
93
|
+
unit[:qty].times do
|
94
|
+
label = "[Unlabelled #{type.capitalize}]"
|
95
|
+
documents.inventory.add_item!(label, ref.generate_id, type, unit[:sku])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_folder(args, output)
|
100
|
+
skus = inventory_units_of(:folder)
|
101
|
+
prompt = TTY::Prompt.new
|
102
|
+
ref = self
|
103
|
+
|
104
|
+
item = prompt.collect do
|
105
|
+
key(:sku).select('sku:', skus, filter: true)
|
106
|
+
key(:id).ask('id:', default: ref.generate_id)
|
107
|
+
key(:label).ask('label:', default: '[Unlabelled Folder]')
|
108
|
+
key(:active).yes?('is active:')
|
109
|
+
end
|
110
|
+
|
111
|
+
label = item[:active] ? "#{item[:label]} @active" : item[:label]
|
112
|
+
|
113
|
+
documents.inventory.add_folder!(label, item[:id], item[:sku])
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_box(args, output)
|
117
|
+
skus = inventory_units_of(:box)
|
118
|
+
prompt = TTY::Prompt.new
|
119
|
+
ref = self
|
120
|
+
|
121
|
+
item = prompt.collect do
|
122
|
+
key(:sku).select('sku:', skus, filter: true)
|
123
|
+
key(:id).ask('id:', default: ref.generate_id)
|
124
|
+
key(:label).ask('label:', default: '[Unlabelled Box]')
|
125
|
+
end
|
126
|
+
|
127
|
+
# Repository write pattern
|
128
|
+
documents.inventory.add_box!(label, item[:id], item[:sku])
|
129
|
+
|
130
|
+
# Alternative design
|
131
|
+
# noun = create_noun(:box, label, tags)
|
132
|
+
# Add.invoke(:append, documents.inventory, noun)
|
133
|
+
end
|
134
|
+
|
135
|
+
def assign_folder(args, output)
|
136
|
+
projects = documents.projects.all_tokens
|
137
|
+
folders = inventory_unassigned_folders
|
138
|
+
prompt = TTY::Prompt.new
|
139
|
+
|
140
|
+
folder_id = prompt.select('folder:', folders)
|
141
|
+
folder = documents.inventory.folder_by_id(folder_id)
|
142
|
+
|
143
|
+
details = prompt.collect do
|
144
|
+
key(:projects).multi_select('projects:', projects)
|
145
|
+
key(:label).ask('label:', default: folder.text)
|
146
|
+
# TODO: is active
|
147
|
+
end
|
148
|
+
|
149
|
+
folder.text = details[:label]
|
150
|
+
folder.projects.concat(details[:projects])
|
151
|
+
documents.inventory.save!
|
152
|
+
end
|
153
|
+
|
154
|
+
def assign_box(args, output)
|
155
|
+
projects = documents.projects.all_tokens
|
156
|
+
boxes = inventory_unassigned_boxes
|
157
|
+
prompt = TTY::Prompt.new
|
158
|
+
|
159
|
+
box_id = prompt.select('box:', boxes)
|
160
|
+
box = documents.inventory.box_by_id(box_id)
|
161
|
+
|
162
|
+
details = prompt.collect do
|
163
|
+
key(:projects).multi_select('projects:', projects)
|
164
|
+
key(:label).ask('label:', default: box.text)
|
165
|
+
# TODO: is active
|
166
|
+
end
|
167
|
+
|
168
|
+
box.text = details[:label]
|
169
|
+
box.projects.concat(details[:projects])
|
170
|
+
documents.inventory.save!
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'readline'
|
2
|
+
|
3
|
+
module Intent
|
4
|
+
module Commands
|
5
|
+
class Projects < Base
|
6
|
+
def run(args, output)
|
7
|
+
if args.empty?
|
8
|
+
print_help(output)
|
9
|
+
else
|
10
|
+
case args.first.to_sym
|
11
|
+
when :help
|
12
|
+
print_help(output)
|
13
|
+
when :list
|
14
|
+
documents.projects.all.each do |task|
|
15
|
+
output.puts task.highlight_as_project
|
16
|
+
end
|
17
|
+
when :add
|
18
|
+
add_project(args, output)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def add_project(args, output)
|
26
|
+
prompt = TTY::Prompt.new
|
27
|
+
name = prompt.ask('Project identifier: ')
|
28
|
+
name = name.downcase.gsub("_", "-").gsub(" ", "-").gsub(/[^0-9a-z\-]/i, '')
|
29
|
+
name = "+#{name}" unless name.start_with?('+')
|
30
|
+
output.puts name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Intent
|
2
|
+
module Commands
|
3
|
+
class Todo < Base
|
4
|
+
def run(args, output)
|
5
|
+
if args.empty?
|
6
|
+
print_help(output)
|
7
|
+
else
|
8
|
+
case args.first.to_sym
|
9
|
+
when :add then add_line(args, output)
|
10
|
+
when :list then list_draw(args, output)
|
11
|
+
when :focus then focus_draw(args, output)
|
12
|
+
else
|
13
|
+
raise "Verb not found"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def add_line(args, output)
|
21
|
+
reader = TTY::Reader.new
|
22
|
+
line = reader.read_line("task line: ")
|
23
|
+
documents.inbox.add_line!(line)
|
24
|
+
end
|
25
|
+
|
26
|
+
def focus_draw(args, output)
|
27
|
+
pastel = Pastel.new
|
28
|
+
documents.inbox.focused_projects.each do |project|
|
29
|
+
output.puts pastel.green(project)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def list_draw(args, output)
|
34
|
+
filtered_list = documents.inbox.all
|
35
|
+
|
36
|
+
unless args[1].nil?
|
37
|
+
case args[1][0]
|
38
|
+
when '@'
|
39
|
+
filtered_list = filtered_list.by_context(args[1]).by_not_done
|
40
|
+
when '+'
|
41
|
+
filtered_list = filtered_list.by_project(args[1])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
filtered_list.by_not_done.each do |task|
|
46
|
+
output.puts task.to_s_highlighted
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'intent/commands/base'
|
2
|
+
require 'intent/commands/errors'
|
3
|
+
require 'intent/commands/intent'
|
4
|
+
require 'intent/commands/todo'
|
5
|
+
require 'intent/commands/projects'
|
6
|
+
#require 'intent/commands/project'
|
7
|
+
#require 'intent/commands/ideas'
|
8
|
+
#require 'intent/commands/idea'
|
9
|
+
require 'intent/commands/inventory'
|
data/lib/intent/core.rb
ADDED
@@ -0,0 +1,184 @@
|
|
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
|
+
end
|
19
|
+
|
20
|
+
module Core
|
21
|
+
List = ::Todo::List
|
22
|
+
Record = ::Todo::Task
|
23
|
+
|
24
|
+
class Noun
|
25
|
+
def initialize(type, label, tags)
|
26
|
+
@type = type
|
27
|
+
@label = label
|
28
|
+
@props = lex_props(tags)
|
29
|
+
@tags = tags
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def lex_props(tags)
|
35
|
+
p tags
|
36
|
+
end
|
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)
|
109
|
+
record = Record.new("#{Date.today} #{description} id:#{id} is:#{type} sku:#{sku}")
|
110
|
+
@list.append(record)
|
111
|
+
@list.save!
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_folder!(description, id, sku)
|
115
|
+
add_item!(description, id, :folder, sku)
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_box!(description, id, sku)
|
119
|
+
add_item!(description, id, :box, sku)
|
120
|
+
end
|
121
|
+
|
122
|
+
def save!
|
123
|
+
@list.save!
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class Inbox
|
128
|
+
attr_reader :list
|
129
|
+
|
130
|
+
def initialize(db_path)
|
131
|
+
@list = List.new(db_path)
|
132
|
+
end
|
133
|
+
|
134
|
+
def all
|
135
|
+
@list.by_not_done
|
136
|
+
end
|
137
|
+
|
138
|
+
def focused
|
139
|
+
@list.by_context('@focus').by_not_done
|
140
|
+
end
|
141
|
+
|
142
|
+
def focused_projects
|
143
|
+
focused.map { |t| t.projects }.flatten.uniq
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_line!(line)
|
147
|
+
record = Record.new("#{Date.today} #{line}")
|
148
|
+
@list.prepend(record)
|
149
|
+
@list.save!
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class Documents
|
154
|
+
attr_reader :projects
|
155
|
+
attr_reader :inventory
|
156
|
+
attr_reader :inbox
|
157
|
+
|
158
|
+
def initialize
|
159
|
+
@projects = Projects.new("#{Intent::Env.documents_dir}/projects.txt")
|
160
|
+
@inventory = Inventory.new("#{Intent::Env.documents_dir}/inventory.txt")
|
161
|
+
@inbox = Inbox.new("#{Intent::Env.documents_dir}/todo.txt")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class Dispatcher
|
167
|
+
def self.exec_command(command, args, output=STDOUT)
|
168
|
+
command = init_command(command).new
|
169
|
+
command.run(args, output)
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.init_command(command)
|
173
|
+
case command
|
174
|
+
when :intent then return Commands::Intent
|
175
|
+
when :inventory then return Commands::Inventory
|
176
|
+
when :projects then return Commands::Projects
|
177
|
+
when :project then return Commands::Project
|
178
|
+
when :todo then return Commands::Todo
|
179
|
+
else
|
180
|
+
raise Commands::Errors::COMMAND_NOT_FOUND
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
data/lib/intent/projects.rb
CHANGED
data/lib/intent/review.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
usage: projects <task>
|
2
|
+
intent projects <task>
|
3
|
+
|
4
|
+
A set of tasks for managing a network of plain text projects.
|
5
|
+
|
6
|
+
projects status - DEPRECATED parses tracked file status in local project directories
|
7
|
+
projects active - lists currently active projects
|
8
|
+
projects focus - initialise interactive focus navigator
|
9
|
+
projects sync - stores synchronised commit of current changes to projects
|
@@ -0,0 +1,15 @@
|
|
1
|
+
usage: todo <task>
|
2
|
+
intent todo <task>
|
3
|
+
|
4
|
+
A set of tasks for managing a plain text todo list.
|
5
|
+
|
6
|
+
todo list - list all items in the list
|
7
|
+
todo add - add a new task to the list
|
8
|
+
todo sample - randomly select a priority task"
|
9
|
+
todo projects - list all project tags in the list
|
10
|
+
todo contexts - list all context tags in the list
|
11
|
+
todo archive - archive completed tasks in the nearest `done.txt`
|
12
|
+
todo status - show completion status for all projects
|
13
|
+
todo sync - synchronize local changes with remote git repo
|
14
|
+
todo collect - collect open browser tabs as items for later reading
|
15
|
+
todo focus - block distractions and start focusing
|
data/lib/intent/todo.rb
CHANGED
@@ -5,8 +5,10 @@ require 'fileutils'
|
|
5
5
|
require 'logger'
|
6
6
|
require 'git'
|
7
7
|
require 'terminal-notifier'
|
8
|
+
require 'sorted_set'
|
8
9
|
require 'ghost'
|
9
|
-
|
10
|
+
|
11
|
+
require 'intent/todo/commands'
|
10
12
|
|
11
13
|
Todo.customize do |options|
|
12
14
|
options.require_completed_on = false
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Intent
|
2
|
+
module Verbs
|
3
|
+
class Add
|
4
|
+
def initialize(documents)
|
5
|
+
@documents = documents
|
6
|
+
end
|
7
|
+
|
8
|
+
def invoke_prepend(scope, noun)
|
9
|
+
ledger = @documents.send(scope)
|
10
|
+
ledger.prepend(new Todo::Task(noun.todo_s))
|
11
|
+
ledger.save!
|
12
|
+
end
|
13
|
+
|
14
|
+
def invoke_append(ledger, noun)
|
15
|
+
ledger = @documents.send(scope)
|
16
|
+
ledger.append(new Todo::Task(noun.todo_s))
|
17
|
+
ledger.save!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Intent
|
2
|
+
module Verbs
|
3
|
+
class Install
|
4
|
+
attr_reader :documents
|
5
|
+
|
6
|
+
def initialize(documents)
|
7
|
+
@documents = documents
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
# Preprequisite checks
|
12
|
+
# return env_not_detected! unless @documents.env_detected?
|
13
|
+
# return already_installed! if @documents.install_detected?
|
14
|
+
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Intent
|
2
|
+
module Review
|
3
|
+
class Commands < Intent::CommandDispatcher
|
4
|
+
def run(args, output=STDOUT)
|
5
|
+
if args.empty?
|
6
|
+
launch_densityplot
|
7
|
+
else
|
8
|
+
print_help(output)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def launch_densityplot
|
13
|
+
UnicodePlot.barplot(data: {'calyx': 20, 'fictive': 50}, title: "Projects").render
|
14
|
+
end
|
15
|
+
|
16
|
+
def launch_ui_loop
|
17
|
+
list = Todo::List.new(ENV['TODO_TXT'])
|
18
|
+
|
19
|
+
box = TTY::Box.frame(
|
20
|
+
width: TTY::Screen.width,
|
21
|
+
height: TTY::Screen.height-1,
|
22
|
+
align: :center,
|
23
|
+
border: :thick,
|
24
|
+
style: {
|
25
|
+
fg: :bright_yellow,
|
26
|
+
border: {
|
27
|
+
fg: :white,
|
28
|
+
}
|
29
|
+
}
|
30
|
+
)
|
31
|
+
|
32
|
+
focus_index = 0
|
33
|
+
|
34
|
+
def truncate(str, width)
|
35
|
+
return str unless str.length >= width
|
36
|
+
|
37
|
+
"#{str.slice(0, width-3)}..."
|
38
|
+
end
|
39
|
+
|
40
|
+
def draw_card(top, item, focus)
|
41
|
+
|
42
|
+
style = unless top == focus
|
43
|
+
{ fg: :white, border: { fg: :white } }
|
44
|
+
else
|
45
|
+
{ fg: :bright_white, border: { fg: :bright_magenta, bg: :black } }
|
46
|
+
end
|
47
|
+
|
48
|
+
title = if top == focus
|
49
|
+
{bottom_right: "[x: close][enter: launch]"}
|
50
|
+
else
|
51
|
+
{}
|
52
|
+
end
|
53
|
+
|
54
|
+
#pastel = Pastel.new
|
55
|
+
width = 90
|
56
|
+
|
57
|
+
TTY::Box.frame(width: width, height: 4, left: 4, title: title, border: :thick, style: style) do
|
58
|
+
"\s#{truncate(item[:title], 88)}\n\s#{truncate(item[:href], 88)}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
items_per_page = (TTY::Screen.height-1) / 4
|
63
|
+
|
64
|
+
items = list.by_not_done.by_context("@reading").slice(0, items_per_page).map do |item|
|
65
|
+
{ title: item.text, href: item.text }
|
66
|
+
end
|
67
|
+
|
68
|
+
$cursor = TTY::Cursor
|
69
|
+
print $cursor.hide
|
70
|
+
|
71
|
+
def draw_list(items, focus)
|
72
|
+
buffer = []
|
73
|
+
items.each_with_index do |item, i|
|
74
|
+
buffer << draw_card(i, item, focus)
|
75
|
+
end
|
76
|
+
result = buffer.join("")
|
77
|
+
|
78
|
+
print $cursor.clear_screen + $cursor.move_to(0,0)
|
79
|
+
print result
|
80
|
+
end
|
81
|
+
|
82
|
+
draw_list(items, focus_index)
|
83
|
+
|
84
|
+
reader = TTY::Reader.new(interrupt: :exit)
|
85
|
+
|
86
|
+
reader.on(:keyctrl_x, :keyescape) do
|
87
|
+
print $cursor.clear_screen + $cursor.move_to(0,0)
|
88
|
+
print $cursor.show
|
89
|
+
exit
|
90
|
+
end
|
91
|
+
|
92
|
+
reader.on(:keytab, :keydown) do
|
93
|
+
if focus_index == items.count - 1
|
94
|
+
focus_index = 0
|
95
|
+
else
|
96
|
+
focus_index += 1
|
97
|
+
end
|
98
|
+
draw_list(items, focus_index)
|
99
|
+
end
|
100
|
+
|
101
|
+
reader.on(:keyup) do
|
102
|
+
if focus_index == 0
|
103
|
+
focus_index = items.count - 1
|
104
|
+
else
|
105
|
+
focus_index -= 1
|
106
|
+
end
|
107
|
+
draw_list(items, focus_index)
|
108
|
+
end
|
109
|
+
|
110
|
+
reader.on(:keypress) do |key|
|
111
|
+
if key.value == "x"
|
112
|
+
items.delete_at(focus_index)
|
113
|
+
focus_index -= 1 if focus_index >= items.count
|
114
|
+
draw_list(items, focus_index)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
reader.on(:keyenter) do
|
119
|
+
`chrome-cli open #{items[focus_index][:href]}`
|
120
|
+
end
|
121
|
+
|
122
|
+
loop do
|
123
|
+
reader.read_line(echo: false)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
|
@@ -4,10 +4,10 @@ module Intent
|
|
4
4
|
List = ::Todo::List
|
5
5
|
Syntax = ::Todo::Syntax
|
6
6
|
|
7
|
-
class
|
7
|
+
class Commands < Intent::CommandDispatcher
|
8
8
|
include Syntax
|
9
9
|
|
10
|
-
def
|
10
|
+
def run(args, output=STDOUT)
|
11
11
|
if args.empty?
|
12
12
|
print_help(output)
|
13
13
|
else
|
@@ -183,20 +183,7 @@ module Intent
|
|
183
183
|
end
|
184
184
|
|
185
185
|
def self.print_help(output)
|
186
|
-
output.puts
|
187
|
-
output.puts
|
188
|
-
output.puts "A set of tasks for managing a plain text todo list."
|
189
|
-
output.puts
|
190
|
-
output.puts "todo list - list all items in the list"
|
191
|
-
output.puts "todo add - add a new task to the list"
|
192
|
-
output.puts "todo sample - randomly select a priority task"
|
193
|
-
output.puts "todo projects - list all project tags in the list"
|
194
|
-
output.puts "todo contexts - list all context tags in the list"
|
195
|
-
output.puts "todo archive - archive completed tasks in the nearest `done.txt`"
|
196
|
-
output.puts "todo status - show completion status for all projects"
|
197
|
-
output.puts "todo sync - synchronize local changes with remote git repo"
|
198
|
-
output.puts "todo collect - collect open browser tabs as items for later reading"
|
199
|
-
output.puts "todo focus - block distractions and start focusing"
|
186
|
+
output.puts File.read('./todo.help.txt')
|
200
187
|
end
|
201
188
|
end
|
202
189
|
end
|
data/lib/intent/version.rb
CHANGED
data/lib/intent.rb
CHANGED
@@ -1,4 +1,21 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
1
|
+
#require 'random'
|
2
|
+
require 'todo-txt'
|
3
|
+
require 'pastel'
|
4
|
+
require 'tty-prompt'
|
5
|
+
require 'tty-table'
|
6
|
+
require 'tty-tree'
|
7
|
+
require 'nanoid'
|
8
|
+
require 'gem_ext/todo-txt'
|
9
|
+
|
10
|
+
Todo.customize do |options|
|
11
|
+
options.require_completed_on = false
|
12
|
+
end
|
13
|
+
|
4
14
|
require 'intent/version'
|
15
|
+
require 'intent/core'
|
16
|
+
require 'intent/commands'
|
17
|
+
# require 'intent/todo'
|
18
|
+
# require 'intent/review'
|
19
|
+
# require 'intent/projects'
|
20
|
+
# require 'intent/desktop'
|
21
|
+
|
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.
|
4
|
+
version: 0.7.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:
|
11
|
+
date: 2024-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: todo-txt
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.
|
47
|
+
version: 1.19.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
54
|
+
version: 1.19.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: terminal-notifier
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,132 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: unicode_plot
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.0.5
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.0.5
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: kdl
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.0.3
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.0.3
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sorted_set
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.0.3
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.0.3
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: strings-ansi
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.2.0
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.2.0
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: bibtex-ruby
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 6.1.0
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 6.1.0
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: tty-prompt
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.23.1
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.23.1
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: tty-table
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 0.12.0
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 0.12.0
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: tty-tree
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: 0.4.0
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: 0.4.0
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: nanoid
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: 2.0.0
|
202
|
+
type: :runtime
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: 2.0.0
|
83
209
|
- !ruby/object:Gem::Dependency
|
84
210
|
name: bundler
|
85
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,37 +252,54 @@ description:
|
|
126
252
|
email:
|
127
253
|
- me@maetl.net
|
128
254
|
executables:
|
255
|
+
- intent
|
256
|
+
- inventory
|
129
257
|
- project_doc
|
130
258
|
- projects
|
131
259
|
- projects_active
|
132
|
-
- review
|
133
260
|
- todo
|
134
261
|
- todo_review
|
135
262
|
extensions: []
|
136
263
|
extra_rdoc_files: []
|
137
264
|
files:
|
138
265
|
- ".gitignore"
|
139
|
-
- ".travis.yml"
|
140
266
|
- Gemfile
|
141
267
|
- LICENSE.txt
|
268
|
+
- README.md
|
142
269
|
- Rakefile
|
270
|
+
- bin/intent
|
271
|
+
- bin/inventory
|
143
272
|
- bin/project_doc
|
144
273
|
- bin/projects
|
145
274
|
- bin/projects_active
|
146
|
-
- bin/review
|
147
275
|
- bin/todo
|
148
276
|
- bin/todo_review
|
149
277
|
- intent.gemspec
|
150
278
|
- lib/gem_ext/todo-txt.rb
|
151
279
|
- lib/intent.rb
|
280
|
+
- lib/intent/commands.rb
|
281
|
+
- lib/intent/commands/base.rb
|
282
|
+
- lib/intent/commands/errors.rb
|
283
|
+
- lib/intent/commands/intent.rb
|
284
|
+
- lib/intent/commands/inventory.rb
|
285
|
+
- lib/intent/commands/projects.rb
|
286
|
+
- lib/intent/commands/todo.rb
|
287
|
+
- lib/intent/core.rb
|
288
|
+
- lib/intent/desktop.rb
|
152
289
|
- lib/intent/projects.rb
|
153
|
-
- lib/intent/projects/manager.rb
|
154
|
-
- lib/intent/projects/status.rb
|
155
290
|
- lib/intent/review.rb
|
156
|
-
- lib/intent/
|
291
|
+
- lib/intent/text/inventory.help.txt
|
292
|
+
- lib/intent/text/project.help.txt
|
293
|
+
- lib/intent/text/projects.help.txt
|
294
|
+
- lib/intent/text/todo.help.txt
|
157
295
|
- lib/intent/todo.rb
|
158
|
-
- lib/intent/todo/manager.rb
|
159
296
|
- lib/intent/ui/ttyui.rb
|
297
|
+
- lib/intent/verbs/add.rb
|
298
|
+
- lib/intent/verbs/cite.rb
|
299
|
+
- lib/intent/verbs/install.rb
|
300
|
+
- lib/intent/verbs/review.rb
|
301
|
+
- lib/intent/verbs/status.rb
|
302
|
+
- lib/intent/verbs/todo.rb
|
160
303
|
- lib/intent/version.rb
|
161
304
|
homepage: http://maetl.net
|
162
305
|
licenses:
|
@@ -177,7 +320,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
320
|
- !ruby/object:Gem::Version
|
178
321
|
version: '0'
|
179
322
|
requirements: []
|
180
|
-
rubygems_version: 3.
|
323
|
+
rubygems_version: 3.3.7
|
181
324
|
signing_key:
|
182
325
|
specification_version: 4
|
183
326
|
summary: Text-based project management
|
data/.travis.yml
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Intent
|
2
|
-
module Projects
|
3
|
-
class Manager
|
4
|
-
def self.run(args, output=STDOUT)
|
5
|
-
if args.empty?
|
6
|
-
print_help(output)
|
7
|
-
else
|
8
|
-
case args.first.to_sym
|
9
|
-
when :status
|
10
|
-
Status.run(File.expand_path('~/Projects').to_s)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.print_help(output)
|
16
|
-
output.puts "usage: review"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
File without changes
|