With my online course building journey, I had to keep track of the slides it has. My coach has set me goal and it looked like a really hard one to reach, but it seemed doable. I wanted it to be a challenge. By some numbers I got from the previous month, I came up to the conclusion that I can build on average around three slides per day. I was quite comfortable with that number but coach though different.
Make it four.
This was his words. He personally went similar journey before me and he knew how to push himself. Being a coach, he also knows how to push others that need help. Jumping from three to four slides a day does not seem like a lot but it meant increase from 90 to 120 slides. Doing 4 slides a day, I would be finished in around 23 days, which would leave me with exactly 7 days for other projects and relax. Now all 30 days of the upcoming month were already occupied in my calendar.
Presentation arrangement
I am bulding the slides by using pandoc. Pandoc is a great piece of software that allows me to transform markdown text into revealJS presentation. Which is just another great tool and if you do not know about these, just take a look. They both contain more features than I could count.
One of the concepts that RevealJS provides which is not common among other presentation engines I have tried (PowerPoint, LibreOffice Impress or LaTeX Beamer) is that it provides two-dimensional slide arrangement. It makes a grid with vertical and horizontal slides. All of the former have only one dimension, or at least it held true up until time I had tried them without much special configuration.
Markdowns level 1 heading (denoted by a single hashtag #
) get's converted
to a horizontal slide. You can thing of a horizontal slide as a chapter
name. It denotes a part of the presentation, but does not bear any content
to itself. All level 2 headings (denoted by double hashtag ##
) get
converted by a vertical slide below the current horizontal one, up to the
next vertical one. Only vertical slides show content (text, bullet lists,
images, ...). It feels really logical and neat to me. As a side bonus, when
you press o
key, it displays you a whole 2D outline of your presentation,
which looks like a grid.
Counting slides
Since a whole course is a one gigantic .md
file, which of course is
stored as a text format, we can simply count all level 2 headings in that
file to get a number of slides programatically. Syntax is for grep
:
grep "##" presentation.md | wc -l
And the_silver_searcher
is the same:
ag "##" presentation.md | wc -l
If you do not use
the_silver_searcher, it is
also one of the tools worth looking into. It claims to be much
faster than grep. It can save you a few
miliseconds here and there. As a side note, ag
is only two characters,
which is half compared to grep
. Unless you have an alias that looks
something like alias gr='grep'
, it laso saves you keystrokes.
The result displays a single number that shows the count of lines containing level 2 markdown heading, which represents number of horizontal slides in the presentation. Since only horizontal slides have a content, this is precisely all we need.
Google Calendar API
At first, I ust thought updating an event in a gCal would be really fast, but I could not be further from the truth. The HTTP API documentation for PATCH method shows tidy URL. PATCH is the method usually used in REST API to update part of the entity.
PATCH https://www.googleapis.com/calendar/v3/calendars/calendarId/events/eventId
Yeah, nice! I just run a curl
or it's newer cousin,
httpie request to update some information in the
Google calendar event and I am done. Well, it requires three additional
pieces of information:
- calendarId
- eventId
- authorization
I had tried looking at URL browsing gCal web UI, but I could not find any
IDs there, nor anywhere in the settings. The authorization part was even
more complicated. If you have never enabled a Calendar API, it is a lot of
steps. I will not explain them here, because they are docuemnted by the
Google itself, and as anything Google, they are suject to (frequent)
change. What I ended up doing was enabling it and not used curl
, nor
any other plain request tool, because handling OAuth2 access and
refresh tokens in bash would be a hassle. There is also an older API key
based way, which could work easily, but it has some limitations and it was
not completely clear
to me, if it is still a feasible option, thus I went with OAuth2 option.
The update script
Google Calendar API also supports multiple languages (more are being added):
- Go
- Java
- JavaScript
- node.js
- PHP
- Python
- Ruby
My course is made as a node.js project, so naturally I have followed the
provided quickstart [example](https://developers.google.com/calenda
r/quickstart/nodejs). Unfortunately, it only shows how to create an event,
not how to update the existing one. I have tried learning more about the
node API for Calendar patch
method
here
but somehow, I could not understand a word there. Again, StackOverflow for
the help. The
post
here shows the guidelins to updating the event. By combining these three
resorces I was able to get a working script, you can have a look at the
source.
Bash in node
If you dig through the script, you might find one another oddity: function
lineCount
. It calls a bash command we have found earlier in a node
script. I could do it straight up in the node, so it would not be such a
tangled mess, but hey, I had it already figured out and life is short.
Following a Medium
article
provided not one but multiple already working options to do this. I have
chosen the one that uses promises. Even though the quickstart article used
callbacks, I wanted to progressively evolve the script to only use arrow
functions and async/await
syntax in the end, if possible.
Git hooks
Git hook is a technique to call certain scripts during a git lifecycle.
There is a lot of them. You can learn more by studying sample files
ls .git/hooks/*.sample
in your repository or by man githooks
. Since
there is a lot of them, choosing the right one can be difficult. Initially
I have thought that I use post-push
, but as I have later learned, such a
hook does not exist in git! The StackOverflow's
post was
first thing that popped up in the search results, explaining that this hook
would require the remote repository to execute the code, which is not
implemented.
The next thing in line was pre-push
hook. Usually, pre-hooks are used to
perform checks before executing an action (for example checking for wording
in commit mesage). I did not need perform any checks to be performed, I
just wanted to call a script together with the git push
. This time, it
did not matter if it was performed before or after the push, so I used it.
One another question was where to put hooks to be tracked by git. Putting
hooks inside .git/hooks/
directory makes them work, but git wont list
them as untracked files. If a hook is part of the overal project, you have
to put them elsewhere. This Medium
article
outlines a concept to put tehme inside hooks/
directory and symlink them
to .git
repository.
mkdir hooks
cd hooks
touch pre-push
cd ..
# CAUTION: the -f parameter overwrites destination!
ln -s -f ../../hooks/pre-push ./git/hooks/pre-push
Wrapping up
By setting this working script as a pre-push
git hook, I was able to
update my Google Calendar event automatically together with git push
. Now
the advantages are threefold:
- I can see the slides count straight up
- My couch can track my progress
- My girlfriend can see if I am meeting my goals or if I need more help
The third one is especially helpful, if you have a committed, helpful girlfriend like I do. It helps us plan out relax time much better this way.
Hopefully, this guide was helpful to you in some way, be it general knowledge, task automation, git concepts or you are just curious. If you have any questions, please contact me.