standup_md 0.3.3 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/standup_md.rb CHANGED
@@ -34,7 +34,7 @@ module StandupMD
34
34
  # @example
35
35
  # StandupMD.configure { |s| s.cli.editor = 'mate' }
36
36
  def self.configure
37
- yield self.config
37
+ yield config
38
38
  end
39
39
 
40
40
  ##
@@ -52,6 +52,7 @@ module StandupMD
52
52
  def self.load_config_file(file)
53
53
  file = ::File.expand_path(file)
54
54
  raise "File #{file} does not exist." unless ::File.file?(file)
55
+
55
56
  @config_file_loaded = true
56
57
  load file
57
58
  end
@@ -4,7 +4,6 @@ require 'optparse'
4
4
  require_relative 'cli/helpers'
5
5
 
6
6
  module StandupMD
7
-
8
7
  ##
9
8
  # Class for handing the command-line interface.
10
9
  class Cli
@@ -66,10 +65,10 @@ module StandupMD
66
65
  @preference_file_loaded = false
67
66
  @options = options
68
67
  load_preferences if load_config
69
- set_preferences(options)
68
+ load_runtime_preferences(options)
70
69
  @file = StandupMD::File.find_by_date(@config.date)
71
70
  @file.load
72
- @entry = set_entry(@file)
71
+ @entry = new_entry(@file)
73
72
  end
74
73
 
75
74
  ##
@@ -2,11 +2,9 @@
2
2
 
3
3
  module StandupMD
4
4
  class Cli
5
-
6
5
  ##
7
6
  # Module responsible for reading and writing standup files.
8
7
  module Helpers
9
-
10
8
  ##
11
9
  # Print an entry to the command line.
12
10
  #
@@ -15,99 +13,108 @@ module StandupMD
15
13
  # @return [nil]
16
14
  def print(entry)
17
15
  if entry.nil?
18
- puts "No record found for #{StandupMD.config.cli.date}"
16
+ puts "No record found for #{config.cli.date}"
19
17
  return
20
18
  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)
19
+ puts header(entry)
20
+ config.file.sub_header_order.each do |header_type|
21
+ tasks = entry.public_send(header_type)
24
22
  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 }
23
+
24
+ puts sub_header(header_type)
25
+ tasks.each { |task| puts config.file.bullet_character + ' ' + task }
27
26
  end
28
27
  puts
29
28
  end
30
29
 
31
30
  private
32
31
 
32
+ ##
33
+ # Helper for accessing config.
34
+ #
35
+ # @return [StandupMD::Config]
36
+ def config # :nodoc:
37
+ StandupMD.config
38
+ end
39
+
33
40
  ##
34
41
  # Parses options passed at runtime and concatenates them with the options
35
42
  # in the user's preferences file. Reveal source to see options.
36
43
  #
37
44
  # @return [Hash]
38
- def set_preferences(options)
45
+ def load_runtime_preferences(options)
39
46
  OptionParser.new do |opts|
40
47
  opts.banner = 'The Standup Doctor'
41
- opts.version = "[StandupMD] #{::StandupMD::VERSION}"
48
+ opts.version = "[StandupMD] #{::StandupMD::Version}"
42
49
  opts.on(
43
50
  '--current ARRAY', Array,
44
51
  "List of current entry's tasks"
45
- ) { |v| StandupMD.config.entry.current = v }
52
+ ) { |v| config.entry.current = v }
46
53
 
47
54
  opts.on(
48
55
  '--previous ARRAY', Array,
49
56
  "List of precious entry's tasks"
50
- ) { |v| StandupMD.config.entry.previous = v }
57
+ ) { |v| config.entry.previous = v }
51
58
 
52
59
  opts.on(
53
60
  '--impediments ARRAY', Array,
54
61
  'List of impediments for current entry'
55
- ) { |v| StandupMD.config.entry.impediments = v }
62
+ ) { |v| config.entry.impediments = v }
56
63
 
