standup_md 0.2.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,29 +1,50 @@
1
- require 'json'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'optparse'
3
- require_relative '../standup_md'
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
- # The user's preference file.
12
- PREFERENCE_FILE =
13
- File.expand_path(File.join(ENV['HOME'], '.standup_md.yml')).freeze
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.print_current_entry if exe.print_current_entry?
22
- exe.print_all_entries if exe.print_all_entries?
23
- exe.write_file if exe.write?
24
- exe.edit if exe.edit?
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
- # Preferences after reading config file and parsing ARGV.
55
+ # The file loaded.
35
56
  #
36
- # @return [Array]
37
- attr_reader :preferences
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
- @edit = true
45
- @write = true
46
- @append_previous = true
47
- @print_current_entry = false
48
- @json = false
49
- @verbose = false
50
- @print_all_entries = false
51
- @options = options
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
- # Sets up an instance of +StandupMD+ and passes all user preferences.
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 preferences.key?('editor')
83
- echo "Editor set to [#{preferences.key('editor')}] via preferences"
84
- preferences.delete('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 print_current_entry
118
- echo 'Print current entry'
119
- unless json?
120
- print_entry(standup.header, standup.current_entry)
121
- return
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
- # Appends entries passed at runtime to existing previous entries.
89
+ # Has the preference file been loaded?
130
90
  #
131
- # @return [Hash]
132
- def append_to_previous_entry_tasks
133
- echo 'Appending previous entry tasks'
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} #{standup.file}")
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 'Writing file'
151
- standup.write
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
- # Should debug info be printed?
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
- puts msg if verbose?
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
- prefs['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