standup_md 0.3.16 → 1.0.0
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 +2 -2
- data/README.md +15 -0
- data/completion/zsh/_standup +81 -0
- data/lib/standup_md/cli/helpers.rb +26 -2
- data/lib/standup_md/cli.rb +65 -0
- data/lib/standup_md/config/file.rb +21 -0
- data/lib/standup_md/entry.rb +46 -28
- data/lib/standup_md/file.rb +4 -44
- data/lib/standup_md/parsers/markdown.rb +168 -0
- data/lib/standup_md/section.rb +77 -0
- data/lib/standup_md/task.rb +60 -0
- data/lib/standup_md/title.rb +41 -0
- data/lib/standup_md/version.rb +3 -3
- data/lib/standup_md.rb +6 -2
- metadata +6 -2
- data/lib/standup_md/file/helpers.rb +0 -65
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2734d31b2ce72d31aceeb789f562b015c4f0e7422b3a755992df7c1f293a7051
|
|
4
|
+
data.tar.gz: 651d1f6f9a613366b90e2b26ba83b8e05dd80dbc5d8bde3a0fcc7d07b57acef1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5df3037a20d107f82cc34533f89ab8c31a2ba13eb8180b5931b052c500c5c1f7c4922d22ffed254c5fb9e9d7623b5bb207ed5d5c0c22773bcc972a91bba061d4
|
|
7
|
+
data.tar.gz: c99e5cf930d4dcf84e6089d458321b00f427ab0c124ecf3b02b8e98d79ba416d5c629793f6f77a8cf1a0337b05ed620600833f1ad8fa2775d7e6eb7205ec22ed
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
standup_md (0.
|
|
4
|
+
standup_md (1.0.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -115,7 +115,7 @@ CHECKSUMS
|
|
|
115
115
|
standard (1.54.0) sha256=7a4b08f83d9893083c8f03bc486f0feeb6a84d48233b40829c03ef4767ea0100
|
|
116
116
|
standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b
|
|
117
117
|
standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
|
|
118
|
-
standup_md (0.
|
|
118
|
+
standup_md (1.0.0)
|
|
119
119
|
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
|
|
120
120
|
test-unit (3.7.8) sha256=689d1ca53f4d46f678b4e5d68d8e4294f87fc5e8b9238cc4de7c5727e8d65943
|
|
121
121
|
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
|
data/README.md
CHANGED
|
@@ -59,6 +59,17 @@ cd standup_md
|
|
|
59
59
|
rake install
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
### Zsh Completion
|
|
63
|
+
The gem ships with a zsh completion file at `completion/zsh/_standup`. RubyGems
|
|
64
|
+
doesn't automatically add gem-provided completion directories to zsh's `fpath`,
|
|
65
|
+
so you'll need to add the completion directory yourself after installation.
|
|
66
|
+
|
|
67
|
+
For setup instructions and example, run the following.
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
standup --zsh-completion
|
|
71
|
+
```
|
|
72
|
+
|
|
62
73
|
## Usage
|
|
63
74
|
### Command Line
|
|
64
75
|
For the most basic usage, simply call the executable.
|
|
@@ -169,6 +180,7 @@ StandupMD.configure do |c|
|
|
|
169
180
|
c.file.sub_header_order = %w[previous current impediments notes]
|
|
170
181
|
c.file.directory = ::File.join(ENV["HOME"], ".cache", "standup_md")
|
|
171
182
|
c.file.bullet_character = "-"
|
|
183
|
+
c.file.indent_width = 2
|
|
172
184
|
c.file.name_format = "%Y_%m.md"
|
|
173
185
|
c.file.create = true
|
|
174
186
|
|
|
@@ -207,6 +219,7 @@ Some of these options can be changed at runtime. They are as follows.
|
|
|
207
219
|
--impediments ARRAY List of impediments for current entry
|
|
208
220
|
--notes ARRAY List of notes for current entry
|
|
209
221
|
--sub-header-order ARRAY The order of the sub-headers when writing the file
|
|
222
|
+
--indent-width INTEGER Number of spaces used for each nested task level
|
|
210
223
|
-f, --file-name-format STRING Date-formattable string to use for standup file name
|
|
211
224
|
-E, --editor EDITOR Editor to use for opening standup files
|
|
212
225
|
-d, --directory DIRECTORY The directories where standup files are located
|
|
@@ -214,6 +227,7 @@ Some of these options can be changed at runtime. They are as follows.
|
|
|
214
227
|
-a --[no-]auto-fill-previous Auto-generate 'previous' tasks for new entries
|
|
215
228
|
-e --[no-]edit Open the file in the editor. Default is true
|
|
216
229
|
-v, --[no-]verbose Verbose output. Default is false.
|
|
230
|
+
--zsh-completion Print zsh completion setup instructions
|
|
217
231
|
-p, --print [DATE] Print current entry.
|
|
218
232
|
If DATE is passed, will print entry for DATE, if it exists.
|
|
219
233
|
DATE must be in the same format as file-name-format
|
|
@@ -263,6 +277,7 @@ StandupMD.configure do |c|
|
|
|
263
277
|
c.file.previous_header = "Yesterday"
|
|
264
278
|
c.file.impediments_header = "Hold-ups"
|
|
265
279
|
c.file.bullet_character = "*"
|
|
280
|
+
c.file.indent_width = 2
|
|
266
281
|
c.file.header_date_format = "%m/%d/%Y"
|
|
267
282
|
c.file.sub_header_order = %w[current previous impediments notes]
|
|
268
283
|
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#compdef standup
|
|
2
|
+
|
|
3
|
+
_standup_array_values() {
|
|
4
|
+
_message -e values 'comma-separated list'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
_standup_sub_header_order() {
|
|
8
|
+
local -a headers
|
|
9
|
+
|
|
10
|
+
headers=(
|
|
11
|
+
'previous:previous entry tasks'
|
|
12
|
+
'current:current entry tasks'
|
|
13
|
+
'impediments:current entry impediments'
|
|
14
|
+
'notes:current entry notes'
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
_values -s , 'sub-header' $headers
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
_standup_dates() {
|
|
21
|
+
local directory="${STANDUP_MD_DIR:-$HOME/.cache/standup_md}"
|
|
22
|
+
local index
|
|
23
|
+
local file
|
|
24
|
+
local -a dates
|
|
25
|
+
|
|
26
|
+
for (( index = 1; index <= $#words; index++ )); do
|
|
27
|
+
case "$words[index]" in
|
|
28
|
+
--directory=*)
|
|
29
|
+
directory="${words[index]#--directory=}"
|
|
30
|
+
;;
|
|
31
|
+
--directory|-d)
|
|
32
|
+
if (( index < $#words )); then
|
|
33
|
+
directory="$words[index + 1]"
|
|
34
|
+
fi
|
|
35
|
+
;;
|
|
36
|
+
esac
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
directory=${~directory}
|
|
40
|
+
if [[ -d "$directory" ]]; then
|
|
41
|
+
for file in "$directory"/*.md(N); do
|
|
42
|
+
file="${file:t:r}"
|
|
43
|
+
if [[ "$file" == <->_<-> ]]; then
|
|
44
|
+
dates+=("${file/_/-}:standup file ${file}.md")
|
|
45
|
+
fi
|
|
46
|
+
done
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
if (( ${#dates} )); then
|
|
50
|
+
_describe -t dates 'standup date' dates
|
|
51
|
+
else
|
|
52
|
+
_message -e dates 'date (YYYY-MM or YYYY-MM-DD)'
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_arguments -s -S \
|
|
57
|
+
'(- *)'{-h,--help}'[show help]' \
|
|
58
|
+
'(- *)--version[show version]' \
|
|
59
|
+
'(- *)--zsh-completion[print zsh completion setup instructions]' \
|
|
60
|
+
'--current[List of current entry tasks]:tasks:_standup_array_values' \
|
|
61
|
+
'--previous[List of previous entry tasks]:tasks:_standup_array_values' \
|
|
62
|
+
'--impediments[List of impediments for current entry]:impediments:_standup_array_values' \
|
|
63
|
+
'--notes[List of notes for current entry]:notes:_standup_array_values' \
|
|
64
|
+
'--sub-header-order[The order of the sub-headers when writing the file]:sub-header order:_standup_sub_header_order' \
|
|
65
|
+
'--indent-width[Number of spaces used for each nested task level]:indent width:' \
|
|
66
|
+
'(-f --file-name-format)-f[Date-formattable string to use for standup file name]:strftime format:' \
|
|
67
|
+
'(-f --file-name-format)--file-name-format[Date-formattable string to use for standup file name]:strftime format:' \
|
|
68
|
+
'(-E --editor)-E[Editor to use for opening standup files]:editor:_path_commands' \
|
|
69
|
+
'(-E --editor)--editor[Editor to use for opening standup files]:editor:_path_commands' \
|
|
70
|
+
'(-d --directory)-d[The directory where standup files are located]:directory:_directories' \
|
|
71
|
+
'(-d --directory)--directory[The directory where standup files are located]:directory:_directories' \
|
|
72
|
+
'(-w --write --no-write)'{-w,--write}'[write current entry if it does not exist]' \
|
|
73
|
+
'(-w --write --no-write)--no-write[do not write current entry if it does not exist]' \
|
|
74
|
+
'(-a --auto-fill-previous --no-auto-fill-previous)'{-a,--auto-fill-previous}'[auto-generate previous tasks for new entries]' \
|
|
75
|
+
'(-a --auto-fill-previous --no-auto-fill-previous)--no-auto-fill-previous[do not auto-generate previous tasks for new entries]' \
|
|
76
|
+
'(-e --edit --no-edit)'{-e,--edit}'[open the file in the editor]' \
|
|
77
|
+
'(-e --edit --no-edit)--no-edit[do not open the file in the editor]' \
|
|
78
|
+
'(-v --verbose --no-verbose)'{-v,--verbose}'[use verbose output]' \
|
|
79
|
+
'(-v --verbose --no-verbose)--no-verbose[disable verbose output]' \
|
|
80
|
+
'(-p --print)'{-p,--print}'[print current entry]::date:_standup_dates' \
|
|
81
|
+
'1:standup file date:_standup_dates'
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "standup_md/parsers/markdown"
|
|
4
|
+
|
|
3
5
|
module StandupMD
|
|
4
6
|
class Cli
|
|
5
7
|
##
|
|
@@ -20,7 +22,9 @@ module StandupMD
|
|
|
20
22
|
next if !tasks || tasks.empty?
|
|
21
23
|
|
|
22
24
|
puts sub_header(header_type)
|
|
23
|
-
|
|
25
|
+
entry.public_send("#{header_type}_tasks").each do |task|
|
|
26
|
+
puts parser.task_line(task)
|
|
27
|
+
end
|
|
24
28
|
end
|
|
25
29
|
puts
|
|
26
30
|
end
|
|
@@ -69,6 +73,11 @@ module StandupMD
|
|
|
69
73
|
"The order of the sub-headers when writing the file"
|
|
70
74
|
) { |v| config.file.sub_header_order = v }
|
|
71
75
|
|
|
76
|
+
opts.on(
|
|
77
|
+
"--indent-width INTEGER", Integer,
|
|
78
|
+
"Number of spaces used for each nested task level"
|
|
79
|
+
) { |v| config.file.indent_width = v }
|
|
80
|
+
|
|
72
81
|
opts.on(
|
|
73
82
|
"-f", "--file-name-format STRING",
|
|
74
83
|
"Date-formattable string to use for standup file name"
|
|
@@ -104,6 +113,11 @@ module StandupMD
|
|
|
104
113
|
"Verbose output. Default is false."
|
|
105
114
|
) { |v| config.cli.verbose = v }
|
|
106
115
|
|
|
116
|
+
opts.on(
|
|
117
|
+
"--zsh-completion",
|
|
118
|
+
"Print zsh completion setup instructions"
|
|
119
|
+
) { @zsh_completion_requested = true }
|
|
120
|
+
|
|
107
121
|
opts.on(
|
|
108
122
|
"-p", "--print [DATE]",
|
|
109
123
|
"Print current entry.",
|
|
@@ -115,6 +129,12 @@ module StandupMD
|
|
|
115
129
|
v.nil? ? Date.today : Date.strptime(v, config.file.header_date_format)
|
|
116
130
|
end
|
|
117
131
|
end.parse!(options)
|
|
132
|
+
if zsh_completion_requested?
|
|
133
|
+
raise OptionParser::InvalidArgument, options.join(" ") unless options.empty?
|
|
134
|
+
|
|
135
|
+
return
|
|
136
|
+
end
|
|
137
|
+
|
|
118
138
|
unless options.empty?
|
|
119
139
|
@file_date_argument = true
|
|
120
140
|
config.cli.date = parse_file_date(options.shift)
|
|
@@ -206,7 +226,11 @@ module StandupMD
|
|
|
206
226
|
# @return [String]
|
|
207
227
|
def sub_header(header_type)
|
|
208
228
|
"#" * config.file.sub_header_depth + " " +
|
|
209
|
-
config.file.public_send("#{header_type}_header")
|
|
229
|
+
config.file.public_send("#{header_type}_header")
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def parser
|
|
233
|
+
StandupMD::Parsers::Markdown.new(config.file)
|
|
210
234
|
end
|
|
211
235
|
end
|
|
212
236
|
end
|
data/lib/standup_md/cli.rb
CHANGED
|
@@ -9,6 +9,10 @@ module StandupMD
|
|
|
9
9
|
class Cli
|
|
10
10
|
include Helpers
|
|
11
11
|
|
|
12
|
+
ZSH_COMPLETION_FILE = ::File.expand_path(
|
|
13
|
+
::File.join(__dir__, "..", "..", "completion", "zsh", "_standup")
|
|
14
|
+
).freeze
|
|
15
|
+
|
|
12
16
|
##
|
|
13
17
|
# Access to the class's configuration.
|
|
14
18
|
#
|
|
@@ -25,10 +29,45 @@ module StandupMD
|
|
|
25
29
|
puts msg if config.verbose
|
|
26
30
|
end
|
|
27
31
|
|
|
32
|
+
##
|
|
33
|
+
# Prints zsh completion setup instructions.
|
|
34
|
+
#
|
|
35
|
+
# @return [String]
|
|
36
|
+
def self.zsh_completion_instructions
|
|
37
|
+
completion_dir = ::File.dirname(ZSH_COMPLETION_FILE)
|
|
38
|
+
|
|
39
|
+
<<~INSTRUCTIONS
|
|
40
|
+
Zsh completion file:
|
|
41
|
+
#{ZSH_COMPLETION_FILE}
|
|
42
|
+
|
|
43
|
+
To load it directly, add this before compinit runs:
|
|
44
|
+
|
|
45
|
+
fpath=("#{completion_dir}" $fpath)
|
|
46
|
+
autoload -Uz compinit
|
|
47
|
+
compinit
|
|
48
|
+
|
|
49
|
+
Or symlink it into your own completion directory:
|
|
50
|
+
|
|
51
|
+
mkdir -p ~/.zsh/completions
|
|
52
|
+
ln -sf "#{ZSH_COMPLETION_FILE}" ~/.zsh/completions/_standup
|
|
53
|
+
|
|
54
|
+
Then make sure that directory is in fpath before compinit runs:
|
|
55
|
+
|
|
56
|
+
fpath=(~/.zsh/completions $fpath)
|
|
57
|
+
autoload -Uz compinit
|
|
58
|
+
compinit
|
|
59
|
+
INSTRUCTIONS
|
|
60
|
+
end
|
|
61
|
+
|
|
28
62
|
##
|
|
29
63
|
# Creates an instance of +StandupMD+ and runs what the user requested.
|
|
30
64
|
def self.execute(options = [])
|
|
31
65
|
new(options).tap do |exe|
|
|
66
|
+
if exe.zsh_completion_requested?
|
|
67
|
+
puts zsh_completion_instructions
|
|
68
|
+
next
|
|
69
|
+
end
|
|
70
|
+
|
|
32
71
|
exe.write_file if exe.write?
|
|
33
72
|
if config.print
|
|
34
73
|
exe.print(exe.entry)
|
|
@@ -64,6 +103,14 @@ module StandupMD
|
|
|
64
103
|
@file_date_argument
|
|
65
104
|
end
|
|
66
105
|
|
|
106
|
+
##
|
|
107
|
+
# Was zsh completion output requested?
|
|
108
|
+
#
|
|
109
|
+
# @return [Boolean]
|
|
110
|
+
def zsh_completion_requested?
|
|
111
|
+
@zsh_completion_requested
|
|
112
|
+
end
|
|
113
|
+
|
|
67
114
|
##
|
|
68
115
|
# Constructor. Sets defaults.
|
|
69
116
|
#
|
|
@@ -72,9 +119,14 @@ module StandupMD
|
|
|
72
119
|
@config = self.class.config
|
|
73
120
|
@preference_file_loaded = false
|
|
74
121
|
@file_date_argument = false
|
|
122
|
+
@zsh_completion_requested = false
|
|
75
123
|
@options = options
|
|
124
|
+
return if load_zsh_completion_request(options)
|
|
125
|
+
|
|
76
126
|
load_preferences if load_config
|
|
77
127
|
load_runtime_preferences(options)
|
|
128
|
+
return if zsh_completion_requested?
|
|
129
|
+
|
|
78
130
|
@file = find_file
|
|
79
131
|
@file&.load
|
|
80
132
|
@entry = @file.nil? ? nil : new_entry(@file)
|
|
@@ -137,6 +189,19 @@ module StandupMD
|
|
|
137
189
|
|
|
138
190
|
private
|
|
139
191
|
|
|
192
|
+
##
|
|
193
|
+
# Detects zsh completion setup requests before loading user preferences.
|
|
194
|
+
#
|
|
195
|
+
# @return [Boolean]
|
|
196
|
+
def load_zsh_completion_request(options)
|
|
197
|
+
return false unless options.include?("--zsh-completion")
|
|
198
|
+
|
|
199
|
+
invalid_options = options - ["--zsh-completion"]
|
|
200
|
+
raise OptionParser::InvalidArgument, invalid_options.join(" ") unless invalid_options.empty?
|
|
201
|
+
|
|
202
|
+
@zsh_completion_requested = true
|
|
203
|
+
end
|
|
204
|
+
|
|
140
205
|
##
|
|
141
206
|
# Is this a read-only action?
|
|
142
207
|
#
|
|
@@ -20,6 +20,7 @@ module StandupMD
|
|
|
20
20
|
sub_header_order: %w[previous current impediments notes],
|
|
21
21
|
directory: ::File.join(ENV["HOME"], ".cache", "standup_md"),
|
|
22
22
|
bullet_character: "-",
|
|
23
|
+
indent_width: 2,
|
|
23
24
|
name_format: "%Y_%m.md",
|
|
24
25
|
create: true
|
|
25
26
|
}.freeze
|
|
@@ -56,6 +57,14 @@ module StandupMD
|
|
|
56
57
|
# @default "-" (dash)
|
|
57
58
|
attr_reader :bullet_character
|
|
58
59
|
|
|
60
|
+
##
|
|
61
|
+
# Number of spaces used for each nested task level.
|
|
62
|
+
#
|
|
63
|
+
# @return [Integer]
|
|
64
|
+
#
|
|
65
|
+
# @default 2
|
|
66
|
+
attr_reader :indent_width
|
|
67
|
+
|
|
59
68
|
##
|
|
60
69
|
# String to be used as "Current" header.
|
|
61
70
|
#
|
|
@@ -186,6 +195,18 @@ module StandupMD
|
|
|
186
195
|
@bullet_character = char
|
|
187
196
|
end
|
|
188
197
|
|
|
198
|
+
##
|
|
199
|
+
# Setter for indent_width. Must be a positive integer.
|
|
200
|
+
#
|
|
201
|
+
# @param [Integer] width
|
|
202
|
+
#
|
|
203
|
+
# @return [Integer]
|
|
204
|
+
def indent_width=(width)
|
|
205
|
+
raise "Indent width must be a positive integer" unless width.is_a?(Integer) && width.positive?
|
|
206
|
+
|
|
207
|
+
@indent_width = width
|
|
208
|
+
end
|
|
209
|
+
|
|
189
210
|
##
|
|
190
211
|
# Setter for directory. Must be expanded in case the user uses `~` for
|
|
191
212
|
# home. If the directory doesn't exist, it will be created. To reset
|
data/lib/standup_md/entry.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require "standup_md/section"
|
|
4
5
|
|
|
5
6
|
module StandupMD
|
|
6
7
|
##
|
|
@@ -9,6 +10,8 @@ module StandupMD
|
|
|
9
10
|
class Entry
|
|
10
11
|
include Comparable
|
|
11
12
|
|
|
13
|
+
SECTION_TYPES = %i[current previous impediments notes].freeze
|
|
14
|
+
|
|
12
15
|
##
|
|
13
16
|
# Access to the class's configuration.
|
|
14
17
|
#
|
|
@@ -25,30 +28,6 @@ module StandupMD
|
|
|
25
28
|
# @return [Date]
|
|
26
29
|
attr_accessor :date
|
|
27
30
|
|
|
28
|
-
##
|
|
29
|
-
# The tasks for today.
|
|
30
|
-
#
|
|
31
|
-
# @return [Array]
|
|
32
|
-
attr_accessor :current
|
|
33
|
-
|
|
34
|
-
##
|
|
35
|
-
# The tasks from the previous day.
|
|
36
|
-
#
|
|
37
|
-
# @return [Array]
|
|
38
|
-
attr_accessor :previous
|
|
39
|
-
|
|
40
|
-
##
|
|
41
|
-
# Impediments for this entry.
|
|
42
|
-
#
|
|
43
|
-
# @return [Array]
|
|
44
|
-
attr_accessor :impediments
|
|
45
|
-
|
|
46
|
-
##
|
|
47
|
-
# Nnotes to add to this entry.
|
|
48
|
-
#
|
|
49
|
-
# @return [Array]
|
|
50
|
-
attr_accessor :notes
|
|
51
|
-
|
|
52
31
|
##
|
|
53
32
|
# Creates a generic entry. Default values can be set via configuration.
|
|
54
33
|
# Yields the entry if a block is passed so you can change values.
|
|
@@ -81,10 +60,43 @@ module StandupMD
|
|
|
81
60
|
|
|
82
61
|
@config = self.class.config
|
|
83
62
|
@date = date
|
|
84
|
-
@
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
63
|
+
@sections = {}
|
|
64
|
+
self.current = current
|
|
65
|
+
self.previous = previous
|
|
66
|
+
self.impediments = impediments
|
|
67
|
+
self.notes = notes
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
SECTION_TYPES.each do |type|
|
|
71
|
+
define_method(type) do
|
|
72
|
+
section(type).tasks.map(&:to_s)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
define_method("#{type}=") do |tasks|
|
|
76
|
+
set_section(type, tasks)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
define_method("#{type}_tasks") do
|
|
80
|
+
section(type).tasks
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Sections for this entry.
|
|
86
|
+
#
|
|
87
|
+
# @return [Array<StandupMD::Section>]
|
|
88
|
+
def sections
|
|
89
|
+
SECTION_TYPES.map { |type| section(type) }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Find a section by type.
|
|
94
|
+
#
|
|
95
|
+
# @param [Symbol, String] type
|
|
96
|
+
#
|
|
97
|
+
# @return [StandupMD::Section]
|
|
98
|
+
def section(type)
|
|
99
|
+
@sections[type.to_sym] ||= Section.new(type)
|
|
88
100
|
end
|
|
89
101
|
|
|
90
102
|
##
|
|
@@ -115,5 +127,11 @@ module StandupMD
|
|
|
115
127
|
def to_json
|
|
116
128
|
to_h.to_json
|
|
117
129
|
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def set_section(type, tasks)
|
|
134
|
+
@sections[type.to_sym] = Section.new(type, tasks || [])
|
|
135
|
+
end
|
|
118
136
|
end
|
|
119
137
|
end
|
data/lib/standup_md/file.rb
CHANGED
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
require "date"
|
|
4
4
|
require "fileutils"
|
|
5
|
-
require "standup_md/
|
|
5
|
+
require "standup_md/parsers/markdown"
|
|
6
6
|
|
|
7
7
|
module StandupMD
|
|
8
8
|
##
|
|
9
9
|
# Class for handling reading and writing standup files.
|
|
10
10
|
class File
|
|
11
|
-
include StandupMD::File::Helpers
|
|
12
|
-
|
|
13
11
|
class << self
|
|
14
12
|
##
|
|
15
13
|
# Access to the class's configuration.
|
|
@@ -88,6 +86,7 @@ module StandupMD
|
|
|
88
86
|
# @return [StandupMP::File]
|
|
89
87
|
def initialize(file_name)
|
|
90
88
|
@config = self.class.config
|
|
89
|
+
@parser = StandupMD::Parsers::Markdown.new(@config)
|
|
91
90
|
if file_name.include?(::File::SEPARATOR)
|
|
92
91
|
raise ArgumentError,
|
|
93
92
|
"#{file_name} contains directory. Please use `StandupMD.config.file.directory=`"
|
|
@@ -137,40 +136,14 @@ module StandupMD
|
|
|
137
136
|
|
|
138
137
|
##
|
|
139
138
|
# Loads the file's contents.
|
|
140
|
-
# TODO clean up this method.
|
|
141
139
|
#
|
|
142
140
|
# @return [StandupMD::FileList]
|
|
143
141
|
def load
|
|
144
142
|
raise "File #{name} does not exist." unless ::File.file?(name)
|
|
145
143
|
|
|
146
|
-
entry_list = EntryList.new
|
|
147
|
-
record = {}
|
|
148
|
-
section_type = ""
|
|
149
|
-
::File.foreach(name) do |line|
|
|
150
|
-
line.chomp!
|
|
151
|
-
next if line.strip.empty?
|
|
152
|
-
|
|
153
|
-
if header?(line)
|
|
154
|
-
unless record.empty?
|
|
155
|
-
entry_list << new_entry(record)
|
|
156
|
-
record = {}
|
|
157
|
-
end
|
|
158
|
-
record["header"] = line.sub(/^\#{#{@config.header_depth}}\s*/, "")
|
|
159
|
-
section_type = @config.notes_header
|
|
160
|
-
record[section_type] = []
|
|
161
|
-
elsif sub_header?(line)
|
|
162
|
-
section_type = determine_section_type(line)
|
|
163
|
-
record[section_type] = []
|
|
164
|
-
else
|
|
165
|
-
record[section_type] << line.sub(bullet_character_regex, "")
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
entry_list << new_entry(record) unless record.empty?
|
|
169
144
|
@loaded = true
|
|
170
|
-
@entries =
|
|
145
|
+
@entries = @parser.read(name)
|
|
171
146
|
self
|
|
172
|
-
rescue => e
|
|
173
|
-
raise "File malformation: #{e}"
|
|
174
147
|
end
|
|
175
148
|
|
|
176
149
|
##
|
|
@@ -185,20 +158,7 @@ module StandupMD
|
|
|
185
158
|
sorted_entries = entries.sort
|
|
186
159
|
start_date = dates.fetch(:start_date, sorted_entries.first.date)
|
|
187
160
|
end_date = dates.fetch(:end_date, sorted_entries.last.date)
|
|
188
|
-
|
|
189
|
-
sorted_entries.filter(start_date, end_date).sort_reverse.each do |entry|
|
|
190
|
-
f.puts header(entry.date)
|
|
191
|
-
@config.sub_header_order.each do |attr|
|
|
192
|
-
tasks = entry.public_send(attr)
|
|
193
|
-
next if !tasks || tasks.empty?
|
|
194
|
-
|
|
195
|
-
f.puts sub_header(@config.public_send("#{attr}_header").capitalize)
|
|
196
|
-
tasks.each { |task| f.puts "#{@config.bullet_character} #{task}" }
|
|
197
|
-
end
|
|
198
|
-
f.puts
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
true
|
|
161
|
+
@parser.write(name, sorted_entries, start_date: start_date, end_date: end_date)
|
|
202
162
|
end
|
|
203
163
|
end
|
|
204
164
|
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "date"
|
|
4
|
+
require "standup_md/entry"
|
|
5
|
+
require "standup_md/entry_list"
|
|
6
|
+
require "standup_md/section"
|
|
7
|
+
require "standup_md/task"
|
|
8
|
+
require "standup_md/title"
|
|
9
|
+
|
|
10
|
+
module StandupMD
|
|
11
|
+
module Parsers
|
|
12
|
+
##
|
|
13
|
+
# Parser and renderer for the markdown standup format.
|
|
14
|
+
class Markdown
|
|
15
|
+
##
|
|
16
|
+
# Access to file configuration.
|
|
17
|
+
#
|
|
18
|
+
# @return [StandupMD::Config::File]
|
|
19
|
+
attr_reader :config
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Constructs an instance of +StandupMD::Parsers::Markdown+.
|
|
23
|
+
#
|
|
24
|
+
# @param [StandupMD::Config::File] config
|
|
25
|
+
def initialize(config = StandupMD.config.file)
|
|
26
|
+
@config = config
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Reads entries from a markdown standup file.
|
|
31
|
+
#
|
|
32
|
+
# @param [String] file_name
|
|
33
|
+
#
|
|
34
|
+
# @return [StandupMD::EntryList]
|
|
35
|
+
def read(file_name)
|
|
36
|
+
entry_list = EntryList.new
|
|
37
|
+
record = nil
|
|
38
|
+
section = nil
|
|
39
|
+
|
|
40
|
+
::File.foreach(file_name) do |line|
|
|
41
|
+
line.chomp!
|
|
42
|
+
next if line.strip.empty?
|
|
43
|
+
|
|
44
|
+
if header?(line)
|
|
45
|
+
entry_list << entry(record) if record
|
|
46
|
+
record = {title: title(line), sections: {}}
|
|
47
|
+
section = section(:notes)
|
|
48
|
+
record[:sections][:notes] = section
|
|
49
|
+
elsif sub_header?(line)
|
|
50
|
+
section = section(section_type(line))
|
|
51
|
+
record[:sections][section.type] = section
|
|
52
|
+
else
|
|
53
|
+
section << task(line)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
entry_list << entry(record) if record
|
|
58
|
+
entry_list.sort
|
|
59
|
+
rescue => e
|
|
60
|
+
raise "File malformation: #{e}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Writes entries to a markdown standup file.
|
|
65
|
+
#
|
|
66
|
+
# @param [String] file_name
|
|
67
|
+
# @param [StandupMD::EntryList] entries
|
|
68
|
+
# @param [Date] start_date
|
|
69
|
+
# @param [Date] end_date
|
|
70
|
+
#
|
|
71
|
+
# @return [Boolean]
|
|
72
|
+
def write(file_name, entries, start_date:, end_date:)
|
|
73
|
+
::File.open(file_name, "w") do |f|
|
|
74
|
+
entries.filter(start_date, end_date).sort_reverse.each do |entry|
|
|
75
|
+
f.puts Title.new(entry.date).to_markdown
|
|
76
|
+
config.sub_header_order.each do |attr|
|
|
77
|
+
section = Section.new(attr, entry.public_send("#{attr}_tasks"))
|
|
78
|
+
next if section.empty?
|
|
79
|
+
|
|
80
|
+
f.puts section.to_markdown
|
|
81
|
+
end
|
|
82
|
+
f.puts
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
true
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Renders a task as a markdown list item.
|
|
90
|
+
#
|
|
91
|
+
# @param [String, StandupMD::Task] task
|
|
92
|
+
#
|
|
93
|
+
# @return [String]
|
|
94
|
+
def task_line(task)
|
|
95
|
+
build_task(task).to_markdown
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def header?(line)
|
|
101
|
+
line.match?(header_regex)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def sub_header?(line)
|
|
105
|
+
line.match?(sub_header_regex)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def header_regex
|
|
109
|
+
/^#{"#" * config.header_depth}\s+/
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def sub_header_regex
|
|
113
|
+
/^#{"#" * config.sub_header_depth}\s+/
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def title(line)
|
|
117
|
+
line.sub(/^\#{#{config.header_depth}}\s*/, "")
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def section(type)
|
|
121
|
+
Section.new(type)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def section_type(line)
|
|
125
|
+
sub_header = line.sub(/^\#{#{config.sub_header_depth}}\s*/, "")
|
|
126
|
+
Entry::SECTION_TYPES.each do |type|
|
|
127
|
+
header = config.public_send("#{type}_header")
|
|
128
|
+
return type if sub_header.include?(header)
|
|
129
|
+
end
|
|
130
|
+
raise "Unrecognized header [#{sub_header}]"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def task(line)
|
|
134
|
+
match = line.match(task_regex)
|
|
135
|
+
return Task.new(line) unless match
|
|
136
|
+
|
|
137
|
+
Task.new(
|
|
138
|
+
match[:text],
|
|
139
|
+
indent_level: match[:indent].size / config.indent_width
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def task_regex
|
|
144
|
+
/\A(?<indent>\s*)#{Regexp.escape(config.bullet_character)}\s*(?<text>.*)\z/
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def entry(record)
|
|
148
|
+
Entry.new(
|
|
149
|
+
Date.strptime(record[:title], config.header_date_format),
|
|
150
|
+
tasks(record, :current),
|
|
151
|
+
tasks(record, :previous),
|
|
152
|
+
tasks(record, :impediments),
|
|
153
|
+
tasks(record, :notes)
|
|
154
|
+
)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def tasks(record, type)
|
|
158
|
+
record[:sections].fetch(type, Section.new(type)).tasks
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def build_task(task)
|
|
162
|
+
return task if task.is_a?(Task)
|
|
163
|
+
|
|
164
|
+
Task.new(task)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "standup_md/task"
|
|
4
|
+
|
|
5
|
+
module StandupMD
|
|
6
|
+
##
|
|
7
|
+
# A named section of a standup entry, such as current, previous,
|
|
8
|
+
# impediments, or notes.
|
|
9
|
+
class Section
|
|
10
|
+
##
|
|
11
|
+
# The semantic section type.
|
|
12
|
+
#
|
|
13
|
+
# @return [Symbol]
|
|
14
|
+
attr_reader :type
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Tasks for the section.
|
|
18
|
+
#
|
|
19
|
+
# @return [Array<StandupMD::Task>]
|
|
20
|
+
attr_reader :tasks
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Constructs an instance of +StandupMD::Section+.
|
|
24
|
+
#
|
|
25
|
+
# @param [Symbol, String] type
|
|
26
|
+
# @param [Array<String, StandupMD::Task>] tasks
|
|
27
|
+
def initialize(type, tasks = [])
|
|
28
|
+
@type = type.to_sym
|
|
29
|
+
@tasks = tasks.map { |task| build_task(task) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Adds a task to the section.
|
|
34
|
+
#
|
|
35
|
+
# @param [String, StandupMD::Task] task
|
|
36
|
+
#
|
|
37
|
+
# @return [Array<StandupMD::Task>]
|
|
38
|
+
def <<(task)
|
|
39
|
+
tasks << build_task(task)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# Is the section empty?
|
|
44
|
+
#
|
|
45
|
+
# @return [Boolean]
|
|
46
|
+
def empty?
|
|
47
|
+
tasks.empty?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# The configured section heading.
|
|
52
|
+
#
|
|
53
|
+
# @return [String]
|
|
54
|
+
def to_s
|
|
55
|
+
StandupMD.config.file.public_send("#{type}_header")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# The section rendered as markdown lines.
|
|
60
|
+
#
|
|
61
|
+
# @return [Array<String>]
|
|
62
|
+
def to_markdown
|
|
63
|
+
[
|
|
64
|
+
"#" * StandupMD.config.file.sub_header_depth + " " + to_s,
|
|
65
|
+
*tasks.map(&:to_markdown)
|
|
66
|
+
]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def build_task(task)
|
|
72
|
+
return task if task.is_a?(Task)
|
|
73
|
+
|
|
74
|
+
Task.new(task)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StandupMD
|
|
4
|
+
##
|
|
5
|
+
# A single standup task. The text stays format-neutral, while indentation
|
|
6
|
+
# level lets parsers render nested tasks for their own formats.
|
|
7
|
+
class Task
|
|
8
|
+
##
|
|
9
|
+
# The task text.
|
|
10
|
+
#
|
|
11
|
+
# @return [String]
|
|
12
|
+
attr_reader :text
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# The nesting level of the task.
|
|
16
|
+
#
|
|
17
|
+
# @return [Integer]
|
|
18
|
+
attr_reader :indent_level
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Constructs an instance of +StandupMD::Task+.
|
|
22
|
+
#
|
|
23
|
+
# @param [String] text
|
|
24
|
+
# @param [Integer] indent_level
|
|
25
|
+
def initialize(text, indent_level: 0)
|
|
26
|
+
unless indent_level.is_a?(Integer) && !indent_level.negative?
|
|
27
|
+
raise ArgumentError, "Indent level must be a non-negative integer"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@text = text.to_s
|
|
31
|
+
@indent_level = indent_level
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# The format-neutral task text.
|
|
36
|
+
#
|
|
37
|
+
# @return [String]
|
|
38
|
+
def to_s
|
|
39
|
+
text
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# The task rendered as a markdown list item.
|
|
44
|
+
#
|
|
45
|
+
# @return [String]
|
|
46
|
+
def to_markdown
|
|
47
|
+
indent = " " * StandupMD.config.file.indent_width * indent_level
|
|
48
|
+
"#{indent}#{StandupMD.config.file.bullet_character} #{text}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# Compares task contents.
|
|
53
|
+
def ==(other)
|
|
54
|
+
return text == other if other.is_a?(String)
|
|
55
|
+
return false unless other.is_a?(Task)
|
|
56
|
+
|
|
57
|
+
text == other.text && indent_level == other.indent_level
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "date"
|
|
4
|
+
|
|
5
|
+
module StandupMD
|
|
6
|
+
##
|
|
7
|
+
# The title for a standup entry.
|
|
8
|
+
class Title
|
|
9
|
+
##
|
|
10
|
+
# The entry date.
|
|
11
|
+
#
|
|
12
|
+
# @return [Date]
|
|
13
|
+
attr_reader :date
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Constructs an instance of +StandupMD::Title+.
|
|
17
|
+
#
|
|
18
|
+
# @param [Date] date
|
|
19
|
+
def initialize(date)
|
|
20
|
+
raise ArgumentError, "Must be a Date object" unless date.is_a?(Date)
|
|
21
|
+
|
|
22
|
+
@date = date
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# The configured title text.
|
|
27
|
+
#
|
|
28
|
+
# @return [String]
|
|
29
|
+
def to_s
|
|
30
|
+
date.strftime(StandupMD.config.file.header_date_format)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# The title rendered as markdown.
|
|
35
|
+
#
|
|
36
|
+
# @return [String]
|
|
37
|
+
def to_markdown
|
|
38
|
+
"#" * StandupMD.config.file.header_depth + " " + to_s
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/standup_md/version.rb
CHANGED
|
@@ -9,19 +9,19 @@ module StandupMD
|
|
|
9
9
|
# Major version.
|
|
10
10
|
#
|
|
11
11
|
# @return [Integer]
|
|
12
|
-
MAJOR =
|
|
12
|
+
MAJOR = 1
|
|
13
13
|
|
|
14
14
|
##
|
|
15
15
|
# Minor version.
|
|
16
16
|
#
|
|
17
17
|
# @return [Integer]
|
|
18
|
-
MINOR =
|
|
18
|
+
MINOR = 0
|
|
19
19
|
|
|
20
20
|
##
|
|
21
21
|
# Patch version.
|
|
22
22
|
#
|
|
23
23
|
# @return [Integer]
|
|
24
|
-
PATCH =
|
|
24
|
+
PATCH = 0
|
|
25
25
|
|
|
26
26
|
##
|
|
27
27
|
# Version as +[MAJOR, MINOR, PATCH]+
|
data/lib/standup_md.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "standup_md/version"
|
|
4
|
-
require "standup_md/
|
|
4
|
+
require "standup_md/config"
|
|
5
|
+
require "standup_md/task"
|
|
6
|
+
require "standup_md/title"
|
|
7
|
+
require "standup_md/section"
|
|
5
8
|
require "standup_md/entry"
|
|
6
9
|
require "standup_md/entry_list"
|
|
10
|
+
require "standup_md/parsers/markdown"
|
|
11
|
+
require "standup_md/file"
|
|
7
12
|
require "standup_md/cli"
|
|
8
|
-
require "standup_md/config"
|
|
9
13
|
|
|
10
14
|
##
|
|
11
15
|
# The main module for the gem. Provides access to configuration classes.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: standup_md
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Evan Gray
|
|
@@ -107,6 +107,7 @@ files:
|
|
|
107
107
|
- Rakefile
|
|
108
108
|
- _config.yml
|
|
109
109
|
- bin/standup
|
|
110
|
+
- completion/zsh/_standup
|
|
110
111
|
- lib/standup_md.rb
|
|
111
112
|
- lib/standup_md/cli.rb
|
|
112
113
|
- lib/standup_md/cli/helpers.rb
|
|
@@ -118,7 +119,10 @@ files:
|
|
|
118
119
|
- lib/standup_md/entry.rb
|
|
119
120
|
- lib/standup_md/entry_list.rb
|
|
120
121
|
- lib/standup_md/file.rb
|
|
121
|
-
- lib/standup_md/
|
|
122
|
+
- lib/standup_md/parsers/markdown.rb
|
|
123
|
+
- lib/standup_md/section.rb
|
|
124
|
+
- lib/standup_md/task.rb
|
|
125
|
+
- lib/standup_md/title.rb
|
|
122
126
|
- lib/standup_md/version.rb
|
|
123
127
|
- standup_md.gemspec
|
|
124
128
|
homepage: https://evanthegrayt.github.io/standup_md/
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module StandupMD
|
|
4
|
-
class File
|
|
5
|
-
##
|
|
6
|
-
# Module responsible for reading and writing standup files.
|
|
7
|
-
module Helpers # :nodoc:
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
def header?(line) # :nodoc:
|
|
11
|
-
line.match(header_regex)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def sub_header?(line) # :nodoc:
|
|
15
|
-
line.match(sub_header_regex)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def header_regex # :nodoc:
|
|
19
|
-
/^#{"#" * StandupMD.config.file.header_depth}\s+/
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def sub_header_regex # :nodoc:
|
|
23
|
-
/^#{"#" * StandupMD.config.file.sub_header_depth}\s+/
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def bullet_character_regex # :nodoc:
|
|
27
|
-
/\s*#{StandupMD.config.file.bullet_character}\s*/
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def determine_section_type(line) # :nodoc:
|
|
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
|
|
37
|
-
].each { |header| return header if line.include?(header) }
|
|
38
|
-
raise "Unrecognized header [#{line}]"
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def new_entry(record) # :nodoc:
|
|
42
|
-
Entry.new(
|
|
43
|
-
Date.strptime(
|
|
44
|
-
record["header"],
|
|
45
|
-
StandupMD.config.file.header_date_format
|
|
46
|
-
),
|
|
47
|
-
record[StandupMD.config.file.current_header],
|
|
48
|
-
record[StandupMD.config.file.previous_header],
|
|
49
|
-
record[StandupMD.config.file.impediments_header],
|
|
50
|
-
record[StandupMD.config.file.notes_header]
|
|
51
|
-
)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def header(date)
|
|
55
|
-
"#" * StandupMD.config.file.header_depth +
|
|
56
|
-
" " +
|
|
57
|
-
date.strftime(StandupMD.config.file.header_date_format)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def sub_header(subhead)
|
|
61
|
-
"#" * StandupMD.config.file.sub_header_depth + " " + subhead
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|