standup_md 0.3.3 → 0.3.8

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.
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