standup_md 0.3.14 → 0.3.16

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.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'optparse'
4
- require_relative 'cli/helpers'
3
+ require "optparse"
4
+ require "standup_md/cli/helpers"
5
5
 
6
6
  module StandupMD
7
7
  ##
@@ -29,7 +29,7 @@ module StandupMD
29
29
  # Creates an instance of +StandupMD+ and runs what the user requested.
30
30
  def self.execute(options = [])
31
31
  new(options).tap do |exe|
32
- exe.write_file if config.write
32
+ exe.write_file if exe.write?
33
33
  if config.print
34
34
  exe.print(exe.entry)
35
35
  elsif config.edit
@@ -56,19 +56,28 @@ module StandupMD
56
56
  # @return [StandupMD::File]
57
57
  attr_reader :file
58
58
 
59
+ ##
60
+ # Was a file date argument passed?
61
+ #
62
+ # @return [Boolean]
63
+ def file_date_argument?
64
+ @file_date_argument
65
+ end
66
+
59
67
  ##
60
68
  # Constructor. Sets defaults.
61
69
  #
62
70
  # @param [Array] options
63
- def initialize(options = [], load_config = true)
71
+ def initialize(options = [], load_config: true)
64
72
  @config = self.class.config
65
73
  @preference_file_loaded = false
74
+ @file_date_argument = false
66
75
  @options = options
67
76
  load_preferences if load_config
68
77
  load_runtime_preferences(options)
69
- @file = StandupMD::File.find_by_date(@config.date)
70
- @file.load
71
- @entry = new_entry(@file)
78
+ @file = find_file
79
+ @file&.load
80
+ @entry = @file.nil? ? nil : new_entry(@file)
72
81
  end
73
82
 
74
83
  ##
@@ -87,7 +96,7 @@ module StandupMD
87
96
  ##
88
97
  # Has the preference file been loaded?
89
98
  #
90
- # @return boolean
99
+ # @return [boolean]
91
100
  def preference_file_loaded?
92
101
  @preference_file_loaded
93
102
  end
@@ -111,11 +120,55 @@ module StandupMD
111
120
  end
112
121
 
113
122
  ##
114
- # Quick access to Cli.echo.
123
+ # Should the file be written?
124
+ #
125
+ # @return [Boolean]
126
+ def write?
127
+ !!(@config.write && !read_only? && entry)
128
+ end
129
+
130
+ ##
131
+ # Quick access to +Cli.echo+.
115
132
  #
116
133
  # @return [nil]
117
134
  def echo(msg)
118
135
  self.class.echo(msg)
119
136
  end
137
+
138
+ private
139
+
140
+ ##
141
+ # Is this a read-only action?
142
+ #
143
+ # @return [Boolean]
144
+ def read_only?
145
+ @config.print || file_date_argument?
146
+ end
147
+
148
+ ##
149
+ # Finds the file, avoiding file creation for read-only actions.
150
+ #
151
+ # @return [StandupMD::File, nil]
152
+ def find_file
153
+ return StandupMD::File.find_by_date(@config.date) unless read_only?
154
+
155
+ without_file_creation { StandupMD::File.find_by_date(@config.date) }
156
+ rescue
157
+ raise unless @config.print
158
+
159
+ nil
160
+ end
161
+
162
+ ##
163
+ # Temporarily disables file creation while looking for a file.
164
+ #
165
+ # @return [StandupMD::File]
166
+ def without_file_creation
167
+ original_create = config.file.create
168
+ config.file.create = false
169
+ yield
170
+ ensure
171
+ config.file.create = original_create
172
+ end
120
173
  end
121
174
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
3
+ require "date"
4
4
 
5
5
  module StandupMD
6
6
  class Config
@@ -13,14 +13,14 @@ module StandupMD
13
13
  # @return [Hash]
14
14
  DEFAULTS = {
15
15
  date: Date.today,
16
- editor: ENV['VISUAL'] || ENV['EDITOR'] || 'vim',
16
+ editor: ENV["VISUAL"] || ENV["EDITOR"] || "vim",
17
17
  verbose: false,
18
18
  edit: true,
19
19
  write: true,
20
20
  print: false,
21
21
  auto_fill_previous: true,
22
22
  preference_file: ::File.expand_path(
23
- ::File.join(ENV['HOME'], '.standuprc')
23
+ ::File.join(ENV["HOME"], ".standuprc")
24
24
  )
25
25
  }.freeze