57
64
  opts.on(
58
65
  '--notes ARRAY', Array,
59
66
  'List of notes for current entry'
60
- ) { |v| StandupMD.config.entry.notes = v }
67
+ ) { |v| config.entry.notes = v }
61
68
 
62
69
  opts.on(
63
70
  '--sub-header-order ARRAY', Array,
64
71
  'The order of the sub-headers when writing the file'
65
- ) { |v| StandupMD.config.file.sub_header_order = v }
72
+ ) { |v| config.file.sub_header_order = v }
66
73
 
67
74
  opts.on(
68
75
  '-f', '--file-name-format STRING',
69
76
  'Date-formattable string to use for standup file name'
70
- ) { |v| StandupMD.config.file.name_format = v }
77
+ ) { |v| config.file.name_format = v }
71
78
 
72
79
  opts.on(
73
80
  '-E', '--editor EDITOR',
74
81
  'Editor to use for opening standup files'
75
- ) { |v| StandupMD.config.cli.editor = v }
82
+ ) { |v| config.cli.editor = v }
76
83
 
77
84
  opts.on(
78
85
  '-d', '--directory DIRECTORY',
79
86
  'The directories where standup files are located'
80
- ) { |v| StandupMD.config.file.directory = v }
87
+ ) { |v| config.file.directory = v }
81
88
 
82
89
  opts.on(
83
90
  '-w', '--[no-]write',
84
91
  "Write current entry if it doesn't exist. Default is true"
85
- ) { |v| StandupMD.config.cli.write = v }
92
+ ) { |v| config.cli.write = v }
86
93
 
87
94
  opts.on(
88
95
  '-a', '--[no-]auto-fill-previous',
89
96
  "Auto-generate 'previous' tasks for new entries. Default is true"
90
- ) { |v| StandupMD.config.cli.auto_fill_previous = v }
97
+ ) { |v| config.cli.auto_fill_previous = v }
91
98
 
92
99
  opts.on(
93
100
  '-e', '--[no-]edit',
94
101
  'Open the file in the editor. Default is true'
95
- ) { |v| StandupMD.config.cli.edit = v }
102
+ ) { |v| config.cli.edit = v }
96
103
 
97
104
  opts.on(
98
105
  '-v', '--[no-]verbose',
99
106
  'Verbose output. Default is false.'
100
- ) { |v| StandupMD.config.cli.verbose = v }
107
+ ) { |v| config.cli.verbose = v }
101
108
 
102
109
  opts.on(
103
110
  '-p', '--print [DATE]',
104
111
  'Print current entry.',
105
112
  'If DATE is passed, will print entry for DATE, if it exists.',
106
- 'DATE must be in the same format as file-name-format',
113
+ 'DATE must be in the same format as file-name-format'
107
114
  ) 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)
115
+ config.cli.print = true
116
+ config.cli.date =
117
+ v.nil? ? Date.today : Date.strptime(v, config.file.header_date_format)
111
118
  end
112
119
  end.parse!(options)
113
120
  end
@@ -116,16 +123,16 @@ module StandupMD
116
123
  # The entry for today.
117
124
  #
118
125
  # @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
126
+ def new_entry(file)
127
+ entry = file.entries.find(config.cli.date)
128
+ if entry.nil? && config.cli.date == Date.today
122
129
  previous_entry = set_previous_entry(file)
123
130
  entry = StandupMD::Entry.new(
124
- StandupMD.config.cli.date,
125
- StandupMD.config.entry.current,
131
+ config.cli.date,
132
+ config.entry.current,
126
133
  previous_entry,
127
- StandupMD.config.entry.impediments,
128
- StandupMD.config.entry.notes
134
+ config.entry.impediments,
135
+ config.entry.notes
129
136
  )
130
137
  file.entries << entry
131
138
  end
@@ -137,8 +144,10 @@ module StandupMD
137
144
  #
138
145
  # @return [Array]
139
146
  def set_previous_entry(file)
