standup_md 0.2.1 → 0.3.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 +1 -0
- data/Gemfile.lock +7 -1
- data/README.md +142 -116
- data/bin/standup +1 -1
- data/doc/README_md.html +143 -96
- data/doc/StandupMD.html +96 -1322
- data/doc/StandupMD/Cli.html +124 -479
- data/doc/StandupMD/Cli/Helpers.html +167 -0
- data/doc/StandupMD/Config.html +230 -0
- data/doc/StandupMD/Config/Cli.html +355 -0
- data/doc/StandupMD/Config/Entry.html +284 -0
- data/doc/StandupMD/Config/EntryList.html +197 -0
- data/doc/StandupMD/Config/File.html +609 -0
- data/doc/StandupMD/Entry.html +478 -0
- data/doc/StandupMD/EntryList.html +759 -0
- data/doc/StandupMD/File.html +574 -0
- data/doc/created.rid +15 -5
- data/doc/index.html +153 -94
- data/doc/js/search_index.js +1 -1
- data/doc/js/search_index.js.gz +0 -0
- data/doc/table_of_contents.html +221 -72
- data/lib/standup_md.rb +27 -544
- data/lib/standup_md/cli.rb +63 -246
- data/lib/standup_md/cli/helpers.rb +165 -0
- data/lib/standup_md/config.rb +45 -0
- data/lib/standup_md/config/cli.rb +106 -0
- data/lib/standup_md/config/entry.rb +61 -0
- data/lib/standup_md/config/entry_list.rb +26 -0
- data/lib/standup_md/config/file.rb +199 -0
- data/lib/standup_md/entry.rb +121 -0
- data/lib/standup_md/entry_list.rb +166 -0
- data/lib/standup_md/file.rb +172 -0
- data/lib/standup_md/file/helpers.rb +62 -0
- data/lib/standup_md/version.rb +5 -3
- data/standup_md.gemspec +1 -0
- metadata +35 -2
data/lib/standup_md/cli.rb
CHANGED
@@ -1,29 +1,50 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'optparse'
|
3
|
-
require_relative '
|
4
|
+
require_relative 'cli/helpers'
|
5
|
+
|
6
|
+
module StandupMD
|
4
7
|
|
5
|
-
class StandupMD
|
6
8
|
##
|
7
9
|
# Class for handing the command-line interface.
|
8
10
|
class Cli
|
11
|
+
include Helpers
|
12
|
+
|
13
|
+
##
|
14
|
+
# Access to the class's configuration.
|
15
|
+
#
|
16
|
+
# @return [StandupMD::Config::Cli]
|
17
|
+
def self.config
|
18
|
+
@config ||= StandupMD.config.cli
|
19
|
+
end
|
9
20
|
|
10
21
|
##
|
11
|
-
#
|
12
|
-
|
13
|
-
|
22
|
+
# Prints output if +verbose+ is true.
|
23
|
+
#
|
24
|
+
# @return [nil]
|
25
|
+
def self.echo(msg)
|
26
|
+
puts msg if config.verbose
|
27
|
+
end
|
14
28
|
|
15
29
|
##
|
16
30
|
# Creates an instance of +StandupMD+ and runs what the user requested.
|
17
31
|
def self.execute(options = [])
|
18
32
|
exe = new(options)
|
19
|
-
exe.append_to_previous_entry_tasks if exe.should_append?
|
20
33
|
|
21
|
-
exe.
|
22
|
-
|
23
|
-
|
24
|
-
|
34
|
+
exe.write_file if config.write
|
35
|
+
if config.print
|
36
|
+
exe.print(exe.entry)
|
37
|
+
elsif config.edit
|
38
|
+
exe.edit
|
39
|
+
end
|
25
40
|
end
|
26
41
|
|
42
|
+
##
|
43
|
+
# The entry searched for, usually today.
|
44
|
+
#
|
45
|
+
# @return [StandupMD::Entry]
|
46
|
+
attr_reader :entry
|
47
|
+
|
27
48
|
##
|
28
49
|
# Arguments passed at runtime.
|
29
50
|
#
|
@@ -31,115 +52,54 @@ class StandupMD
|
|
31
52
|
attr_reader :options
|
32
53
|
|
33
54
|
##
|
34
|
-
#
|
55
|
+
# The file loaded.
|
35
56
|
#
|
36
|
-
# @return [
|
37
|
-
attr_reader :
|
57
|
+
# @return [StandupMD::File]
|
58
|
+
attr_reader :file
|
38
59
|
|
39
60
|
##
|
40
61
|
# Constructor. Sets defaults.
|
41
62
|
#
|
42
63
|
# @param [Array] options
|
43
|
-
def initialize(options)
|
44
|
-
@
|
45
|
-
@
|
46
|
-
@
|
47
|
-
|
48
|
-
|
49
|
-
@
|
50
|
-
@
|
51
|
-
@
|
52
|
-
@preferences = get_preferences
|
64
|
+
def initialize(options = [], load_config = true)
|
65
|
+
@config = self.class.config
|
66
|
+
@preference_file_loaded = false
|
67
|
+
@options = options
|
68
|
+
load_preferences if load_config
|
69
|
+
set_preferences(options)
|
70
|
+
@file = StandupMD::File.find_by_date(@config.date)
|
71
|
+
@file.load
|
72
|
+
@entry = set_entry(@file)
|
53
73
|
end
|
54
74
|
|
55
75
|
##
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# @return [StandupMD]
|
59
|
-
def standup
|
60
|
-
cf = File.file?(PREFERENCE_FILE) ? PREFERENCE_FILE : nil
|
61
|
-
@standup ||= ::StandupMD.new(cf) do |s|
|
62
|
-
if s.config.any?
|
63
|
-
echo 'Config options:'
|
64
|
-
s.config.each { |k, v| echo " #{k} = #{v}" }
|
65
|
-
end
|
66
|
-
echo 'Runtime options:' if preferences.any?
|
67
|
-
preferences.each do |k, v|
|
68
|
-
echo " #{k} = #{v}"
|
69
|
-
s.send("#{k}=", v)
|
70
|
-
end
|
71
|
-
end.load
|
72
|
-
end
|
73
|
-
|
74
|
-
##
|
75
|
-
# Tries to determine the editor, first by checking if the user has one set
|
76
|
-
# in their preferences. If not, the +VISUAL+ and +EDITOR+ environmental
|
77
|
-
# variables are checked. If none of the above are set, defaults to +vim+.
|
78
|
-
#
|
79
|
-
# @return [String] The editor
|
80
|
-
def editor
|
81
|
-
@editor ||=
|
82
|
-
if standup.config.key?('editor')
|
83
|
-
echo "Editor set to [#{standup.config['editor']}] via preferences"
|
84
|
-
standup.config['editor']
|
85
|
-
elsif ENV['VISUAL']
|
86
|
-
echo "Editor set to [#{ENV['VISUAL']}] (ENV['VISUAL'])"
|
87
|
-
ENV['VISUAL']
|
88
|
-
elsif ENV['EDITOR']
|
89
|
-
echo "Editor set to [#{ENV['EDITOR']}] (ENV['EDITOR'])"
|
90
|
-
ENV['EDITOR']
|
91
|
-
else
|
92
|
-
echo "Editor set to [vim] (default)"
|
93
|
-
'vim'
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
##
|
98
|
-
# Prints all entries to the command line.
|
99
|
-
#
|
100
|
-
# @return [nil]
|
101
|
-
def print_all_entries
|
102
|
-
echo 'Display all entries'
|
103
|
-
unless json?
|
104
|
-
standup.all_entries.keys.reverse.each do |head|
|
105
|
-
print_entry(head, standup.all_entries[head])
|
106
|
-
end
|
107
|
-
return
|
108
|
-
end
|
109
|
-
echo ' ...as json'
|
110
|
-
puts standup.all_entries.to_json
|
111
|
-
end
|
112
|
-
|
113
|
-
##
|
114
|
-
# Prints the current entry to the command line.
|
76
|
+
# Load the preference file.
|
115
77
|
#
|
116
78
|
# @return [nil]
|
117
|
-
def
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
79
|
+
def load_preferences
|
80
|
+
if ::File.exist?(@config.preference_file)
|
81
|
+
::StandupMD.load_config_file(@config.preference_file)
|
82
|
+
@preference_file_loaded = true
|
83
|
+
else
|
84
|
+
echo "Preference file #{@config.preference_file} does not exist."
|
122
85
|
end
|
123
|
-
echo ' ...as json'
|
124
|
-
entry = {standup.header => standup.current_entry}.to_json
|
125
|
-
puts entry
|
126
86
|
end
|
127
87
|
|
128
88
|
##
|
129
|
-
#
|
89
|
+
# Has the preference file been loaded?
|
130
90
|
#
|
131
|
-
# @return
|
132
|
-
def
|
133
|
-
|
134
|
-
additions = preferences.delete('previous_entry_tasks')
|
135
|
-
standup.previous_entry_tasks.concat(additions)
|
91
|
+
# @return boolean
|
92
|
+
def preference_file_loaded?
|
93
|
+
@preference_file_loaded
|
136
94
|
end
|
137
95
|
|
138
96
|
##
|
139
97
|
# Opens the file in an editor. Abandons the script.
|
98
|
+
#
|
99
|
+
# @return [nil]
|
140
100
|
def edit
|
141
|
-
echo "Opening file in #{editor}"
|
142
|
-
exec("#{editor} #{
|
101
|
+
echo "Opening file in #{@config.editor}"
|
102
|
+
exec("#{@config.editor} #{file.name}")
|
143
103
|
end
|
144
104
|
|
145
105
|
##
|
@@ -147,159 +107,16 @@ class StandupMD
|
|
147
107
|
#
|
148
108
|
# @return [Boolean] true if file was written
|
149
109
|
def write_file
|
150
|
-
echo
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
##
|
155
|
-
# Should current entry be printed? If true, disables editing.
|
156
|
-
#
|
157
|
-
# @return [Boolean] Default is false
|
158
|
-
def print_current_entry?
|
159
|
-
@print_current_entry
|
160
|
-
end
|
161
|
-
|
162
|
-
##
|
163
|
-
# If printing an entry, should it be printed as json?
|
164
|
-
#
|
165
|
-
# @return [Boolean] Default is false
|
166
|
-
def json?
|
167
|
-
@json
|
168
|
-
end
|
169
|
-
|
170
|
-
##
|
171
|
-
# Should all entries be printed? If true, disables editing.
|
172
|
-
#
|
173
|
-
# @return [Boolean] Default is false
|
174
|
-
def print_all_entries?
|
175
|
-
@print_all_entries
|
110
|
+
echo "Writing file #{file.name}"
|
111
|
+
file.write
|
176
112
|
end
|
177
113
|
|
178
114
|
##
|
179
|
-
#
|
180
|
-
#
|
181
|
-
# @return [Boolean] Default is false
|
182
|
-
def verbose?
|
183
|
-
@verbose
|
184
|
-
end
|
185
|
-
|
186
|
-
##
|
187
|
-
# Should the file be written?
|
188
|
-
#
|
189
|
-
# @return [Boolean] Default is true
|
190
|
-
def write?
|
191
|
-
@write
|
192
|
-
end
|
193
|
-
|
194
|
-
##
|
195
|
-
# Should the standup file be opened in the editor?
|
196
|
-
#
|
197
|
-
# @return [Boolean] Default is true
|
198
|
-
def edit?
|
199
|
-
@edit
|
200
|
-
end
|
201
|
-
|
202
|
-
##
|
203
|
-
# Should `previous_entry_tasks` be appended? If false,
|
204
|
-
# +previous_entry_tasks+ will be overwritten.
|
205
|
-
#
|
206
|
-
# @return [Boolean] Default is true
|
207
|
-
def append_previous?
|
208
|
-
@append_previous
|
209
|
-
end
|
210
|
-
|
211
|
-
##
|
212
|
-
# Did the user pass +previous_entry_tasks+, and should we append?
|
213
|
-
#
|
214
|
-
# @return [Boolean]
|
215
|
-
def should_append?
|
216
|
-
preferences.key?('previous_entry_tasks') && append_previous?
|
217
|
-
end
|
218
|
-
|
219
|
-
##
|
220
|
-
# Prints output if +verbose+ is true.
|
115
|
+
# Quick access to Cli.echo.
|
221
116
|
#
|
222
117
|
# @return [nil]
|
223
118
|
def echo(msg)
|
224
|
-
|
225
|
-
end
|
226
|
-
|
227
|
-
private
|
228
|
-
|
229
|
-
##
|
230
|
-
# Prints entries to the command line as markdown.
|
231
|
-
def print_entry(head, s_heads) # :nodoc:
|
232
|
-
puts '#' * standup.header_depth + ' ' + head
|
233
|
-
s_heads.each do |s_head, tasks|
|
234
|
-
puts '#' * standup.sub_header_depth + ' ' + s_head
|
235
|
-
tasks.each { |task| puts standup.bullet_character + ' ' + task }
|
236
|
-
end
|
237
|
-
puts
|
238
|
-
end
|
239
|
-
|
240
|
-
##
|
241
|
-
# Parses options passed at runtime and concatenates them with the options in
|
242
|
-
# the user's preferences file. Reveal source to see options.
|
243
|
-
#
|
244
|
-
# @return [Hash]
|
245
|
-
def get_preferences # :nodoc:
|
246
|
-
prefs = {}
|
247
|
-
|
248
|
-
OptionParser.new do |opts|
|
249
|
-
opts.banner = 'The Standup Doctor'
|
250
|
-
opts.version = ::StandupMD::VERSION
|
251
|
-
opts.on('--current-entry-tasks=ARRAY', Array, "List of current entry's tasks") do |v|
|
252
|
-
prefs['current_entry_tasks'] = v
|
253
|
-
end
|
254
|
-
opts.on('--previous-entry-tasks=ARRAY', Array, "List of precious entry's tasks") do |v|
|
255
|
-
prefs['previous_entry_tasks'] = v
|
256
|
-
end
|
257
|
-
opts.on('--impediments=ARRAY', Array, 'List of impediments for current entry') do |v|
|
258
|
-
prefs['impediments'] = v
|
259
|
-
end
|
260
|
-
opts.on('--notes=ARRAY', Array, 'List of notes for current entry') do |v|
|
261
|
-
prefs['notes'] = v
|
262
|
-
end
|
263
|
-
opts.on('--sub-header-order=ARRAY', Array, 'The order of the sub-headers when writing the file') do |v|
|
264
|
-
prefs['sub_header_order'] = v
|
265
|
-
end
|
266
|
-
opts.on('--[no-]append-previous', 'Append previous tasks? Default is true') do |v|
|
267
|
-
@append_previous = v
|
268
|
-
end
|
269
|
-
opts.on('-f', '--file-name-format=STRING', 'Date-formattable string to use for standup file name') do |v|
|
270
|
-
prefs['file_name_format'] = v
|
271
|
-
end
|
272
|
-
opts.on('-e', '--editor=EDITOR', 'Editor to use for opening standup files') do |v|
|
273
|
-
@editor = v
|
274
|
-
end
|
275
|
-
opts.on('-d', '--directory=DIRECTORY', 'The directories where standup files are located') do |v|
|
276
|
-
prefs['directory'] = v
|
277
|
-
end
|
278
|
-
opts.on('--[no-]write', "Write current entry if it doesn't exist. Default is true") do |v|
|
279
|
-
@write = v
|
280
|
-
end
|
281
|
-
opts.on('--[no-]edit', 'Open the file in the editor. Default is true') do |v|
|
282
|
-
@edit = v
|
283
|
-
end
|
284
|
-
opts.on('-j', '--[no-]json', 'Print output as formatted json. Default is false.') do |v|
|
285
|
-
@json = v
|
286
|
-
end
|
287
|
-
opts.on('-v', '--[no-]verbose', 'Verbose output. Default is false.') do |v|
|
288
|
-
@verbose = v
|
289
|
-
end
|
290
|
-
opts.on('-c', '--current', 'Print current entry. Disables editing and writing') do |v|
|
291
|
-
@print_current_entry = v
|
292
|
-
@edit = false
|
293
|
-
@write = false
|
294
|
-
end
|
295
|
-
opts.on('-a', '--all', 'Print all previous entries. Disables editing and writing') do |v|
|
296
|
-
@print_all_entries = v
|
297
|
-
@edit = false
|
298
|
-
@write = false
|
299
|
-
end
|
300
|
-
end.parse!(options)
|
301
|
-
|
302
|
-
prefs
|
119
|
+
self.class.echo(msg)
|
303
120
|
end
|
304
121
|
end
|
305
122
|
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StandupMD
|
4
|
+
class Cli
|
5
|
+
|
6
|
+
##
|
7
|
+
# Module responsible for reading and writing standup files.
|
8
|
+
module Helpers
|
9
|
+
|
10
|
+
##
|
11
|
+
# Print an entry to the command line.
|
12
|
+
#
|
13
|
+
# @param [StandupMD::Entry] entry
|
14
|
+
#
|
15
|
+
# @return [nil]
|
16
|
+
def print(entry)
|
17
|
+
if entry.nil?
|
18
|
+
puts "No record found for #{StandupMD.config.cli.date}"
|
19
|
+
return
|
20
|
+
end
|
21
|
+
puts '#' * StandupMD.config.file.header_depth + ' ' + entry.date.strftime(StandupMD.config.file.header_date_format)
|
22
|
+
StandupMD.config.file.sub_header_order.each do |attr|
|
23
|
+
tasks = entry.send(attr)
|
24
|
+
next if !tasks || tasks.empty?
|
25
|
+
puts '#' * StandupMD.config.file.sub_header_depth + ' ' + StandupMD.config.file.send("#{attr}_header").capitalize
|
26
|
+
tasks.each { |task| puts StandupMD.config.file.bullet_character + ' ' + task }
|
27
|
+
end
|
28
|
+
puts
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
##
|
34
|
+
# Parses options passed at runtime and concatenates them with the options
|
35
|
+
# in the user's preferences file. Reveal source to see options.
|
36
|
+
#
|
37
|
+
# @return [Hash]
|
38
|
+
def set_preferences(options)
|
39
|
+
OptionParser.new do |opts|
|
40
|
+
opts.banner = 'The Standup Doctor'
|
41
|
+
opts.version = "[StandupMD] #{::StandupMD::VERSION}"
|
42
|
+
opts.on(
|
43
|
+
'--current ARRAY', Array,
|
44
|
+
"List of current entry's tasks"
|
45
|
+
) { |v| StandupMD.config.entry.current = v }
|
46
|
+
|
47
|
+
opts.on(
|
48
|
+
'--previous ARRAY', Array,
|
49
|
+
"List of precious entry's tasks"
|
50
|
+
) { |v| StandupMD.config.entry.previous = v }
|
51
|
+
|
52
|
+
opts.on(
|
53
|
+
'--impediments ARRAY', Array,
|
54
|
+
'List of impediments for current entry'
|
55
|
+
) { |v| StandupMD.config.entry.impediments = v }
|
56
|
+
|
57
|
+
opts.on(
|
58
|
+
'--notes ARRAY', Array,
|
59
|
+
'List of notes for current entry'
|
60
|
+
) { |v| StandupMD.config.entry.notes = v }
|
61
|
+
|
62
|
+
opts.on(
|
63
|
+
'--sub-header-order ARRAY', Array,
|
64
|
+
'The order of the sub-headers when writing the file'
|
65
|
+
) { |v| StandupMD.config.file.sub_header_order = v }
|
66
|
+
|
67
|
+
opts.on(
|
68
|
+
'-f', '--file-name-format STRING',
|
69
|
+
'Date-formattable string to use for standup file name'
|
70
|
+
) { |v| StandupMD.config.file.name_format = v }
|
71
|
+
|
72
|
+
opts.on(
|
73
|
+
'-E', '--editor EDITOR',
|
74
|
+
'Editor to use for opening standup files'
|
75
|
+
) { |v| StandupMD.config.cli.editor = v }
|
76
|
+
|
77
|
+
opts.on(
|
78
|
+
'-d', '--directory DIRECTORY',
|
79
|
+
'The directories where standup files are located'
|
80
|
+
) { |v| StandupMD.config.file.directory = v }
|
81
|
+
|
82
|
+
opts.on(
|
83
|
+
'-w', '--[no-]write',
|
84
|
+
"Write current entry if it doesn't exist. Default is true"
|
85
|
+
) { |v| StandupMD.config.cli.write = v }
|
86
|
+
|
87
|
+
opts.on(
|
88
|
+
'-a', '--[no-]auto-fill-previous',
|
89
|
+
"Auto-generate 'previous' tasks for new entries. Default is true"
|
90
|
+
) { |v| StandupMD.config.cli.auto_fill_previous = v }
|
91
|
+
|
92
|
+
opts.on(
|
93
|
+
'-e', '--[no-]edit',
|
94
|
+
'Open the file in the editor. Default is true'
|
95
|
+
) { |v| StandupMD.config.cli.edit = v }
|
96
|
+
|
97
|
+
opts.on(
|
98
|
+
'-v', '--[no-]verbose',
|
99
|
+
'Verbose output. Default is false.'
|
100
|
+
) { |v| StandupMD.config.cli.verbose = v }
|
101
|
+
|
102
|
+
opts.on(
|
103
|
+
'-p', '--print [DATE]',
|
104
|
+
'Print current entry.',
|
105
|
+
'If DATE is passed, will print entry for DATE, if it exists.',
|
106
|
+
'DATE must be in the same format as file-name-format',
|
107
|
+
) do |v|
|
108
|
+
StandupMD.config.cli.print = true
|
109
|
+
StandupMD.config.cli.date =
|
110
|
+
v.nil? ? Date.today : Date.strptime(v, StandupMD.config.file.header_date_format)
|
111
|
+
end
|
112
|
+
end.parse!(options)
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# The entry for today.
|
117
|
+
#
|
118
|
+
# @return [StandupMD::Entry]
|
119
|
+
def set_entry(file)
|
120
|
+
entry = file.entries.find(StandupMD.config.cli.date)
|
121
|
+
if entry.nil? && StandupMD.config.cli.date == Date.today
|
122
|
+
previous_entry = set_previous_entry(file)
|
123
|
+
entry = StandupMD::Entry.new(
|
124
|
+
StandupMD.config.cli.date,
|
125
|
+
StandupMD.config.entry.current,
|
126
|
+
previous_entry,
|
127
|
+
StandupMD.config.entry.impediments,
|
128
|
+
StandupMD.config.entry.notes
|
129
|
+
)
|
130
|
+
file.entries << entry
|
131
|
+
end
|
132
|
+
entry
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# The "previous" entries.
|
137
|
+
#
|
138
|
+
# @return [Array]
|
139
|
+
def set_previous_entry(file)
|
140
|
+
return [] unless StandupMD.config.cli.auto_fill_previous
|
141
|
+
return prev_entry(prev_file.load.entries) if file.new? && prev_file
|
142
|
+
prev_entry(file.entries)
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# The previous entry.
|
147
|
+
#
|
148
|
+
# @param [StandupMD::EntryList] entries
|
149
|
+
#
|
150
|
+
# @return [StandupMD::Entry]
|
151
|
+
def prev_entry(entries)
|
152
|
+
return [] if entries.empty?
|
153
|
+
entries.last.current
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# The previous month's file.
|
158
|
+
#
|
159
|
+
# @return [StandupMD::File]
|
160
|
+
def prev_file
|
161
|
+
StandupMD::File.find_by_date(Date.today.prev_month)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|