26
26
 
@@ -12,7 +12,7 @@ module StandupMD
12
12
  DEFAULTS = {
13
13
  current: ["<!-- ADD TODAY'S WORK HERE -->"],
14
14
  previous: [],
15
- impediments: ['None'],
15
+ impediments: ["None"],
16
16
  notes: []
17
17
  }.freeze
18
18
 
@@ -9,7 +9,7 @@ module StandupMD
9
9
  # The default options.
10
10
  #
11
11
  # @return [Hash]
12
- DEFAULTS = {}
12
+ DEFAULTS = {}.freeze
13
13
 
14
14
  ##
15
15
  # Initializes the config with default values.
@@ -10,19 +10,19 @@ module StandupMD
10
10
  #
11
11
  # @return [Hash]
12
12
  DEFAULTS = {
13
- header_date_format: '%Y-%m-%d',
13
+ header_date_format: "%Y-%m-%d",
14
14
  header_depth: 1,
15
15
  sub_header_depth: 2,
16
- current_header: 'Current',
17
- previous_header: 'Previous',
18
- impediments_header: 'Impediments',
19
- notes_header: 'Notes',
16
+ current_header: "Current",
17
+ previous_header: "Previous",
18
+ impediments_header: "Impediments",
19
+ notes_header: "Notes",
20
20
  sub_header_order: %w[previous current impediments notes],
21
- directory: ::File.join(ENV['HOME'], '.cache', 'standup_md'),
22
- bullet_character: '-',
23
- name_format: '%Y_%m.md',
24
- create: true,
25
- }
21
+ directory: ::File.join(ENV["HOME"], ".cache", "standup_md"),
22
+ bullet_character: "-",
23
+ name_format: "%Y_%m.md",
24
+ create: true
25
+ }.freeze
26
26
 
27
27
  ##
28
28
  # Number of octothorps that should preface entry headers.
@@ -154,7 +154,7 @@ module StandupMD
154
154
  #
155
155
  # @return [Integer]
156
156
  def header_depth=(depth)
157
- raise 'Header depth out of bounds (1..5)' if !depth.between?(1, 5)
157
+ raise "Header depth out of bounds (1..5)" if !depth.between?(1, 5)
158
158
 
159
159
  @sub_header_depth = depth + 1 if depth >= sub_header_depth
160
160
  @header_depth = depth
@@ -168,7 +168,7 @@ module StandupMD
168
168
  #
169
169
  # @return [Integer]
170
170
  def sub_header_depth=(depth)
171
- raise 'Sub-header depth out of bounds (2..6)' if !depth.between?(2, 6)
171
+ raise "Sub-header depth out of bounds (2..6)" if !depth.between?(2, 6)
172
172
 
173
173
  @header_depth = depth - 1 if depth <= header_depth
174
174
  @sub_header_depth = depth
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'config/cli'
4
- require_relative 'config/file'
5
- require_relative 'config/entry'
6
- require_relative 'config/entry_list'
3
+ require "standup_md/config/cli"
4
+ require "standup_md/config/file"
5
+ require "standup_md/config/entry"
6
+ require "standup_md/config/entry_list"
7
7
 
8
8
  module StandupMD
9
9
  ##
@@ -36,9 +36,9 @@ module StandupMD
36
36
  ##
37
37
  # Builds the links to the configuration classes.
38
38
  def initialize
39
- @cli = StandupMD::Config::Cli.new
40
- @file = StandupMD::Config::File.new
41
- @entry = StandupMD::Config::Entry.new
39
+ @cli = StandupMD::Config::Cli.new
40
+ @file = StandupMD::Config::File.new
41
+ @entry = StandupMD::Config::Entry.new
42
42
  @entry_list = StandupMD::Config::EntryList.new
43
43
  end
44
44
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
3
+ require "json"
4
4
 
5
5
  module StandupMD
6
6
  ##
@@ -100,10 +100,10 @@ module StandupMD
100
100
  def to_h
101
101
  {
102
102
  date => {
103
- 'current' => current,
104
- 'previous' => previous,
105
- 'impediments' => impediments,
106
- 'notes' => notes
103
+ "current" => current,
104
+ "previous" => previous,
105
+ "impediments" => impediments,
106
+ "notes" => notes
107
107
  }
108
108
  }
