standup_md 1.0.1 → 2.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/.github/workflows/ruby.yml +4 -6
- data/Gemfile.lock +2 -2
- data/README.md +191 -39
- data/completion/zsh/_standup +12 -17
- data/lib/standup_md/cli/helpers.rb +55 -53
- data/lib/standup_md/cli.rb +40 -22
- data/lib/standup_md/config/cli.rb +70 -7
- data/lib/standup_md/config/entry.rb +31 -1
- data/lib/standup_md/config/file.rb +41 -7
- data/lib/standup_md/config/post.rb +152 -0
- data/lib/standup_md/config.rb +18 -5
- data/lib/standup_md/entry.rb +27 -18
- data/lib/standup_md/entry_list.rb +5 -22
- data/lib/standup_md/file.rb +57 -54
- data/lib/standup_md/parsers/markdown.rb +42 -34
- data/lib/standup_md/post/adapter.rb +41 -0
- data/lib/standup_md/post/adapters/slack.rb +108 -0
- data/lib/standup_md/post/message.rb +47 -0
- data/lib/standup_md/post/result.rb +87 -0
- data/lib/standup_md/post.rb +84 -0
- data/lib/standup_md/section.rb +2 -13
- data/lib/standup_md/task.rb +0 -9
- data/lib/standup_md/version.rb +2 -2
- data/lib/standup_md.rb +2 -2
- data/standup_md.gemspec +1 -0
- metadata +8 -4
- data/lib/standup_md/config/entry_list.rb +0 -29
- data/lib/standup_md/title.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 47c9542a3be072fc9067823aeeaf6c41741e657f7c628476cf1811c3699978f0
|
|
4
|
+
data.tar.gz: 165f18178d4e7038f2c2511e0b7e0e907671c6819f9158fc601c29ebd18ac3be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e56ad3a3e3e633f235af7078708ebb27f1a184cd6a0bd94a1b52299e82de2b75842f169e9495003f26c49907a9f0eb9b5c8d52511bf6cc39e1978f60848a2ca8
|
|
7
|
+
data.tar.gz: 043a1a0119e0921196840fae06143f33a87dbbe4e9b62c381c671defd1695c6e1d5694174872a15932b63c42119dd19764cff992cd3c0f456220f0c9474d15d6
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -10,6 +10,8 @@ on:
|
|
|
10
10
|
jobs:
|
|
11
11
|
test:
|
|
12
12
|
runs-on: ubuntu-22.04
|
|
13
|
+
env:
|
|
14
|
+
BUNDLER_VERSION: 4.0.10
|
|
13
15
|
|
|
14
16
|
strategy:
|
|
15
17
|
fail-fast: false
|
|
@@ -17,14 +19,13 @@ jobs:
|
|
|
17
19
|
ruby-version: ['3.2', '3.3', '4.0']
|
|
18
20
|
|
|
19
21
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
22
|
+
- uses: actions/checkout@v4
|
|
21
23
|
|
|
22
|
-
# Set up Ruby and Bundler
|
|
23
24
|
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
24
25
|
uses: ruby/setup-ruby@v1
|
|
25
26
|
with:
|
|
26
27
|
ruby-version: ${{ matrix.ruby-version }}
|
|
27
|
-
bundler: ${{
|
|
28
|
+
bundler: ${{ env.BUNDLER_VERSION }}
|
|
28
29
|
bundler-cache: true
|
|
29
30
|
|
|
30
31
|
- name: Print Ruby and Bundler versions
|
|
@@ -32,8 +33,5 @@ jobs:
|
|
|
32
33
|
ruby -v
|
|
33
34
|
bundle -v
|
|
34
35
|
|
|
35
|
-
- name: Install dependencies
|
|
36
|
-
run: bundle install --jobs 4 --retry 3
|
|
37
|
-
|
|
38
36
|
- name: Run tests
|
|
39
37
|
run: bundle exec rake
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
standup_md (
|
|
4
|
+
standup_md (2.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 (
|
|
118
|
+
standup_md (2.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
|
@@ -14,8 +14,8 @@ You can view the documentation
|
|
|
14
14
|
[here](https://evanthegrayt.github.io/standup_md/).
|
|
15
15
|
|
|
16
16
|
## About
|
|
17
|
-
I've now been at
|
|
18
|
-
|
|
17
|
+
I've now been at multiple companies where we post our daily standups in a chat
|
|
18
|
+
client, such as Slack, Mattermost, or Riot. Typing out my standup every day
|
|
19
19
|
became tedious, as I'd have to look up what I did the day before, copy and paste
|
|
20
20
|
yesterday's work into a new entry, and add today's tasks. This gem automates
|
|
21
21
|
most of this process, along with providing means of opening the file in your
|
|
@@ -30,7 +30,9 @@ entry exists, it will be added to today's entry as your previous day's work. See
|
|
|
30
30
|
this in your own code somehow.
|
|
31
31
|
|
|
32
32
|
## Installation
|
|
33
|
-
|
|
33
|
+
Requires Ruby 3.2 or newer.
|
|
34
|
+
|
|
35
|
+
If you don't have the permissions to install system-wide gems, you're probably
|
|
34
36
|
also running an older version of ruby. I recommend installing
|
|
35
37
|
[rbenv](https://github.com/rbenv/rbenv#installation), and then installing an
|
|
36
38
|
up-to-date version of ruby.
|
|
@@ -132,6 +134,28 @@ your clipboard without even opening your editor.
|
|
|
132
134
|
standup -p | pbcopy
|
|
133
135
|
```
|
|
134
136
|
|
|
137
|
+
#### Post the entry for today to Slack
|
|
138
|
+
You can also post today's entry directly to a chat client. Slack is the default
|
|
139
|
+
adapter, so `standup -P` and `standup -P slack` are equivalent. Tokens are read
|
|
140
|
+
from environment variables at post time, and are not stored in `~/.standuprc`.
|
|
141
|
+
You can set a default channel via the
|
|
142
|
+
[config](#available-config-file-options-and-defaults) via
|
|
143
|
+
`c.post.configure_adapter(:slack, channel: "C123456")`.
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
export STANDUP_MD_SLACK_TOKEN="xoxb-your-token"
|
|
147
|
+
standup -P slack --post-channel C123456
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The same posting path is available from Ruby:
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
file = StandupMD::File.find_by_date(Date.today).load
|
|
154
|
+
entry = file.entries.find(Date.today)
|
|
155
|
+
|
|
156
|
+
StandupMD::Post.post(entry, adapter: :slack, channel: "C123456")
|
|
157
|
+
```
|
|
158
|
+
|
|
135
159
|
#### Add entry to file without opening it
|
|
136
160
|
You can add an entry for today without even opening your editor. Note that, if
|
|
137
161
|
you have multiple entries, you must separate them with a comma and *no spaces*.
|
|
@@ -142,17 +166,17 @@ standup --no-edit --current "Work on this thing","And another thing"
|
|
|
142
166
|
|
|
143
167
|
### Customization and Runtime Options
|
|
144
168
|
You can create a file in your home directory called `~/.standuprc`. Settings
|
|
145
|
-
located in this file
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
169
|
+
located in this file define your application defaults. CLI flags can override
|
|
170
|
+
those defaults for a single invocation, but they do not persist back into
|
|
171
|
+
`StandupMD.config` or `~/.standuprc`. You can view
|
|
172
|
+
[my config file](https://github.com/evanthegrayt/dotfiles/blob/master/dotfiles/standuprc)
|
|
173
|
+
as an example.
|
|
150
174
|
|
|
151
175
|
You'll notice, a lot of settings don't have the ability to be changed at runtime
|
|
152
|
-
when calling the executable. This is because the
|
|
176
|
+
when calling the executable. This is because the markdown structure is very
|
|
153
177
|
important, and changing values that affect formatting will cause problems with
|
|
154
|
-
the
|
|
155
|
-
config file before you start editing standups.
|
|
178
|
+
the markdown parser. If you don't want to use a default, make the change in
|
|
179
|
+
your config file before you start editing standups.
|
|
156
180
|
|
|
157
181
|
#### Available Config File Options and Defaults
|
|
158
182
|
For command-line usage, this file needs to be named `~/.standuprc`. To use in a
|
|
@@ -161,7 +185,7 @@ rails project, create an initializer (`config/initializers/standup_md.rb`).
|
|
|
161
185
|
```ruby
|
|
162
186
|
StandupMD.configure do |c|
|
|
163
187
|
# Defaults for how the file is formatted.
|
|
164
|
-
# See https://evanthegrayt.github.io/standup_md/doc/StandupMD/Config/
|
|
188
|
+
# See https://evanthegrayt.github.io/standup_md/doc/StandupMD/Config/File.html
|
|
165
189
|
c.file.header_date_format = "%Y-%m-%d"
|
|
166
190
|
c.file.header_depth = 1
|
|
167
191
|
c.file.sub_header_depth = 2
|
|
@@ -191,38 +215,143 @@ StandupMD.configure do |c|
|
|
|
191
215
|
c.cli.edit = true
|
|
192
216
|
c.cli.write = true
|
|
193
217
|
c.cli.print = false
|
|
218
|
+
c.cli.post = false
|
|
219
|
+
c.cli.post_adapter = nil
|
|
220
|
+
c.cli.post_channel = nil
|
|
194
221
|
c.cli.auto_fill_previous = true
|
|
195
222
|
c.cli.preference_file = ::File.expand_path(::File.join(ENV["HOME"], ".standuprc"))
|
|
223
|
+
|
|
224
|
+
# Defaults for posting standups to chat clients.
|
|
225
|
+
c.post.default_adapter = :slack
|
|
226
|
+
c.post.title = nil
|
|
227
|
+
c.post.configure_adapter(
|
|
228
|
+
:slack,
|
|
229
|
+
channel: "C123456",
|
|
230
|
+
token_env: "STANDUP_MD_SLACK_TOKEN"
|
|
231
|
+
)
|
|
196
232
|
end
|
|
197
233
|
```
|
|
198
234
|
|
|
199
235
|
Any options not set in this file will retain their default values. Note that if
|
|
200
|
-
you change `
|
|
236
|
+
you change `name_format`, and don't use a month or year, there will only
|
|
201
237
|
ever be one standup file. This could cause issues long-term, as the files will
|
|
202
238
|
get large over time and possibly cause performance issues.
|
|
203
239
|
|
|
204
240
|
|
|
205
241
|
#### Executable Flags
|
|
206
|
-
Some
|
|
242
|
+
Some defaults can be overridden for a single CLI invocation. They are as
|
|
243
|
+
follows.
|
|
207
244
|
|
|
208
|
-
```
|
|
245
|
+
```text
|
|
209
246
|
--current ARRAY List of current entry's tasks
|
|
210
247
|
--previous ARRAY List of previous entry's tasks
|
|
211
248
|
--impediments ARRAY List of impediments for current entry
|
|
212
249
|
--notes ARRAY List of notes for current entry
|
|
213
|
-
--sub-header-order ARRAY The order of the sub-headers when writing the file
|
|
214
|
-
--indent-width INTEGER Number of spaces used for each nested task level
|
|
215
|
-
-f, --file-name-format STRING Date-formattable string to use for standup file name
|
|
216
250
|
-E, --editor EDITOR Editor to use for opening standup files
|
|
217
|
-
-d, --directory DIRECTORY The
|
|
218
|
-
-w
|
|
219
|
-
-a
|
|
220
|
-
-e
|
|
251
|
+
-d, --directory DIRECTORY The directory where standup files are located
|
|
252
|
+
-w, --[no-]write Write current entry if it doesn't exist. Default is true
|
|
253
|
+
-a, --[no-]auto-fill-previous Auto-generate 'previous' tasks for new entries
|
|
254
|
+
-e, --[no-]edit Open the file in the editor. Default is true
|
|
221
255
|
-v, --[no-]verbose Verbose output. Default is false.
|
|
222
256
|
--zsh-completion Print zsh completion setup instructions
|
|
223
257
|
-p, --print [DATE] Print current entry.
|
|
224
258
|
If DATE is passed, will print entry for DATE, if it exists.
|
|
225
|
-
DATE must be in the same format as
|
|
259
|
+
DATE must be in the same format as the entry header date.
|
|
260
|
+
-P, --post [PLATFORM] Post current entry to a chat client. Defaults to Slack.
|
|
261
|
+
If PLATFORM is passed, use that post adapter.
|
|
262
|
+
--post-channel CHANNEL Channel, room, or conversation to post to
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Posting and Secrets
|
|
266
|
+
The built-in Slack adapter sends the rendered markdown entry to Slack's
|
|
267
|
+
`chat.postMessage` API. It needs a Slack token with the `chat:write` scope and a
|
|
268
|
+
channel or conversation. Channel-like IDs such as `C123456`, `G123456`, and
|
|
269
|
+
`D123456` are the most reliable values to use. By default, the token is read
|
|
270
|
+
from `STANDUP_MD_SLACK_TOKEN`.
|
|
271
|
+
|
|
272
|
+
The recommended pattern is to keep secret values in the environment and store
|
|
273
|
+
only non-secret adapter defaults in `~/.standuprc`:
|
|
274
|
+
|
|
275
|
+
```ruby
|
|
276
|
+
StandupMD.configure do |c|
|
|
277
|
+
c.post.configure_adapter(:slack, channel: "C123456")
|
|
278
|
+
end
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Most chat clients now prefer messages to come from an installed app or bot
|
|
282
|
+
instead of a long-lived user token. That keeps permissions clearer, but it also
|
|
283
|
+
means the visible sender might be a general name like "StandupMD" rather than
|
|
284
|
+
the person whose update is being posted. Set `c.post.title` to identify the
|
|
285
|
+
standup owner in the message title without changing the markdown files that
|
|
286
|
+
StandupMD parses.
|
|
287
|
+
|
|
288
|
+
```ruby
|
|
289
|
+
StandupMD.configure do |c|
|
|
290
|
+
c.post.title = "%s - Evan Gray"
|
|
291
|
+
end
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
The `%s` placeholder is replaced with the normal entry title, usually the entry
|
|
295
|
+
date, so a stored `# 2026-06-27` entry posts as
|
|
296
|
+
`# 2026-06-27 - Evan Gray`.
|
|
297
|
+
|
|
298
|
+
To use a different token variable, set `token_env`.
|
|
299
|
+
|
|
300
|
+
```ruby
|
|
301
|
+
StandupMD.configure do |c|
|
|
302
|
+
c.post.configure_adapter(
|
|
303
|
+
:slack,
|
|
304
|
+
channel: "C123456",
|
|
305
|
+
token_env: "WORK_SLACK_TOKEN"
|
|
306
|
+
)
|
|
307
|
+
end
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### Custom Post Adapters
|
|
311
|
+
Adapters are registered in `~/.standuprc`. They receive a
|
|
312
|
+
`StandupMD::Post::Message`, which includes the rendered markdown text and the
|
|
313
|
+
channel passed through `StandupMD::Post.post` or `--post-channel`.
|
|
314
|
+
|
|
315
|
+
```ruby
|
|
316
|
+
class TeamsAdapter
|
|
317
|
+
def initialize(options = {})
|
|
318
|
+
@options = options
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def post(message)
|
|
322
|
+
channel = message.channel || @options[:channel]
|
|
323
|
+
token = ENV.fetch("TEAMS_TOKEN")
|
|
324
|
+
|
|
325
|
+
# Send message.text to channel with token.
|
|
326
|
+
|
|
327
|
+
StandupMD::Post::Result.success(
|
|
328
|
+
adapter: message.adapter,
|
|
329
|
+
channel: channel
|
|
330
|
+
)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
StandupMD.configure do |c|
|
|
335
|
+
c.post.register_adapter(:teams, TeamsAdapter)
|
|
336
|
+
c.post.configure_adapter(:teams, channel: "team-channel-id")
|
|
337
|
+
end
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Custom adapters can be used from either the CLI or the Ruby API:
|
|
341
|
+
|
|
342
|
+
```ruby
|
|
343
|
+
StandupMD::Post.post(entry, adapter: :teams, channel: "team-channel-id")
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
For request-scoped API usage, copy the global defaults and pass the copy into
|
|
347
|
+
the operation:
|
|
348
|
+
|
|
349
|
+
```ruby
|
|
350
|
+
runtime = StandupMD.config.copy
|
|
351
|
+
runtime.post.default_adapter = :teams
|
|
352
|
+
runtime.post.configure_adapter(:teams, channel: "team-channel-id")
|
|
353
|
+
|
|
354
|
+
StandupMD::Post.post(entry, config: runtime)
|
|
226
355
|
```
|
|
227
356
|
|
|
228
357
|
#### Using Existing Standup Files
|
|
@@ -242,8 +371,8 @@ they must be in a format that the parser can understand. The default is:
|
|
|
242
371
|
```
|
|
243
372
|
|
|
244
373
|
The order, words, date format, and header level are all customizable, but the
|
|
245
|
-
overall format must be the same. If customization is necessary,
|
|
246
|
-
|
|
374
|
+
overall format must be the same. If customization is necessary, set the defaults
|
|
375
|
+
or pass a runtime config before reading the file, or else the parser will error.
|
|
247
376
|
|
|
248
377
|
For example, if you wanted the format to be as follows:
|
|
249
378
|
|
|
@@ -279,9 +408,30 @@ end
|
|
|
279
408
|
The API is fully documented in the
|
|
280
409
|
[RDoc Documentation](https://evanthegrayt.github.io/standup_md/).
|
|
281
410
|
|
|
282
|
-
This was mainly written as a command line utility, but the API is
|
|
283
|
-
|
|
284
|
-
|
|
411
|
+
This was mainly written as a command line utility, but the API is available for
|
|
412
|
+
use in your own projects. `StandupMD.config` stores application defaults. For
|
|
413
|
+
web requests, jobs, or any other multi-call environment, copy those defaults and
|
|
414
|
+
pass the copy into the operation you are running.
|
|
415
|
+
|
|
416
|
+
`StandupMD::File` handles reading and writing files on disk. The markdown parser
|
|
417
|
+
handles markdown strings:
|
|
418
|
+
|
|
419
|
+
```ruby
|
|
420
|
+
parser = StandupMD::Parsers::Markdown.new
|
|
421
|
+
entries = parser.parse(File.read("2026_06.md"))
|
|
422
|
+
markdown = parser.render(entries, start_date: entries.first.date, end_date: entries.last.date)
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
```ruby
|
|
426
|
+
runtime = StandupMD.config.copy
|
|
427
|
+
runtime.file.directory = "/tmp/request-standups"
|
|
428
|
+
runtime.entry.current = ["Work scoped to this request"]
|
|
429
|
+
|
|
430
|
+
file = StandupMD::File.find_by_date(Date.today, config: runtime.file).load
|
|
431
|
+
entry = StandupMD::Entry.create(config: runtime.entry)
|
|
432
|
+
file.entries << entry
|
|
433
|
+
file.write
|
|
434
|
+
```
|
|
285
435
|
|
|
286
436
|
### API Examples
|
|
287
437
|
#### Adding an entry for today
|
|
@@ -289,27 +439,29 @@ new entry via code could look like the following:
|
|
|
289
439
|
require "standup_md"
|
|
290
440
|
|
|
291
441
|
StandupMD.configure do |c|
|
|
292
|
-
c.file.current_header = "Today"
|
|
442
|
+
c.file.current_header = "Today"
|
|
293
443
|
end
|
|
294
444
|
|
|
295
|
-
file = StandupMD::File.find_by_date(Date.today)
|
|
296
|
-
entry = StandupMD::Entry.create
|
|
445
|
+
file = StandupMD::File.find_by_date(Date.today).load
|
|
446
|
+
entry = StandupMD::Entry.create(current: ["Stuff I will do today"])
|
|
297
447
|
file.entries << entry
|
|
298
448
|
file.write
|
|
299
449
|
```
|
|
300
450
|
|
|
301
|
-
The above example
|
|
302
|
-
|
|
451
|
+
The above example uses global defaults. To keep runtime choices scoped to one
|
|
452
|
+
request, copy the defaults and pass the copy into each operation.
|
|
303
453
|
|
|
304
454
|
```ruby
|
|
305
455
|
require "standup_md"
|
|
306
456
|
|
|
307
|
-
StandupMD.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
end
|
|
457
|
+
runtime = StandupMD.config.copy
|
|
458
|
+
runtime.file.current_header = "Today"
|
|
459
|
+
runtime.entry.current = ["Stuff I will do today"]
|
|
311
460
|
|
|
312
|
-
StandupMD::File.find_by_date(Date.today).load
|
|
461
|
+
file = StandupMD::File.find_by_date(Date.today, config: runtime.file).load
|
|
462
|
+
entry = StandupMD::Entry.create(config: runtime.entry)
|
|
463
|
+
file.entries << entry
|
|
464
|
+
file.write
|
|
313
465
|
```
|
|
314
466
|
|
|
315
467
|
#### Finding a past entry
|
|
@@ -349,7 +501,7 @@ command, that file will be opened. There's tab completion for this. Lastly,
|
|
|
349
501
|
it allows for a few variables to be set for customization.
|
|
350
502
|
|
|
351
503
|
```vim
|
|
352
|
-
g:standup_dir = $HOME . '/.cache/standup_md' " the directory where your
|
|
504
|
+
g:standup_dir = $HOME . '/.cache/standup_md' " the directory where your files are
|
|
353
505
|
g:standup_file = strftime('%Y_%m.md') " the file format to use
|
|
354
506
|
```
|
|
355
507
|
|
data/completion/zsh/_standup
CHANGED
|
@@ -4,19 +4,6 @@ _standup_array_values() {
|
|
|
4
4
|
_message -e values 'comma-separated list'
|
|
5
5
|
}
|
|
6
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
7
|
_standup_dates() {
|
|
21
8
|
local directory="${STANDUP_MD_DIR:-$HOME/.cache/standup_md}"
|
|
22
9
|
local index
|
|
@@ -53,6 +40,16 @@ _standup_dates() {
|
|
|
53
40
|
fi
|
|
54
41
|
}
|
|
55
42
|
|
|
43
|
+
_standup_post_adapters() {
|
|
44
|
+
local -a adapters
|
|
45
|
+
|
|
46
|
+
adapters=(
|
|
47
|
+
'slack:Slack chat.postMessage adapter'
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
_describe -t adapters 'post adapter' adapters
|
|
51
|
+
}
|
|
52
|
+
|
|
56
53
|
_arguments -s -S \
|
|
57
54
|
'(- *)'{-h,--help}'[show help]' \
|
|
58
55
|
'(- *)--version[show version]' \
|
|
@@ -61,10 +58,6 @@ _arguments -s -S \
|
|
|
61
58
|
'--previous[List of previous entry tasks]:tasks:_standup_array_values' \
|
|
62
59
|
'--impediments[List of impediments for current entry]:impediments:_standup_array_values' \
|
|
63
60
|
'--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
61
|
'(-E --editor)-E[Editor to use for opening standup files]:editor:_path_commands' \
|
|
69
62
|
'(-E --editor)--editor[Editor to use for opening standup files]:editor:_path_commands' \
|
|
70
63
|
'(-d --directory)-d[The directory where standup files are located]:directory:_directories' \
|
|
@@ -78,4 +71,6 @@ _arguments -s -S \
|
|
|
78
71
|
'(-v --verbose --no-verbose)'{-v,--verbose}'[use verbose output]' \
|
|
79
72
|
'(-v --verbose --no-verbose)--no-verbose[disable verbose output]' \
|
|
80
73
|
'(-p --print)'{-p,--print}'[print current entry]::date:_standup_dates' \
|
|
74
|
+
'(-P --post)'{-P,--post}'[post current entry to a chat client]::platform:_standup_post_adapters' \
|
|
75
|
+
'--post-channel[channel, room, or conversation to post to]:channel:' \
|
|
81
76
|
'1:standup file date:_standup_dates'
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "standup_md/parsers/markdown"
|
|
4
|
+
require "standup_md/post"
|
|
4
5
|
|
|
5
6
|
module StandupMD
|
|
6
7
|
class Cli
|
|
7
8
|
##
|
|
8
|
-
#
|
|
9
|
+
# Helpers for CLI commands and option handling.
|
|
9
10
|
module Helpers
|
|
10
11
|
##
|
|
11
12
|
# Print an entry to the command line.
|
|
@@ -16,17 +17,26 @@ module StandupMD
|
|
|
16
17
|
def print(entry)
|
|
17
18
|
return puts "No record found for #{config.cli.date}" if entry.nil?
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
tasks = entry.public_send("#{header_type}_tasks")
|
|
22
|
-
next if tasks.empty?
|
|
20
|
+
$stdout.print markdown.render_entry(entry)
|
|
21
|
+
end
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
##
|
|
24
|
+
# Post an entry to the configured chat adapter.
|
|
25
|
+
#
|
|
26
|
+
# @param [StandupMD::Entry] entry
|
|
27
|
+
#
|
|
28
|
+
# @return [StandupMD::Post::Result, nil]
|
|
29
|
+
def post(entry)
|
|
30
|
+
return puts "No record found for #{config.cli.date}" if entry.nil?
|
|
31
|
+
|
|
32
|
+
result = StandupMD::Post.post(
|
|
33
|
+
entry,
|
|
34
|
+
adapter: config.cli.post_adapter,
|
|
35
|
+
channel: config.cli.post_channel,
|
|
36
|
+
config: config
|
|
37
|
+
)
|
|
38
|
+
puts "Could not post to #{result.adapter}: #{result.error}" if result.failure?
|
|
39
|
+
result
|
|
30
40
|
end
|
|
31
41
|
|
|
32
42
|
private
|
|
@@ -36,12 +46,12 @@ module StandupMD
|
|
|
36
46
|
#
|
|
37
47
|
# @return [StandupMD::Config]
|
|
38
48
|
def config # :nodoc:
|
|
39
|
-
|
|
49
|
+
@config
|
|
40
50
|
end
|
|
41
51
|
|
|
42
52
|
##
|
|
43
|
-
# Parses options passed at runtime
|
|
44
|
-
#
|
|
53
|
+
# Parses options passed at runtime into this CLI invocation's config
|
|
54
|
+
# snapshot. Reveal source to see options.
|
|
45
55
|
#
|
|
46
56
|
# @return [Hash]
|
|
47
57
|
def load_runtime_preferences(options)
|
|
@@ -68,21 +78,6 @@ module StandupMD
|
|
|
68
78
|
"List of notes for current entry"
|
|
69
79
|
) { |v| config.entry.notes = v }
|
|
70
80
|
|
|
71
|
-
opts.on(
|
|
72
|
-
"--sub-header-order ARRAY", Array,
|
|
73
|
-
"The order of the sub-headers when writing the file"
|
|
74
|
-
) { |v| config.file.sub_header_order = v }
|
|
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
|
-
|
|
81
|
-
opts.on(
|
|
82
|
-
"-f", "--file-name-format STRING",
|
|
83
|
-
"Date-formattable string to use for standup file name"
|
|
84
|
-
) { |v| config.file.name_format = v }
|
|
85
|
-
|
|
86
81
|
opts.on(
|
|
87
82
|
"-E", "--editor EDITOR",
|
|
88
83
|
"Editor to use for opening standup files"
|
|
@@ -90,7 +85,7 @@ module StandupMD
|
|
|
90
85
|
|
|
91
86
|
opts.on(
|
|
92
87
|
"-d", "--directory DIRECTORY",
|
|
93
|
-
"The
|
|
88
|
+
"The directory where standup files are located"
|
|
94
89
|
) { |v| config.file.directory = v }
|
|
95
90
|
|
|
96
91
|
opts.on(
|
|
@@ -122,12 +117,26 @@ module StandupMD
|
|
|
122
117
|
"-p", "--print [DATE]",
|
|
123
118
|
"Print current entry.",
|
|
124
119
|
"If DATE is passed, will print entry for DATE, if it exists.",
|
|
125
|
-
"DATE must be in the same format as
|
|
120
|
+
"DATE must be in the same format as the entry header date."
|
|
126
121
|
) do |v|
|
|
127
122
|
config.cli.print = true
|
|
128
123
|
config.cli.date =
|
|
129
124
|
v.nil? ? Date.today : Date.strptime(v, config.file.header_date_format)
|
|
130
125
|
end
|
|
126
|
+
|
|
127
|
+
opts.on(
|
|
128
|
+
"-P", "--post [PLATFORM]",
|
|
129
|
+
"Post current entry to a chat client. Defaults to Slack.",
|
|
130
|
+
"If PLATFORM is passed, use that post adapter."
|
|
131
|
+
) do |v|
|
|
132
|
+
config.cli.post = true
|
|
133
|
+
config.cli.post_adapter = v.nil? ? config.post.default_adapter : v.to_sym
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
opts.on(
|
|
137
|
+
"--post-channel CHANNEL",
|
|
138
|
+
"Channel, room, or conversation to post to"
|
|
139
|
+
) { |v| config.cli.post_channel = v }
|
|
131
140
|
end.parse!(options)
|
|
132
141
|
if zsh_completion_requested?
|
|
133
142
|
raise OptionParser::InvalidArgument, options.join(" ") unless options.empty?
|
|
@@ -165,7 +174,10 @@ module StandupMD
|
|
|
165
174
|
# @return [Array]
|
|
166
175
|
def previous_entry(file)
|
|
167
176
|
return config.entry.previous unless config.cli.auto_fill_previous
|
|
168
|
-
|
|
177
|
+
if file.new?
|
|
178
|
+
previous_file = prev_file_exists?
|
|
179
|
+
return prev_entry_tasks(previous_file.load.entries) if previous_file
|
|
180
|
+
end
|
|
169
181
|
|
|
170
182
|
prev_entry_tasks(file.entries)
|
|
171
183
|
end
|
|
@@ -202,34 +214,24 @@ module StandupMD
|
|
|
202
214
|
##
|
|
203
215
|
# The previous month's file.
|
|
204
216
|
#
|
|
217
|
+
# @param [StandupMD::Config::File] config
|
|
218
|
+
#
|
|
205
219
|
# @return [StandupMD::File]
|
|
206
|
-
def prev_file
|
|
207
|
-
StandupMD::File.find_by_date(Date.today.prev_month)
|
|
220
|
+
def prev_file(config: self.config.file)
|
|
221
|
+
StandupMD::File.find_by_date(Date.today.prev_month, config: config)
|
|
208
222
|
end
|
|
209
223
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
#
|
|
215
|
-
# @return [String]
|
|
216
|
-
def header(entry)
|
|
217
|
-
"#" * config.file.header_depth + " " +
|
|
218
|
-
entry.date.strftime(config.file.header_date_format)
|
|
224
|
+
def prev_file_exists?
|
|
225
|
+
without_file_creation { |file_config| prev_file(config: file_config) }
|
|
226
|
+
rescue StandupMD::File::NotFoundError
|
|
227
|
+
nil
|
|
219
228
|
end
|
|
220
229
|
|
|
221
230
|
##
|
|
222
|
-
#
|
|
231
|
+
# Markdown renderer used for CLI output.
|
|
223
232
|
#
|
|
224
|
-
# @
|
|
225
|
-
|
|
226
|
-
# @return [String]
|
|
227
|
-
def sub_header(header_type)
|
|
228
|
-
"#" * config.file.sub_header_depth + " " +
|
|
229
|
-
config.file.public_send("#{header_type}_header")
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def parser
|
|
233
|
+
# @return [StandupMD::Parsers::Markdown]
|
|
234
|
+
def markdown
|
|
233
235
|
StandupMD::Parsers::Markdown.new(config.file)
|
|
234
236
|
end
|
|
235
237
|
end
|