140
- return [] unless StandupMD.config.cli.auto_fill_previous
147
+ return config.entry.previous_entry unless config.cli.auto_fill_previous
148
+
141
149
  return prev_entry(prev_file.load.entries) if file.new? && prev_file
150
+
142
151
  prev_entry(file.entries)
143
152
  end
144
153
 
@@ -150,6 +159,7 @@ module StandupMD
150
159
  # @return [StandupMD::Entry]
151
160
  def prev_entry(entries)
152
161
  return [] if entries.empty?
162
+
153
163
  entries.last.current
154
164
  end
155
165
 
@@ -160,6 +170,28 @@ module StandupMD
160
170
  def prev_file
161
171
  StandupMD::File.find_by_date(Date.today.prev_month)
162
172
  end
173
+
174
+ ##
175
+ # The header.
176
+ #
177
+ # @param [StandupMD::Entry] entry
178
+ #
179
+ # @return [String]
180
+ def header(entry)
181
+ '#' * config.file.header_depth + ' ' +
182
+ entry.date.strftime(config.file.header_date_format)
183
+ end
184
+
185
+ ##
186
+ # The sub-header.
187
+ #
188
+ # @param [String] header_type
189
+ #
190
+ # @return [String]
191
+ def sub_header(header_type)
192
+ '#' * config.file.sub_header_depth + ' ' +
193
+ config.file.public_send("#{header_type}_header").capitalize
194
+ end
163
195
  end
164
196
  end
165
197
  end
@@ -6,11 +6,9 @@ require_relative 'config/entry'
6
6
  require_relative 'config/entry_list'
7
7
 
8
8
  module StandupMD
9
-
10
9
  ##
11
10
  # This class provides a connector from StandupMD to the configuration classes.
12
11
  class Config
13
-
14
12
  ##
15
13
  # Reader for Cli config.
16
14
  #
@@ -4,11 +4,9 @@ require 'date'
4
4
 
5
5
  module StandupMD
6
6
  class Config
7
-
8
7
  ##
9
8
  # The configuration class for StandupMD::Cli
10
9
  class Cli
11
-
12
10
  ##
13
11
  # The default options.
14
12
  #
@@ -22,8 +20,8 @@ module StandupMD
22
20
  print: false,
23
21
  auto_fill_previous: true,
24
22
  preference_file:
25
- ::File.expand_path(::File.join(ENV['HOME'], '.standuprc')),
26
- }
23
+ ::File.expand_path(::File.join(ENV['HOME'], '.standuprc'))
24
+ }.freeze
27
25
 
28
26
  ##
29
27
  # The editor to use when opening standup files. If one is not set, the
@@ -2,11 +2,9 @@
2
2
 
3
3
  module StandupMD
4
4
  class Config
5
-
6
5
  ##
7
6
  # The configuration class for StandupMD::Entry
8
7
  class Entry
9
-
10
8
  ##
11
9
  # The default options.
12
10
  #
@@ -15,8 +13,8 @@ module StandupMD
15
13
  current: ["<!-- ADD TODAY'S WORK HERE -->"],
16
14
  previous: [],
17
15
  impediments: ['None'],
18
- notes: [],
19
- }
16
+ notes: []
17
+ }.freeze
20
18
 
21
19
  ##
22
20
  # Tasks for "Current" section.
@@ -3,7 +3,6 @@
3
3
  require 'json'
4
4
 
5
5
  module StandupMD
6
-
7
6
  ##
8
7
  # Class for handling single entries. Includes the comparable module, and
9
8
  # compares by date.
@@ -39,7 +38,7 @@ module StandupMD
39
38
  attr_accessor :previous
40
39
 
41
40
  ##
42
- # Iimpediments for this entry.
41
+ # Impediments for this entry.
43
42
  #
44
43
  # @return [Array]
45
44
  attr_accessor :impediments
@@ -56,15 +55,13 @@ module StandupMD
56
55
  #
57
56
  # @return [StandupMD::Entry]
58
57
  def self.create