109
109
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
3
+ require "forwardable"
4
4
 
5
5
  module StandupMD
6
6
  ##
@@ -50,7 +50,7 @@ module StandupMD
50
50
  #
51
51
  # @return [StandupMD::Entry]
52
52
  def find(date)
53
- entries.bsearch { |e| e.date == date }
53
+ entries.bsearch { |entry| date <=> entry.date }
54
54
  end
55
55
 
56
56
  ##
@@ -71,7 +71,7 @@ module StandupMD
71
71
  end
72
72
 
73
73
  ##
74
- # Returns a copy of self sorted by date.
74
+ # Returns a copy of self sorted by date, reversed.
75
75
  #
76
76
  # @return [StandupMD::EntryList]
77
77
  def sort_reverse
@@ -111,12 +111,17 @@ module StandupMD
111
111
  #
112
112
  # @return [Hash]
113
113
  def to_h
114
- Hash[@entries.map { |e| [e.date, {
115
- 'current' => e.current,
116
- 'previous' => e.previous,
117
- 'impediments' => e.impediments,
118
- 'notes' => e.notes
119
- }]}]
114
+ @entries.map do |e|
115
+ [
116
+ e.date,
117
+ {
118
+ "current" => e.current,
119
+ "previous" => e.previous,
120
+ "impediments" => e.impediments,
121
+ "notes" => e.notes
122
+ }
123
+ ]
124
+ end.to_h
120
125
  end
121
126
 
122
127
  ##
@@ -149,7 +154,7 @@ module StandupMD
149
154
  def validate_entry(entry)
150
155
  return if entry.is_a?(StandupMD::Entry)
151
156
 
152
- raise ArgumentError, 'Entry must be an instance of StandupMD::Entry'
157
+ raise ArgumentError, "Entry must be an instance of StandupMD::Entry"
153
158
  end
154
159
  end
155
160
  end
@@ -16,11 +16,11 @@ module StandupMD
16
16
  end
17
17
 
18
18
  def header_regex # :nodoc:
19
- /^#{'#' * StandupMD.config.file.header_depth}\s+/
19
+ /^#{"#" * StandupMD.config.file.header_depth}\s+/
20
20
  end
21
21
 
22
22
  def sub_header_regex # :nodoc:
23
- /^#{'#' * StandupMD.config.file.sub_header_depth}\s+/
23
+ /^#{"#" * StandupMD.config.file.sub_header_depth}\s+/
24
24
  end
25
25
 
26
26
  def bullet_character_regex # :nodoc:
@@ -28,7 +28,7 @@ module StandupMD
28
28
  end
29
29
 
30
30
  def determine_section_type(line) # :nodoc:
31
- line = line.sub(/^\#{#{StandupMD.config.file.sub_header_depth}}\s*/, '')
31
+ line = line.sub(/^\#{#{StandupMD.config.file.sub_header_depth}}\s*/, "")
32
32
  [
33
33
  StandupMD.config.file.current_header,
34
34
  StandupMD.config.file.previous_header,
@@ -41,7 +41,7 @@ module StandupMD
41
41
  def new_entry(record) # :nodoc:
42
42
  Entry.new(
43
43
  Date.strptime(
44
- record['header'],
44
+ record["header"],
45
45
  StandupMD.config.file.header_date_format
46
46
  ),
47
47
  record[StandupMD.config.file.current_header],
@@ -52,13 +52,13 @@ module StandupMD
52
52
  end
53
53
 
54
54
  def header(date)
55
- '#' * StandupMD.config.file.header_depth +
56
- ' ' +
55
+ "#" * StandupMD.config.file.header_depth +
56
+ " " +
57
57
  date.strftime(StandupMD.config.file.header_date_format)
58
58
  end
59
59
 
60
60
  def sub_header(subhead)
61
- '#' * StandupMD.config.file.sub_header_depth + ' ' + subhead
61
+ "#" * StandupMD.config.file.sub_header_depth + " " + subhead
62
62
  end
63
63
  end
64
64
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
4
- require 'fileutils'
5
- require_relative 'file/helpers'
3
+ require "date"
4
+ require "fileutils"
5
+ require "standup_md/file/helpers"
6
6
 
7
7
  module StandupMD
8
8
  ##
@@ -10,58 +10,62 @@ module StandupMD
10
10
  class File
11
11
  include StandupMD::File::Helpers
12
12
 
13
- ##
14
- # Access to the class's configuration.
15
- #
16
- # @return [StandupMD::Config::EntryList]
17
- def self.config
18
- @config ||= StandupMD.config.file
19
- end
20
-
21
- ##
22
- # Convenience method for calling File.find(file_name).load
23
- #
24
- # @param [String] file_name
25
- #
26
- # @return [StandupMD::File]
27
- def self.load(file_name)
28
- unless ::File.directory?(config.directory)
29
- raise "Dir #{config.directory} not found." unless config.create
13
+ class << self
14
+ ##
15
+ # Access to the class's configuration.
16
+ #
17
+ # @return [StandupMD::Config::EntryList]
18
+ def config
19
+ @config ||= StandupMD.config.file
20
+ end
30
21
 
31
- FileUtils.mkdir_p(config.directory)
22
+ ##
23
+ # Convenience method for calling File.find(file_name).load
24
+ #
25
+ # @param [String] file_name
26
+ #
27
+ # @return [StandupMD::File]
28
+ def load(file_name)
29
+ unless ::File.directory?(config.directory)
30
+ raise "Dir #{config.directory} not found." unless config.create
31
+
32
+ FileUtils.mkdir_p(config.directory)
33
+ end
34
+ new(file_name).load
32
35
  end
33
- new(file_name).load
34
- end
35
36
 
36
- ##
37
- # Find standup file in directory by file name.
38
- #
39
- # @param [String] File_naem
40
- def self.find(file_name)
41
- unless ::File.directory?(config.directory)
42
- raise "Dir #{config.directory} not found." unless config.create
37
+ ##
38
+ # Find standup file in directory by file name.
39
+ #
40
+ # @param [String] File_naem
41
+ def find(file_name)
42
+ unless ::File.directory?(config.directory)
43
+ raise "Dir #{config.directory} not found." unless config.create
43
44
 
44
- FileUtils.mkdir_p(config.directory)
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
45
+ FileUtils.mkdir_p(config.directory)
46
+ end
47
+ file_path = ::File.join(config.directory, file_name)
48
+ unless ::File.file?(file_path) || config.create
49
+ raise "File #{file_name} not found."
50
+ end
48
51
 
49
- new(file_name)
50
- end
52
+ new(file_name)
53
+ end
51
54
 
52
- ##
53
- # Find standup file in directory by Date object.
54
- #
55
- # @param [Date] date
56
- def self.find_by_date(date)
57
- raise ArgumentError, 'Must be a Date object' unless date.is_a?(Date)
55
+ ##
56
+ # Find standup file in directory by Date object.
57
+ #
58
+ # @param [Date] date
59
+ def find_by_date(date)
60
+ raise ArgumentError, "Must be a Date object" unless date.is_a?(Date)
58
61
 
59
- unless ::File.directory?(config.directory)
60
- raise "Dir #{config.directory} not found." unless config.create
62
+ unless ::File.directory?(config.directory)
63
+ raise "Dir #{config.directory} not found." unless config.create
61
64
 
62
- FileUtils.mkdir_p(config.directory)
65
+ FileUtils.mkdir_p(config.directory)
66
+ end
67
+ find(date.strftime(config.name_format))
63
68
  end
64
- find(date.strftime(config.name_format))
65
69
  end
66
70
 
67
71
  ##
@@ -141,7 +145,7 @@ module StandupMD
141
145
 
142
146
  entry_list = EntryList.new
143
147
  record = {}
144
- section_type = ''
148
+ section_type = ""
145
149
  ::File.foreach(name) do |line|
146
150
  line.chomp!
147
151
  next if line.strip.empty?
@@ -151,14 +155,14 @@ module StandupMD
151
155
  entry_list << new_entry(record)
152
156
  record = {}
153
157
  end
154
- record['header'] = line.sub(/^\#{#{@config.header_depth}}\s*/, '')
158
+ record["header"] = line.sub(/^\#{#{@config.header_depth}}\s*/, "")
155
159
  section_type = @config.notes_header
156
160
  record[section_type] = []
157
161
  elsif sub_header?(line)
158
162
  section_type = determine_section_type(line)
159
163
  record[section_type] = []
160
164
  else
161
- record[section_type] << line.sub(bullet_character_regex, '')
165
+ record[section_type] << line.sub(bullet_character_regex, "")
162
166
  end
163
167
  end
164
168
  entry_list << new_entry(record) unless record.empty?
@@ -181,7 +185,7 @@ module StandupMD
181
185
  sorted_entries = entries.sort
182
186
  start_date = dates.fetch(:start_date, sorted_entries.first.date)
183
187
  end_date = dates.fetch(:end_date, sorted_entries.last.date)
184
- ::File.open(name, 'w') do |f|
188
+ ::File.open(name, "w") do |f|
185
189
  sorted_entries.filter(start_date, end_date).sort_reverse.each do |entry|
186
190
  f.puts header(entry.date)
187
191
  @config.sub_header_order.each do |attr|
@@ -189,7 +193,7 @@ module StandupMD
189
193
  next if !tasks || tasks.empty?
190
194
 
191
195
  f.puts sub_header(@config.public_send("#{attr}_header").capitalize)
192
- tasks.each { |task| f.puts @config.bullet_character + ' ' + task }
196
+ tasks.each { |task| f.puts "#{@config.bullet_character} #{task}" }
193
197
  end
194
198
  f.puts
195
199
  end
@@ -21,7 +21,7 @@ module StandupMD
21
21
  # Patch version.
22
22
  #
23
23
  # @return [Integer]
24
- PATCH = 14
24
+ PATCH = 16
25
25
 
26
26
  ##
27
27
  # Version as +[MAJOR, MINOR, PATCH]+
@@ -36,7 +36,7 @@ module StandupMD
36
36
  #
37
37
  # @return [String]
38
38
  def self.to_s
39
- to_a.join('.')
39
+ to_a.join(".")
40
40
  end
41
41
 
42
42
  ##
@@ -44,7 +44,7 @@ module StandupMD
44
44
  #
45
45
  # @return [Hash]
46
46
  def self.to_h
47
- Hash[%i[major minor patch].zip(to_a)]
47
+ %i[major minor patch].zip(to_a).to_h
48
48
  end
49
49
  end
50
50
 
data/lib/standup_md.rb CHANGED
@@ -1,22 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'standup_md/version'
4
- require_relative 'standup_md/file'
5
- require_relative 'standup_md/entry'
6
- require_relative 'standup_md/entry_list'
7
- require_relative 'standup_md/cli'
8
- require_relative 'standup_md/config'
3
+ require "standup_md/version"
4
+ require "standup_md/file"
5
+ require "standup_md/entry"
6
+ require "standup_md/entry_list"
7
+ require "standup_md/cli"
8
+ require "standup_md/config"
9
9
 
10
10
  ##
11
11
  # The main module for the gem. Provides access to configuration classes.
12
12
  module StandupMD
13
13
  @config_file_loaded = false
14
14
 
15
+ module_function
16
+
15
17
  ##
16
18
  # Method for accessing the configuration.
17
19
  #
18
- # @return [StanupMD::Cli]
19
- def self.config
20
+ # @return [StanupMD::Config]
21
+ def config
20
22
  @config || reset_config
21
23
  end
22
24
 
@@ -24,7 +26,7 @@ module StandupMD
24
26
  # Reset all configuration values to their defaults.
25
27
  #
26
28
  # @return [StandupMD::Config]
27
- def self.reset_config
29
+ def reset_config
28
30
  @config = StandupMD::Config.new
29
31
  end
30
32
 
@@ -33,7 +35,7 @@ module StandupMD
33
35
  #
34
36
  # @example
35
37
  # StandupMD.configure { |s| s.cli.editor = 'mate' }
36
- def self.configure
38
+ def configure
37
39
  yield config
38
40
  end
39
41
 
@@ -41,7 +43,7 @@ module StandupMD
41
43
  # Has a config file been loaded?
42
44
  #
43
45
  # @return [Boolean]
44
- def self.config_file_loaded?
46
+ def config_file_loaded?
45
47
  @config_file_loaded
46
48
  end
47
49
 
@@ -51,8 +53,8 @@ module StandupMD
51
53
  # @param [String] file
52
54
  #
53
55
  # @return [String] file
54
- def self.load_config_file(file)
55
- ::File.expand_path(file).tap do |file|
56
+ def load_config_file(config_file)
57
+ ::File.expand_path(config_file).tap do |file|
56
58
  raise "File #{file} does not exist." unless ::File.file?(file)
57
59
 
58
60
  @config_file_loaded = true