standup_md 1.0.1 → 2.0.1
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 +203 -51
- data/SLACK_SETUP_GUIDE.md +82 -0
- data/completion/zsh/_standup +12 -17
- data/lib/standup_md/cli/helpers.rb +73 -55
- data/lib/standup_md/cli.rb +41 -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 +1 -1
- data/lib/standup_md.rb +2 -2
- data/standup_md.gemspec +1 -0
- metadata +9 -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: d5b3c3f8fe55eadcdc0ae76de9cb745bfe0c557c2c715884fd1056403fba31f1
|
|
4
|
+
data.tar.gz: d7191750ade93198d7a432762eb3327425a0dcb632389dc90ba6216735b941f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cc3f477255e687f122e018ce1e4d31e6ca0ca7d9c16a003c463324230e68e528a97fc08a52194fa98965ae9ca82bfd963d0343f3b38f12526b5f8bb276b832b
|
|
7
|
+
data.tar.gz: c0291b6fabd240ac6b292b4e97c2e5c97ed74afd8675b0274295129625326b94ae2a866ff1dabf89a5e91678537b09b572ab677cc6c87bdbb80d8a2e6e36d401
|
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.1)
|
|
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.1)
|
|
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,12 +14,13 @@ 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
|
|
22
|
-
editor,
|
|
22
|
+
editor, finding and displaying entries from the command line, and posting
|
|
23
|
+
today's standup directly to a chat client.
|
|
23
24
|
|
|
24
25
|
In a nutshell, calling `standup` from the command line will open a standup file
|
|
25
26
|
for the current month in your preferred editor. If an entry for today is already
|
|
@@ -30,7 +31,9 @@ entry exists, it will be added to today's entry as your previous day's work. See
|
|
|
30
31
|
this in your own code somehow.
|
|
31
32
|
|
|
32
33
|
## Installation
|
|
33
|
-
|
|
34
|
+
Requires Ruby 3.2 or newer.
|
|
35
|
+
|
|
36
|
+
If you don't have the permissions to install system-wide gems, you're probably
|
|
34
37
|
also running an older version of ruby. I recommend installing
|
|
35
38
|
[rbenv](https://github.com/rbenv/rbenv#installation), and then installing an
|
|
36
39
|
up-to-date version of ruby.
|
|
@@ -132,6 +135,28 @@ your clipboard without even opening your editor.
|
|
|
132
135
|
standup -p | pbcopy
|
|
133
136
|
```
|
|
134
137
|
|
|
138
|
+
#### Post the entry for today to Slack
|
|
139
|
+
You can also post today's entry directly to a chat client. Slack is the default
|
|
140
|
+
adapter, so `standup -P` and `standup -P slack` are equivalent. Tokens are read
|
|
141
|
+
from environment variables at post time, and are not stored in `~/.standuprc`.
|
|
142
|
+
You can set a default channel via the
|
|
143
|
+
[config](#available-config-file-options-and-defaults) via
|
|
144
|
+
`c.post.configure_adapter(:slack, channel: "C123456")`.
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
export STANDUP_MD_SLACK_TOKEN="xoxb-your-token"
|
|
148
|
+
standup -P slack --post-channel C123456
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The same posting path is available from Ruby:
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
file = StandupMD::File.find_by_date(Date.today).load
|
|
155
|
+
entry = file.entries.find(Date.today)
|
|
156
|
+
|
|
157
|
+
StandupMD::Post.post(entry, adapter: :slack, channel: "C123456")
|
|
158
|
+
```
|
|
159
|
+
|
|
135
160
|
#### Add entry to file without opening it
|
|
136
161
|
You can add an entry for today without even opening your editor. Note that, if
|
|
137
162
|
you have multiple entries, you must separate them with a comma and *no spaces*.
|
|
@@ -142,17 +167,17 @@ standup --no-edit --current "Work on this thing","And another thing"
|
|
|
142
167
|
|
|
143
168
|
### Customization and Runtime Options
|
|
144
169
|
You can create a file in your home directory called `~/.standuprc`. Settings
|
|
145
|
-
located in this file
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
170
|
+
located in this file define your application defaults. CLI flags can override
|
|
171
|
+
those defaults for a single invocation, but they do not persist back into
|
|
172
|
+
`StandupMD.config` or `~/.standuprc`. You can view
|
|
173
|
+
[my config file](https://github.com/evanthegrayt/dotfiles/blob/master/dotfiles/standuprc)
|
|
174
|
+
as an example.
|
|
150
175
|
|
|
151
176
|
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
|
|
177
|
+
when calling the executable. This is because the markdown structure is very
|
|
153
178
|
important, and changing values that affect formatting will cause problems with
|
|
154
|
-
the
|
|
155
|
-
config file before you start editing standups.
|
|
179
|
+
the markdown parser. If you don't want to use a default, make the change in
|
|
180
|
+
your config file before you start editing standups.
|
|
156
181
|
|
|
157
182
|
#### Available Config File Options and Defaults
|
|
158
183
|
For command-line usage, this file needs to be named `~/.standuprc`. To use in a
|
|
@@ -161,7 +186,7 @@ rails project, create an initializer (`config/initializers/standup_md.rb`).
|
|
|
161
186
|
```ruby
|
|
162
187
|
StandupMD.configure do |c|
|
|
163
188
|
# Defaults for how the file is formatted.
|
|
164
|
-
# See https://evanthegrayt.github.io/standup_md/doc/StandupMD/Config/
|
|
189
|
+
# See https://evanthegrayt.github.io/standup_md/doc/StandupMD/Config/File.html
|
|
165
190
|
c.file.header_date_format = "%Y-%m-%d"
|
|
166
191
|
c.file.header_depth = 1
|
|
167
192
|
c.file.sub_header_depth = 2
|
|
@@ -191,38 +216,146 @@ StandupMD.configure do |c|
|
|
|
191
216
|
c.cli.edit = true
|
|
192
217
|
c.cli.write = true
|
|
193
218
|
c.cli.print = false
|
|
219
|
+
c.cli.post = false
|
|
220
|
+
c.cli.post_adapter = nil
|
|
221
|
+
c.cli.post_channel = nil
|
|
194
222
|
c.cli.auto_fill_previous = true
|
|
195
223
|
c.cli.preference_file = ::File.expand_path(::File.join(ENV["HOME"], ".standuprc"))
|
|
224
|
+
|
|
225
|
+
# Defaults for posting standups to chat clients.
|
|
226
|
+
c.post.default_adapter = :slack
|
|
227
|
+
c.post.title = nil
|
|
228
|
+
c.post.configure_adapter(
|
|
229
|
+
:slack,
|
|
230
|
+
channel: "C123456",
|
|
231
|
+
token_env: "STANDUP_MD_SLACK_TOKEN"
|
|
232
|
+
)
|
|
196
233
|
end
|
|
197
234
|
```
|
|
198
235
|
|
|
199
236
|
Any options not set in this file will retain their default values. Note that if
|
|
200
|
-
you change `
|
|
237
|
+
you change `name_format`, and don't use a month or year, there will only
|
|
201
238
|
ever be one standup file. This could cause issues long-term, as the files will
|
|
202
239
|
get large over time and possibly cause performance issues.
|
|
203
240
|
|
|
204
241
|
|
|
205
242
|
#### Executable Flags
|
|
206
|
-
Some
|
|
243
|
+
Some defaults can be overridden for a single CLI invocation. They are as
|
|
244
|
+
follows.
|
|
207
245
|
|
|
208
|
-
```
|
|
246
|
+
```text
|
|
209
247
|
--current ARRAY List of current entry's tasks
|
|
210
248
|
--previous ARRAY List of previous entry's tasks
|
|
211
249
|
--impediments ARRAY List of impediments for current entry
|
|
212
250
|
--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
251
|
-E, --editor EDITOR Editor to use for opening standup files
|
|
217
|
-
-d, --directory DIRECTORY The
|
|
218
|
-
-w
|
|
219
|
-
-a
|
|
220
|
-
-e
|
|
252
|
+
-d, --directory DIRECTORY The directory where standup files are located
|
|
253
|
+
-w, --[no-]write Write current entry if it doesn't exist. Default is true
|
|
254
|
+
-a, --[no-]auto-fill-previous Auto-generate 'previous' tasks for new entries
|
|
255
|
+
-e, --[no-]edit Open the file in the editor. Default is true
|
|
221
256
|
-v, --[no-]verbose Verbose output. Default is false.
|
|
222
257
|
--zsh-completion Print zsh completion setup instructions
|
|
223
258
|
-p, --print [DATE] Print current entry.
|
|
224
259
|
If DATE is passed, will print entry for DATE, if it exists.
|
|
225
|
-
DATE must be in the same format as
|
|
260
|
+
DATE must be in the same format as the entry header date.
|
|
261
|
+
-P, --post [PLATFORM] Post current entry to a chat client. Defaults to Slack.
|
|
262
|
+
If PLATFORM is passed, use that post adapter.
|
|
263
|
+
--post-channel CHANNEL Channel, room, or conversation to post to
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### Posting and Secrets
|
|
267
|
+
For a real-world example of how to get the Slack integration working, see [the
|
|
268
|
+
guide](SLACK_SETUP_GUIDE.md).
|
|
269
|
+
|
|
270
|
+
The built-in Slack adapter sends the rendered markdown entry to Slack's
|
|
271
|
+
`chat.postMessage` API. It needs a Slack token with the `chat:write` scope and a
|
|
272
|
+
channel or conversation. Channel-like IDs such as `C123456`, `G123456`, and
|
|
273
|
+
`D123456` are the most reliable values to use. By default, the token is read
|
|
274
|
+
from `STANDUP_MD_SLACK_TOKEN`.
|
|
275
|
+
|
|
276
|
+
The recommended pattern is to keep secret values in the environment and store
|
|
277
|
+
only non-secret adapter defaults in `~/.standuprc`:
|
|
278
|
+
|
|
279
|
+
```ruby
|
|
280
|
+
StandupMD.configure do |c|
|
|
281
|
+
c.post.configure_adapter(:slack, channel: "C123456")
|
|
282
|
+
end
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Most chat clients now prefer messages to come from an installed app or bot
|
|
286
|
+
instead of a long-lived user token. That keeps permissions clearer, but it also
|
|
287
|
+
means the visible sender might be a general name like "StandupMD" rather than
|
|
288
|
+
the person whose update is being posted. Set `c.post.title` to identify the
|
|
289
|
+
standup owner in the message title without changing the markdown files that
|
|
290
|
+
StandupMD parses.
|
|
291
|
+
|
|
292
|
+
```ruby
|
|
293
|
+
StandupMD.configure do |c|
|
|
294
|
+
c.post.title = "%s - Evan Gray"
|
|
295
|
+
end
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The `%s` placeholder is replaced with the normal entry title, usually the entry
|
|
299
|
+
date, so a stored `# 2026-06-27` entry posts as
|
|
300
|
+
`# 2026-06-27 - Evan Gray`.
|
|
301
|
+
|
|
302
|
+
To use a different token variable, set `token_env`.
|
|
303
|
+
|
|
304
|
+
```ruby
|
|
305
|
+
StandupMD.configure do |c|
|
|
306
|
+
c.post.configure_adapter(
|
|
307
|
+
:slack,
|
|
308
|
+
channel: "C123456",
|
|
309
|
+
token_env: "WORK_SLACK_TOKEN"
|
|
310
|
+
)
|
|
311
|
+
end
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### Custom Post Adapters
|
|
315
|
+
Adapters are registered in `~/.standuprc`. They receive a
|
|
316
|
+
`StandupMD::Post::Message`, which includes the rendered markdown text and the
|
|
317
|
+
channel passed through `StandupMD::Post.post` or `--post-channel`.
|
|
318
|
+
|
|
319
|
+
```ruby
|
|
320
|
+
class TeamsAdapter
|
|
321
|
+
def initialize(options = {})
|
|
322
|
+
@options = options
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def post(message)
|
|
326
|
+
channel = message.channel || @options[:channel]
|
|
327
|
+
token = ENV.fetch("TEAMS_TOKEN")
|
|
328
|
+
|
|
329
|
+
# Send message.text to channel with token.
|
|
330
|
+
|
|
331
|
+
StandupMD::Post::Result.success(
|
|
332
|
+
adapter: message.adapter,
|
|
333
|
+
channel: channel
|
|
334
|
+
)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
StandupMD.configure do |c|
|
|
339
|
+
c.post.register_adapter(:teams, TeamsAdapter)
|
|
340
|
+
c.post.configure_adapter(:teams, channel: "team-channel-id")
|
|
341
|
+
end
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Custom adapters can be used from either the CLI or the Ruby API:
|
|
345
|
+
|
|
346
|
+
```ruby
|
|
347
|
+
StandupMD::Post.post(entry, adapter: :teams, channel: "team-channel-id")
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
For request-scoped API usage, copy the global defaults and pass the copy into
|
|
351
|
+
the operation:
|
|
352
|
+
|
|
353
|
+
```ruby
|
|
354
|
+
runtime = StandupMD.config.copy
|
|
355
|
+
runtime.post.default_adapter = :teams
|
|
356
|
+
runtime.post.configure_adapter(:teams, channel: "team-channel-id")
|
|
357
|
+
|
|
358
|
+
StandupMD::Post.post(entry, config: runtime)
|
|
226
359
|
```
|
|
227
360
|
|
|
228
361
|
#### Using Existing Standup Files
|
|
@@ -242,8 +375,8 @@ they must be in a format that the parser can understand. The default is:
|
|
|
242
375
|
```
|
|
243
376
|
|
|
244
377
|
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
|
-
|
|
378
|
+
overall format must be the same. If customization is necessary, set the defaults
|
|
379
|
+
or pass a runtime config before reading the file, or else the parser will error.
|
|
247
380
|
|
|
248
381
|
For example, if you wanted the format to be as follows:
|
|
249
382
|
|
|
@@ -279,9 +412,30 @@ end
|
|
|
279
412
|
The API is fully documented in the
|
|
280
413
|
[RDoc Documentation](https://evanthegrayt.github.io/standup_md/).
|
|
281
414
|
|
|
282
|
-
This was mainly written as a command line utility, but the API is
|
|
283
|
-
|
|
284
|
-
|
|
415
|
+
This was mainly written as a command line utility, but the API is available for
|
|
416
|
+
use in your own projects. `StandupMD.config` stores application defaults. For
|
|
417
|
+
web requests, jobs, or any other multi-call environment, copy those defaults and
|
|
418
|
+
pass the copy into the operation you are running.
|
|
419
|
+
|
|
420
|
+
`StandupMD::File` handles reading and writing files on disk. The markdown parser
|
|
421
|
+
handles markdown strings:
|
|
422
|
+
|
|
423
|
+
```ruby
|
|
424
|
+
parser = StandupMD::Parsers::Markdown.new
|
|
425
|
+
entries = parser.parse(File.read("2026_06.md"))
|
|
426
|
+
markdown = parser.render(entries, start_date: entries.first.date, end_date: entries.last.date)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
```ruby
|
|
430
|
+
runtime = StandupMD.config.copy
|
|
431
|
+
runtime.file.directory = "/tmp/request-standups"
|
|
432
|
+
runtime.entry.current = ["Work scoped to this request"]
|
|
433
|
+
|
|
434
|
+
file = StandupMD::File.find_by_date(Date.today, config: runtime.file).load
|
|
435
|
+
entry = StandupMD::Entry.create(config: runtime.entry)
|
|
436
|
+
file.entries << entry
|
|
437
|
+
file.write
|
|
438
|
+
```
|
|
285
439
|
|
|
286
440
|
### API Examples
|
|
287
441
|
#### Adding an entry for today
|
|
@@ -289,27 +443,29 @@ new entry via code could look like the following:
|
|
|
289
443
|
require "standup_md"
|
|
290
444
|
|
|
291
445
|
StandupMD.configure do |c|
|
|
292
|
-
c.file.current_header = "Today"
|
|
446
|
+
c.file.current_header = "Today"
|
|
293
447
|
end
|
|
294
448
|
|
|
295
|
-
file = StandupMD::File.find_by_date(Date.today)
|
|
296
|
-
entry = StandupMD::Entry.create
|
|
449
|
+
file = StandupMD::File.find_by_date(Date.today).load
|
|
450
|
+
entry = StandupMD::Entry.create(current: ["Stuff I will do today"])
|
|
297
451
|
file.entries << entry
|
|
298
452
|
file.write
|
|
299
453
|
```
|
|
300
454
|
|
|
301
|
-
The above example
|
|
302
|
-
|
|
455
|
+
The above example uses global defaults. To keep runtime choices scoped to one
|
|
456
|
+
request, copy the defaults and pass the copy into each operation.
|
|
303
457
|
|
|
304
458
|
```ruby
|
|
305
459
|
require "standup_md"
|
|
306
460
|
|
|
307
|
-
StandupMD.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
end
|
|
461
|
+
runtime = StandupMD.config.copy
|
|
462
|
+
runtime.file.current_header = "Today"
|
|
463
|
+
runtime.entry.current = ["Stuff I will do today"]
|
|
311
464
|
|
|
312
|
-
StandupMD::File.find_by_date(Date.today).load
|
|
465
|
+
file = StandupMD::File.find_by_date(Date.today, config: runtime.file).load
|
|
466
|
+
entry = StandupMD::Entry.create(config: runtime.entry)
|
|
467
|
+
file.entries << entry
|
|
468
|
+
file.write
|
|
313
469
|
```
|
|
314
470
|
|
|
315
471
|
#### Finding a past entry
|
|
@@ -349,18 +505,14 @@ command, that file will be opened. There's tab completion for this. Lastly,
|
|
|
349
505
|
it allows for a few variables to be set for customization.
|
|
350
506
|
|
|
351
507
|
```vim
|
|
352
|
-
g:standup_dir = $HOME . '/.cache/standup_md' " the directory where your
|
|
508
|
+
g:standup_dir = $HOME . '/.cache/standup_md' " the directory where your files are
|
|
353
509
|
g:standup_file = strftime('%Y_%m.md') " the file format to use
|
|
354
510
|
```
|
|
355
511
|
|
|
356
|
-
##
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
I do these projects for fun, and I enjoy knowing that they're helpful to people.
|
|
364
|
-
Consider starring [the repository](https://github.com/evanthegrayt/standup_md)
|
|
365
|
-
if you like it! If you love it, follow me [on
|
|
366
|
-
Github](https://github.com/evanthegrayt)!
|
|
512
|
+
## Support this project
|
|
513
|
+
I love knowing when people find my work useful. Any kind of support is very much
|
|
514
|
+
appreciated!
|
|
515
|
+
|
|
516
|
+
- ⭐️ Like the project? Star [the repository](https://github.com/evanthegrayt/standup_md)!
|
|
517
|
+
- ❤️ Love the project? Follow me [on GitHub](https://github.com/evanthegrayt)!
|
|
518
|
+
- 💸 *Really* love it? Consider [buying me a tea](https://paypal.me/evanrgray)!
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Slack Setup for StandupMD Posting
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
Create a private Slack app for your workspace, give its bot permission to post
|
|
5
|
+
messages, install it, copy the bot token, invite the bot to `#general`, and
|
|
6
|
+
configure StandupMD with the bot token plus the channel ID.
|
|
7
|
+
|
|
8
|
+
Workflow last tested and validated 2026-06-27.
|
|
9
|
+
|
|
10
|
+
## Assumptions
|
|
11
|
+
- You only need to post your standup into one Slack channel.
|
|
12
|
+
- The app is just for your own workspace, not a public Slack Marketplace app.
|
|
13
|
+
- `chat:write` plus inviting the bot to `#general` is the preferred setup.
|
|
14
|
+
- `chat:write.public` is not needed unless you want posting to public channels
|
|
15
|
+
without inviting the bot first.
|
|
16
|
+
|
|
17
|
+
## Exact Slack Steps
|
|
18
|
+
1. From the screen in your screenshot, click **Create an App**.
|
|
19
|
+
2. Choose **From scratch**.
|
|
20
|
+
3. Set:
|
|
21
|
+
- **App Name:** `StandupMD`
|
|
22
|
+
- **Pick a workspace:** choose the workspace where `#general` lives
|
|
23
|
+
4. Click **Create App**.
|
|
24
|
+
5. In the app sidebar, go to **OAuth & Permissions**.
|
|
25
|
+
6. Under **Scopes** → **Bot Token Scopes**, add:
|
|
26
|
+
- `chat:write`
|
|
27
|
+
7. Optional: add `chat:write.public` only if you want the bot to post to public
|
|
28
|
+
channels without being invited first. For the simplest and safest setup, skip
|
|
29
|
+
this and invite the bot to the channel.
|
|
30
|
+
8. Scroll up and click **Install to Workspace**.
|
|
31
|
+
9. Approve the installation.
|
|
32
|
+
10. After installation, stay on **OAuth & Permissions** and copy the **Bot User
|
|
33
|
+
OAuth Token**.
|
|
34
|
+
- It should start with `xoxb-`.
|
|
35
|
+
- Do not use an `xoxp-` user token.
|
|
36
|
+
- Do not use an app configuration token.
|
|
37
|
+
|
|
38
|
+
## Channel Setup
|
|
39
|
+
1. In Slack, go to `#general`.
|
|
40
|
+
2. Invite the app/bot:
|
|
41
|
+
```text
|
|
42
|
+
/invite @StandupMD
|
|
43
|
+
```
|
|
44
|
+
3. Get the channel ID for `#general`.
|
|
45
|
+
- Open `#general`.
|
|
46
|
+
- Click the channel name at the top.
|
|
47
|
+
- Look for **Copy channel ID** in the details or more/options menu.
|
|
48
|
+
- The ID should look like `C1234567890`.
|
|
49
|
+
|
|
50
|
+
Prefer using the channel ID over `#general` when configuring StandupMD, as the
|
|
51
|
+
name can change but the ID won't.
|
|
52
|
+
|
|
53
|
+
## StandupMD Values
|
|
54
|
+
Set your token in the shell:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
export STANDUP_MD_SLACK_TOKEN="xoxb-your-bot-token"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Post with the channel ID:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
standup -P slack --post-channel C1234567890
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Optional config in `~/.standuprc`:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
StandupMD.configure do |c|
|
|
70
|
+
c.post.configure_adapter(:slack, channel: "C1234567890")
|
|
71
|
+
c.post.title = "%s -- YOUR NAME"
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then you can run:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
standup -P
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If you have multiple users using the same bot, the `c.post.title` is important
|
|
82
|
+
to specify the user posting the standup, since the bot's name is `StandupMD`.
|
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'
|