59
- entry = new(
58
+ new(
60
59
  Date.today,
61
60
  config.current,
62
61
  config.previous,
63
62
  config.impediments,
64
63
  config.notes
65
- )
66
- yield config if block_given?
67
- entry
64
+ ).tap { |entry| yield entry if block_given? }
68
65
  end
69
66
 
70
67
  ##
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module StandupMD
3
+ require 'forwardable'
4
4
 
5
+ module StandupMD
5
6
  ##
6
7
  # Enumerable list of entries.
7
8
  class EntryList
9
+ extend Forwardable
8
10
  include Enumerable
9
11
 
10
12
  ##
@@ -29,12 +31,6 @@ module StandupMD
29
31
  @entries = entries
30
32
  end
31
33
 
32
- ##
33
- # Iterate over the list and yield each entry.
34
- def each(&block)
35
- @entries.each(&block)
36
- end
37
-
38
34
  ##
39
35
  # Appends entries to list.
40
36
  #
@@ -51,8 +47,12 @@ module StandupMD
51
47
  ##
52
48
  # Finds an entry based on date. This method assumes the list has already
53
49
  # been sorted.
54
- def find(key)
55
- to_a.bsearch { |e| e.date == key }
50
+ #
51
+ # @param [Date] date
52
+ #
53
+ # @return [StandupMD::Entry]
54
+ def find(date)
55
+ entries.bsearch { |e| e.date == date }
56
56
  end
57
57
 
58
58
  ##
@@ -129,38 +129,21 @@ module StandupMD
129
129
  to_h.to_json
130
130
  end
131
131
 
132
- ##
133
- # The first entry in the list. This method assumes the list has
134
- # already been sorted.
135
- #
136
- # @return [StandupMD::Entry]
137
- def first
138
- to_a.first
139
- end
132
+ # :section: Delegators
140
133
 
141
134
  ##
142
- # The last entry in the list. This method assumes the list has
143
- # already been sorted.
135
+ # The following are forwarded to @entries, which is the underly array of
136
+ # entries.
144
137
  #
145
- # @return [StandupMD::Entry]
146
- def last
147
- to_a.last
148
- end
149
-
150
- ##
151
- # How many entries are in the list.
138
+ # +each+:: Iterate over each entry.
152
139
  #
153
- # @return [Integer]
154
- def size
155
- @entries.size
156
- end
157
-
158
- ##
159
- # Is the list empty?
140
+ # +empty?+:: Is the list empty?
160
141
  #
161
- # @return [Boolean] true if empty
162
- def empty?
163
- @entries.empty?
164
- end
142
+ # +size+:: How many items are in the list?
143
+ #
144
+ # +first+:: The first record in the list.
145
+ #
146
+ # +last+:: The last record in the list.
147
+ def_delegators :@entries, :each, :empty?, :size, :first, :last
165
148
  end
166
149
  end
@@ -5,7 +5,6 @@ require 'fileutils'
5
5
  require_relative 'file/helpers'
6
6
 
7
7
  module StandupMD
8
-
9
8
  ##
10
9
  # Class for handling reading and writing standup files.
11
10
  class File
@@ -26,6 +25,11 @@ module StandupMD
26
25
  #
27
26
  # @return [StandupMD::File]
28
27
  def self.load(file_name)
28
+ unless ::File.directory?(config.directory)
29
+ raise "Dir #{config.directory} not found." unless config.create
30
+
31
+ FileUtils.mkdir_p(config.directory)
32
+ end
29
33
  new(file_name).load
30
34
  end
31
35
 
@@ -34,10 +38,14 @@ module StandupMD
34
38
  #
35
39
  # @param [String] File_naem
36
40
  def self.find(file_name)
37
- file = Dir.entries(config.directory).bsearch { |f| f == file_name }
38
- if file.nil? && !config.create
39
- raise "File #{file_name} not found." unless config.create
41
+ unless ::File.directory?(config.directory)
42
+ raise "Dir #{config.directory} not found." unless config.create
43
+
44
+ FileUtils.mkdir_p(config.directory)
40
45
  end
