standup_md 0.3.1 → 0.3.6
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/Gemfile.lock +11 -9
- data/README.md +77 -43
- data/Rakefile +3 -1
- data/doc/README_md.html +63 -59
- data/doc/StandupMD.html +4 -23
- data/doc/StandupMD/Cli.html +11 -11
- data/doc/StandupMD/Cli/Helpers.html +8 -7
- data/doc/StandupMD/Config/Cli.html +29 -20
- data/doc/StandupMD/Config/Entry.html +26 -14
- data/doc/StandupMD/Config/EntryList.html +26 -11
- data/doc/StandupMD/Config/File.html +30 -26
- data/doc/StandupMD/Entry.html +1 -1
- data/doc/StandupMD/EntryList.html +116 -194
- data/doc/StandupMD/File.html +67 -25
- data/doc/StandupMD/Version.html +176 -0
- data/doc/created.rid +15 -15
- data/doc/index.html +62 -58
- data/doc/js/navigation.js.gz +0 -0
- data/doc/js/search_index.js +1 -1
- data/doc/js/search_index.js.gz +0 -0
- data/doc/js/searcher.js.gz +0 -0
- data/doc/table_of_contents.html +66 -59
- data/lib/standup_md.rb +4 -3
- data/lib/standup_md/cli.rb +2 -3
- data/lib/standup_md/cli/helpers.rb +66 -34
- data/lib/standup_md/config.rb +2 -2
- data/lib/standup_md/config/cli.rb +24 -23
- data/lib/standup_md/config/entry.rb +14 -9
- data/lib/standup_md/config/entry_list.rb +10 -5
- data/lib/standup_md/config/file.rb +26 -16
- data/lib/standup_md/entry.rb +2 -2
- data/lib/standup_md/entry_list.rb +24 -41
- data/lib/standup_md/file.rb +42 -15
- data/lib/standup_md/file/helpers.rb +13 -15
- data/lib/standup_md/version.rb +23 -6
- data/standup_md.gemspec +12 -16
- metadata +7 -6
@@ -1,9 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module StandupMD
|
2
4
|
class Config
|
3
5
|
|
4
6
|
##
|
5
7
|
# The configuration class for StandupMD::File
|
6
8
|
class File
|
9
|
+
|
10
|
+
##
|
11
|
+
# The default options.
|
12
|
+
#
|
13
|
+
# @return [Hash]
|
14
|
+
DEFAULTS = {
|
15
|
+
header_date_format: '%Y-%m-%d',
|
16
|
+
header_depth: 1,
|
17
|
+
sub_header_depth: 2,
|
18
|
+
current_header: 'Current',
|
19
|
+
previous_header: 'Previous',
|
20
|
+
impediments_header: 'Impediments',
|
21
|
+
notes_header: 'Notes',
|
22
|
+
sub_header_order: %w[previous current impediments notes],
|
23
|
+
directory: ::File.join(ENV['HOME'], '.cache', 'standup_md'),
|
24
|
+
bullet_character: '-',
|
25
|
+
name_format: '%Y_%m.md',
|
26
|
+
create: true,
|
27
|
+
}
|
28
|
+
|
7
29
|
##
|
8
30
|
# Number of octothorps that should preface entry headers.
|
9
31
|
#
|
@@ -116,27 +138,15 @@ module StandupMD
|
|
116
138
|
##
|
117
139
|
# Initializes the config with default values.
|
118
140
|
def initialize
|
119
|
-
|
141
|
+
reset
|
120
142
|
end
|
121
143
|
|
122
144
|
##
|
123
145
|
# Sets all config values back to their defaults.
|
124
146
|
#
|
125
|
-
# @return [
|
126
|
-
def
|
127
|
-
|
128
|
-
@header_depth = 1
|
129
|
-
@sub_header_depth = 2
|
130
|
-
@current_header = 'Current'
|
131
|
-
@previous_header = 'Previous'
|
132
|
-
@impediments_header = 'Impediments'
|
133
|
-
@notes_header = 'Notes'
|
134
|
-
@sub_header_order = %w[previous current impediments notes]
|
135
|
-
@directory = ::File.join(ENV['HOME'], '.cache', 'standup_md')
|
136
|
-
@bullet_character = '-'
|
137
|
-
@name_format = '%Y_%m.md'
|
138
|
-
@create = true
|
139
|
-
true
|
147
|
+
# @return [Hash]
|
148
|
+
def reset
|
149
|
+
DEFAULTS.each { |k, v| instance_variable_set("@#{k}", v) }
|
140
150
|
end
|
141
151
|
|
142
152
|
##
|
data/lib/standup_md/entry.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'json'
|
3
4
|
|
4
5
|
module StandupMD
|
5
|
-
|
6
6
|
##
|
7
7
|
# Class for handling single entries. Includes the comparable module, and
|
8
8
|
# compares by date.
|
@@ -38,7 +38,7 @@ module StandupMD
|
|
38
38
|
attr_accessor :previous
|
39
39
|
|
40
40
|
##
|
41
|
-
#
|
41
|
+
# Impediments for this entry.
|
42
42
|
#
|
43
43
|
# @return [Array]
|
44
44
|
attr_accessor :impediments
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
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,24 +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 }
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# How many entries are in the list.
|
60
50
|
#
|
61
|
-
# @
|
62
|
-
def size
|
63
|
-
@entries.size
|
64
|
-
end
|
65
|
-
|
66
|
-
##
|
67
|
-
# Is the list empty?
|
51
|
+
# @param [Date] date
|
68
52
|
#
|
69
|
-
# @return [
|
70
|
-
def
|
71
|
-
|
53
|
+
# @return [StandupMD::Entry]
|
54
|
+
def find(date)
|
55
|
+
entries.bsearch { |e| e.date == date }
|
72
56
|
end
|
73
57
|
|
74
58
|
##
|
@@ -124,24 +108,6 @@ module StandupMD
|
|
124
108
|
self
|
125
109
|
end
|
126
110
|
|
127
|
-
##
|
128
|
-
# The first entry in the list. This method assumes the list has
|
129
|
-
# already been sorted.
|
130
|
-
#
|
131
|
-
# @return [StandupMD::Entry]
|
132
|
-
def first
|
133
|
-
to_a.first
|
134
|
-
end
|
135
|
-
|
136
|
-
##
|
137
|
-
# The last entry in the list. This method assumes the list has
|
138
|
-
# already been sorted.
|
139
|
-
#
|
140
|
-
# @return [StandupMD::Entry]
|
141
|
-
def last
|
142
|
-
to_a.last
|
143
|
-
end
|
144
|
-
|
145
111
|
##
|
146
112
|
# The list as a hash, with the dates as keys.
|
147
113
|
#
|
@@ -162,5 +128,22 @@ module StandupMD
|
|
162
128
|
def to_json
|
163
129
|
to_h.to_json
|
164
130
|
end
|
131
|
+
|
132
|
+
# :section: Delegators
|
133
|
+
|
134
|
+
##
|
135
|
+
# The following are forwarded to @entries, which is the underly array of
|
136
|
+
# entries.
|
137
|
+
#
|
138
|
+
# +each+:: Iterate over each entry.
|
139
|
+
#
|
140
|
+
# +empty?+:: Is the list empty?
|
141
|
+
#
|
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
|
data/lib/standup_md/file.rb
CHANGED
@@ -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
|
@@ -19,15 +18,34 @@ module StandupMD
|
|
19
18
|
@config ||= StandupMD.config.file
|
20
19
|
end
|
21
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
|
30
|
+
|
31
|
+
FileUtils.mkdir_p(config.directory)
|
32
|
+
end
|
33
|
+
new(file_name).load
|
34
|
+
end
|
35
|
+
|
22
36
|
##
|
23
37
|
# Find standup file in directory by file name.
|
24
38
|
#
|
25
39
|
# @param [String] File_naem
|
26
40
|
def self.find(file_name)
|
27
|
-
|
28
|
-
|
29
|
-
|
41
|
+
unless ::File.directory?(config.directory)
|
42
|
+
raise "Dir #{config.directory} not found." unless config.create
|
43
|
+
|
44
|
+
FileUtils.mkdir_p(config.directory)
|
30
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
|
+
|
31
49
|
new(file_name)
|
32
50
|
end
|
33
51
|
|
@@ -36,8 +54,12 @@ module StandupMD
|
|
36
54
|
#
|
37
55
|
# @param [Date] date
|
38
56
|
def self.find_by_date(date)
|
39
|
-
unless date.is_a?(Date)
|
40
|
-
|
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)
|
41
63
|
end
|
42
64
|
find(date.strftime(config.name_format))
|
43
65
|
end
|
@@ -69,6 +91,7 @@ module StandupMD
|
|
69
91
|
|
70
92
|
unless ::File.directory?(@config.directory)
|
71
93
|
raise "Dir #{@config.directory} not found." unless @config.create
|
94
|
+
|
72
95
|
FileUtils.mkdir_p(@config.directory)
|
73
96
|
end
|
74
97
|
|
@@ -76,6 +99,7 @@ module StandupMD
|
|
76
99
|
|
77
100
|
unless ::File.file?(@name)
|
78
101
|
raise "File #{@name} not found." unless @config.create
|
102
|
+
|
79
103
|
FileUtils.touch(@name)
|
80
104
|
end
|
81
105
|
|
@@ -114,21 +138,23 @@ module StandupMD
|
|
114
138
|
# @return [StandupMD::FileList]
|
115
139
|
def load
|
116
140
|
raise "File #{name} does not exist." unless ::File.file?(name)
|
141
|
+
|
117
142
|
entry_list = EntryList.new
|
118
143
|
record = {}
|
119
144
|
section_type = ''
|
120
145
|
::File.foreach(name) do |line|
|
121
146
|
line.chomp!
|
122
147
|
next if line.strip.empty?
|
123
|
-
|
148
|
+
|
149
|
+
if header?(line)
|
124
150
|
unless record.empty?
|
125
151
|
entry_list << new_entry(record)
|
126
152
|
record = {}
|
127
153
|
end
|
128
|
-
record['header'] = line.sub(
|
129
|
-
|
130
|
-
|
131
|
-
elsif
|
154
|
+
record['header'] = line.sub(/^\#{#{@config.header_depth}}\s*/, '')
|
155
|
+
section_type = @config.notes_header
|
156
|
+
record[section_type] = []
|
157
|
+
elsif sub_header?(line)
|
132
158
|
section_type = determine_section_type(line)
|
133
159
|
record[section_type] = []
|
134
160
|
else
|
@@ -148,10 +174,10 @@ module StandupMD
|
|
148
174
|
# This method is destructive; if a file for entries in the date range
|
149
175
|
# already exists, it will be clobbered with the entries in the range.
|
150
176
|
#
|
151
|
-
# @param [Hash]
|
177
|
+
# @param [Hash] {start_date: Date, end_date: Date}
|
152
178
|
#
|
153
179
|
# @return [Boolean] true if successful
|
154
|
-
def write(dates
|
180
|
+
def write(**dates)
|
155
181
|
sorted_entries = entries.sort
|
156
182
|
start_date = dates.fetch(:start_date, sorted_entries.first.date)
|
157
183
|
end_date = dates.fetch(:end_date, sorted_entries.last.date)
|
@@ -159,9 +185,10 @@ module StandupMD
|
|
159
185
|
sorted_entries.filter(start_date, end_date).sort_reverse.each do |entry|
|
160
186
|
f.puts header(entry.date)
|
161
187
|
@config.sub_header_order.each do |attr|
|
162
|
-
tasks = entry.
|
188
|
+
tasks = entry.public_send(attr)
|
163
189
|
next if !tasks || tasks.empty?
|
164
|
-
|
190
|
+
|
191
|
+
f.puts sub_header(@config.public_send("#{attr}_header").capitalize)
|
165
192
|
tasks.each { |task| f.puts @config.bullet_character + ' ' + task }
|
166
193
|
end
|
167
194
|
f.puts
|
@@ -2,40 +2,38 @@
|
|
2
2
|
|
3
3
|
module StandupMD
|
4
4
|
class File
|
5
|
-
|
6
5
|
##
|
7
6
|
# Module responsible for reading and writing standup files.
|
8
7
|
module Helpers # :nodoc:
|
9
|
-
|
10
8
|
private
|
11
9
|
|
12
|
-
def
|
10
|
+
def header?(line) # :nodoc:
|
13
11
|
line.match(header_regex)
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
14
|
+
def sub_header?(line) # :nodoc:
|
17
15
|
line.match(sub_header_regex)
|
18
16
|
end
|
19
17
|
|
20
18
|
def header_regex # :nodoc:
|
21
|
-
|
19
|
+
/^#{'#' * StandupMD.config.file.header_depth}\s+/
|
22
20
|
end
|
23
21
|
|
24
22
|
def sub_header_regex # :nodoc:
|
25
|
-
|
23
|
+
/^#{'#' * StandupMD.config.file.sub_header_depth}\s+/
|
26
24
|
end
|
27
25
|
|
28
26
|
def bullet_character_regex # :nodoc:
|
29
|
-
|
27
|
+
/\s*#{StandupMD.config.file.bullet_character}\s*/
|
30
28
|
end
|
31
29
|
|
32
30
|
def determine_section_type(line) # :nodoc:
|
33
|
-
line = line.sub(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
line = line.sub(/^\#{#{StandupMD.config.file.sub_header_depth}}\s*/, '')
|
32
|
+
[
|
33
|
+
StandupMD.config.file.current_header,
|
34
|
+
StandupMD.config.file.previous_header,
|
35
|
+
StandupMD.config.file.impediments_header,
|
36
|
+
StandupMD.config.file.notes_header
|
39
37
|
].each { |header| return header if line.include?(header) }
|
40
38
|
raise "Unrecognized header [#{line}]"
|
41
39
|
end
|
@@ -54,8 +52,8 @@ module StandupMD
|
|
54
52
|
'#' * StandupMD.config.file.header_depth + ' ' + date.strftime(StandupMD.config.file.header_date_format)
|
55
53
|
end
|
56
54
|
|
57
|
-
def sub_header(
|
58
|
-
'#' * StandupMD.config.file.sub_header_depth + ' ' +
|
55
|
+
def sub_header(subhead)
|
56
|
+
'#' * StandupMD.config.file.sub_header_depth + ' ' + subhead
|
59
57
|
end
|
60
58
|
end
|
61
59
|
end
|
data/lib/standup_md/version.rb
CHANGED
@@ -1,11 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module StandupMD
|
4
|
+
|
4
5
|
##
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# Module that contains all gem version information. Follows semantic
|
7
|
+
# versioning. Read: https://semver.org/
|
8
|
+
module Version
|
9
|
+
|
10
|
+
##
|
11
|
+
# Major version.
|
12
|
+
MAJOR = 0
|
13
|
+
|
14
|
+
##
|
15
|
+
# Minor version.
|
16
|
+
MINOR = 3
|
17
|
+
|
18
|
+
##
|
19
|
+
# Patch version.
|
20
|
+
PATCH = 6
|
21
|
+
|
22
|
+
##
|
23
|
+
# Version as +MAJOR.MINOR.PATCH+
|
24
|
+
def self.to_s
|
25
|
+
"#{MAJOR}.#{MINOR}.#{PATCH}"
|
26
|
+
end
|
27
|
+
end
|
11
28
|
end
|
data/standup_md.gemspec
CHANGED
@@ -2,7 +2,7 @@ require_relative 'lib/standup_md/version'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'standup_md'
|
5
|
-
spec.version = StandupMD::
|
5
|
+
spec.version = StandupMD::Version.to_s
|
6
6
|
spec.authors = ['Evan Gray']
|
7
7
|
spec.email = 'evanthegrayt@vivaldi.net'
|
8
8
|
spec.license = 'MIT'
|
@@ -12,25 +12,21 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = %q{Generate and edit standups in markdown format}
|
13
13
|
spec.homepage = 'https://evanthegrayt.github.io/standup_md/'
|
14
14
|
|
15
|
-
|
16
|
-
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
17
|
-
if spec.respond_to?(:metadata)
|
18
|
-
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
19
|
-
|
20
|
-
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
-
spec.metadata['source_code_uri'] = 'https://github.com/evanthegrayt/standup_md'
|
22
|
-
spec.metadata['documentation_uri'] = 'https://evanthegrayt.github.io/standup_md/doc/index.html'
|
23
|
-
else
|
15
|
+
unless spec.respond_to?(:metadata)
|
24
16
|
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
25
17
|
'public gem pushes.'
|
26
18
|
end
|
27
19
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
+
spec.metadata['source_code_uri'] =
|
23
|
+
'https://github.com/evanthegrayt/standup_md'
|
24
|
+
spec.metadata['documentation_uri'] =
|
25
|
+
'https://evanthegrayt.github.io/standup_md/doc/index.html'
|
26
|
+
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
28
|
+
f.match(%r{^(test|spec|features)/})
|
29
|
+
end
|
34
30
|
spec.bindir = 'bin'
|
35
31
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
36
32
|
spec.require_paths = ['lib']
|