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.
- checksums.yaml +4 -4
- data/Gemfile.lock +11 -9
- data/README.md +66 -33
- data/Rakefile +3 -1
- data/doc/README_md.html +53 -53
- data/doc/StandupMD.html +7 -96
- data/doc/StandupMD/Cli.html +21 -163
- data/doc/StandupMD/Cli/Helpers.html +13 -34
- data/doc/StandupMD/Config.html +7 -44
- data/doc/StandupMD/Config/Cli.html +10 -78
- data/doc/StandupMD/Config/Entry.html +10 -66
- data/doc/StandupMD/Config/EntryList.html +7 -48
- data/doc/StandupMD/Config/File.html +14 -146
- data/doc/StandupMD/Entry.html +11 -120
- data/doc/StandupMD/EntryList.html +94 -354
- data/doc/StandupMD/File.html +51 -182
- data/doc/StandupMD/Version.html +143 -0
- data/doc/created.rid +15 -15
- data/doc/css/rdoc.css +1 -1
- data/doc/index.html +51 -66
- 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 +46 -105
- data/lib/standup_md.rb +2 -1
- data/lib/standup_md/cli.rb +2 -3
- data/lib/standup_md/cli/helpers.rb +66 -34
- data/lib/standup_md/config.rb +0 -2
- data/lib/standup_md/config/cli.rb +2 -4
- data/lib/standup_md/config/entry.rb +2 -4
- data/lib/standup_md/entry.rb +3 -6
- data/lib/standup_md/entry_list.rb +20 -37
- data/lib/standup_md/file.rb +32 -15
- data/lib/standup_md/file/helpers.rb +13 -15
- data/lib/standup_md/version.rb +22 -4
- data/standup_md.gemspec +12 -16
- metadata +7 -6
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
|
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
|
data/lib/standup_md/cli.rb
CHANGED
@@ -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
|
-
|
68
|
+
load_runtime_preferences(options)
|
70
69
|
@file = StandupMD::File.find_by_date(@config.date)
|
71
70
|
@file.load
|
72
|
-
@entry =
|
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 #{
|
16
|
+
puts "No record found for #{config.cli.date}"
|
19
17
|
return
|
20
18
|
end
|
21
|
-
puts
|
22
|
-
|
23
|
-
tasks = entry.
|
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
|
-
|
26
|
-
|
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
|
45
|
+
def load_runtime_preferences(options)
|
39
46
|
OptionParser.new do |opts|
|
40
47
|
opts.banner = 'The Standup Doctor'
|
41
|
-
opts.version = "[StandupMD] #{::StandupMD::
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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|
|
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
|
-
|
109
|
-
|
110
|
-
v.nil? ? Date.today : Date.strptime(v,
|
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
|
120
|
-
entry = file.entries.find(
|
121
|
-
if entry.nil? &&
|
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
|
-
|
125
|
-
|
131
|
+
config.cli.date,
|
132
|
+
config.entry.current,
|
126
133
|
previous_entry,
|
127
|
-
|
128
|
-
|
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
|
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
|
data/lib/standup_md/config.rb
CHANGED
@@ -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.
|
data/lib/standup_md/entry.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
55
|
-
|
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
|
143
|
-
#
|
135
|
+
# The following are forwarded to @entries, which is the underly array of
|
136
|
+
# entries.
|
144
137
|
#
|
145
|
-
#
|
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
|
-
#
|
154
|
-
def size
|
155
|
-
@entries.size
|
156
|
-
end
|
157
|
-
|
158
|
-
##
|
159
|
-
# Is the list empty?
|
140
|
+
# +empty?+:: Is the list empty?
|
160
141
|
#
|
161
|
-
#
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
@@ -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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
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(
|
139
|
-
|
140
|
-
|
141
|
-
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)
|
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]
|
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.
|
188
|
+
tasks = entry.public_send(attr)
|
173
189
|
next if !tasks || tasks.empty?
|
174
|
-
|
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
|