46
+ file = Dir.entries(config.directory).bsearch { |f| f == file_name }
47
+ raise "File #{file_name} not found." if file.nil? && !config.create
48
+
41
49
  new(file_name)
42
50
  end
43
51
 
@@ -46,8 +54,12 @@ module StandupMD
46
54
  #
47
55
  # @param [Date] date
48
56
  def self.find_by_date(date)
49
- unless date.is_a?(Date)
50
- raise ArgumentError, "Argument must be a Date object"
57
+ raise ArgumentError, 'Must be a Date object' unless date.is_a?(Date)
58
+
59
+ unless ::File.directory?(config.directory)
60
+ raise "Dir #{config.directory} not found." unless config.create
61
+
62
+ FileUtils.mkdir_p(config.directory)
51
63
  end
52
64
  find(date.strftime(config.name_format))
53
65
  end
@@ -79,6 +91,7 @@ module StandupMD
79
91
 
80
92
  unless ::File.directory?(@config.directory)
81
93
  raise "Dir #{@config.directory} not found." unless @config.create
94
+
82
95
  FileUtils.mkdir_p(@config.directory)
83
96
  end
84
97
 
@@ -86,6 +99,7 @@ module StandupMD
86
99
 
87
100
  unless ::File.file?(@name)
88
101
  raise "File #{@name} not found." unless @config.create
102
+
89
103
  FileUtils.touch(@name)
90
104
  end
91
105
 
@@ -124,21 +138,23 @@ module StandupMD
124
138
  # @return [StandupMD::FileList]
125
139
  def load
126
140
  raise "File #{name} does not exist." unless ::File.file?(name)
141
+
127
142
  entry_list = EntryList.new
128
143
  record = {}
129
144
  section_type = ''
130
145
  ::File.foreach(name) do |line|
131
146
  line.chomp!
132
147
  next if line.strip.empty?
133
- if is_header?(line)
148
+
149
+ if header?(line)
134
150
  unless record.empty?
135
151
  entry_list << new_entry(record)
136
152
  record = {}
137
153
  end
138
- record['header'] = line.sub(%r{^\#{#{@config.header_depth}}\s*}, '')
139
- section_type = @config.notes_header
140
- record[section_type] = []
141
- elsif is_sub_header?(line)
154
+ record['header'] = line.sub(/^\#{#{@config.header_depth}}\s*/, '')
155
+ section_type = @config.notes_header
156
+ record[section_type] = []
157
+ elsif sub_header?(line)
142
158
  section_type = determine_section_type(line)
143
159
  record[section_type] = []
144
160
  else
@@ -158,10 +174,10 @@ module StandupMD
158
174
  # This method is destructive; if a file for entries in the date range
159
175
  # already exists, it will be clobbered with the entries in the range.
160
176
  #
161
- # @param [Hash] start_and_end_date
177
+ # @param [Hash] {start_date: Date, end_date: Date}
162
178
  #
163
179
  # @return [Boolean] true if successful
164
- def write(dates = {})
180
+ def write(**dates)
165
181
  sorted_entries = entries.sort
166
182
  start_date = dates.fetch(:start_date, sorted_entries.first.date)
167
183
  end_date = dates.fetch(:end_date, sorted_entries.last.date)
@@ -169,9 +185,10 @@ module StandupMD
169
185
  sorted_entries.filter(start_date, end_date).sort_reverse.each do |entry|
170
186
  f.puts header(entry.date)
171
187
  @config.sub_header_order.each do |attr|
172
- tasks = entry.send(attr)
188
+ tasks = entry.public_send(attr)
173
189
  next if !tasks || tasks.empty?
174
- f.puts sub_header(@config.send("#{attr}_header").capitalize)
190
+
191
+ f.puts sub_header(@config.public_send("#{attr}_header").capitalize)
175
192
  tasks.each { |task| f.puts @config.bullet_character + ' ' + task }
176
193
  end
177
194
  f.puts