intent 0.5.5 → 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 +10 -28
- data/bin/{review → intent} +1 -2
- data/bin/inventory +12 -0
- data/bin/project_doc +30 -0
- data/bin/projects +1 -1
- data/bin/projects_active +123 -0
- data/bin/todo +1 -1
- data/bin/todo_review +123 -0
- data/intent.gemspec +15 -7
- 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/ui/ttyui.rb +90 -0
- 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 +179 -32
- data/.travis.yml +0 -4
- data/CODE_OF_CONDUCT.md +0 -13
- 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
@@ -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,90 @@
|
|
1
|
+
require "tty-box"
|
2
|
+
require "tty-screen"
|
3
|
+
require "tty-reader"
|
4
|
+
require "tty-cursor"
|
5
|
+
require "tty-pager"
|
6
|
+
require "pastel"
|
7
|
+
require "todo-txt"
|
8
|
+
|
9
|
+
module Intent
|
10
|
+
module UI
|
11
|
+
class Panel
|
12
|
+
def initialize(x, y, width, height)
|
13
|
+
@x = x
|
14
|
+
@y = y
|
15
|
+
@width = width
|
16
|
+
@height = height
|
17
|
+
end
|
18
|
+
|
19
|
+
def draw
|
20
|
+
TTY::Box.frame(
|
21
|
+
left: @x,
|
22
|
+
top: @y,
|
23
|
+
width: @width,
|
24
|
+
height: @height,
|
25
|
+
align: :center,
|
26
|
+
border: :light,
|
27
|
+
style: {
|
28
|
+
fg: :white,
|
29
|
+
border: {
|
30
|
+
fg: :white,
|
31
|
+
}
|
32
|
+
}
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Window
|
38
|
+
def initialize
|
39
|
+
@width = TTY::Screen.width
|
40
|
+
@height = TTY::Screen.height-1
|
41
|
+
@panels = [Panel.new(0, 0, @width, @height)]
|
42
|
+
@cursor = TTY::Cursor
|
43
|
+
end
|
44
|
+
|
45
|
+
def split_vertical(view1=nil, view2=nil)
|
46
|
+
width = (@width / 2) - 1
|
47
|
+
height = @height - 2
|
48
|
+
|
49
|
+
@panels << Panel.new(1, 1, width, height)
|
50
|
+
@panels << Panel.new(width + 1, 1, width, height)
|
51
|
+
end
|
52
|
+
|
53
|
+
def split_horizontal(view1=nil, view2=nil)
|
54
|
+
width = @width - 2
|
55
|
+
height = (@height / 2) - 2
|
56
|
+
end
|
57
|
+
|
58
|
+
def box_frame
|
59
|
+
TTY::Box.frame(
|
60
|
+
width: @width,
|
61
|
+
height: @height,
|
62
|
+
align: :center,
|
63
|
+
border: :thick,
|
64
|
+
style: {
|
65
|
+
fg: :blue,
|
66
|
+
border: {
|
67
|
+
fg: :white,
|
68
|
+
}
|
69
|
+
}
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
def draw
|
74
|
+
@cursor.clear_screen
|
75
|
+
|
76
|
+
print box_frame
|
77
|
+
|
78
|
+
@panels.each do |panel|
|
79
|
+
@cursor.move_to
|
80
|
+
|
81
|
+
print panel.draw
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
win = Intent::UI::Window.new
|
89
|
+
win.split_vertical
|
90
|
+
win.draw
|
@@ -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
|