Skip to content

Instantly share code, notes, and snippets.

@rjorgenson
Last active June 2, 2020 14:42
Show Gist options
  • Save rjorgenson/def69e6bb01656328250d1dc0aa56d83 to your computer and use it in GitHub Desktop.
Save rjorgenson/def69e6bb01656328250d1dc0aa56d83 to your computer and use it in GitHub Desktop.
Bear Journal

I created these scripts to generate some daily and monthly notes in Bear.

The launchd scripts will run the daily script every day at 3am and the monthly script on the first of every month at 2am. Make sure to update the path to the actual scripts in the launchd scripts before loading them.

mv com.bearjournal.daily.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.bearjournal.daily.plist

mv com.bearjournal.monthly.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.bearjournal.monthly.plist

You can customize the template in either to add or remove sections.

You can add items to the TASKS_BY_DAY and TASKS_BY_DATE array in dailybear.sh to populate cerains tasks on certain days/dates. This is not super sophisticated or anything but it works. This requires bash v4 or higher, installed via homebrew.

A link to todays note will be added to the end of the monthly note each day. Links to previous notes are also added in other places where appropriate.

The habits table doesn't work very well unless you use a fixed width font. Menlo and Courier are available options in Bear.

A tag hierarchy will be created following #journal/[dailies|monthlies]/year/month

The monthly quote requires jq to be installed. I installed via homebrew.

This is all pretty rough, but it does a thing that I thought might be useful for others so I am throwing it up here. I might update this in the future if I get any other ideas. Feel free to reach out with any questions or ideas!

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.bearjournal.daily</string>
<key>ProgramArguments</key>
<array>
<string>__ADD_PATH_TO_dailybear.sh</string>
</array>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.bearjournal.monthly</string>
<key>ProgramArguments</key>
<array>
<string>__ADD_PATH_TO_monthlybear.sh</string>
</array>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Day</key>
<integer>1</integer>
<key>Hour</key>
<integer>2</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>
</dict>
</plist>
#!/usr/bin/env bash
# function to urlencode values
# https://stackoverflow.com/questions/296536/how-to-urlencode-data-for-curl-command
rawurlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
# REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
# Requires Bash v4 or higher
# add new entries as below
# TASKS_BY_DAY["Some task you want to show up"]="Friday"
# replace Friday with the day you want it to appear on
# matching output of the %A date format
if [[ "${BASH_VERSINFO:-0}" -ge 4 ]]; then
# tasks that you want to show up every particular day
# for example do the laundry every Sunday
# TASKS_BY_DAY["Do the laundry"]="Sunday"
declare -A TASKS_BY_DAY
TASKS_BY_DAY["Do the laundry"]="Sunday"
# tasks that you want to show up on every particular date
# for example pay the cable bill every 10th of the month
# TASKS_BY_DATE["Pay cable bill"]="10"
declare -A TASKS_BY_DATE
TASKS_BY_DATE["Pay cable bill"]="10"
TODAY_DAY=$(date "+%A")
for T in "${!TASKS_BY_DAY[@]}"; do
if [[ ${TASKS_BY_DAY[$T]} == $TODAY_DAY ]]; then
DAILY_TASKS=${DAILY_TASKS}"- [ ] ${T}
"
fi
done
TODAY_DATE=$(date "+%d")
for T in "${!TASKS_BY_DATE[@]}"; do
if [[ ${TASKS_BY_DATE[$T]} == $TODAY_DATE ]]; then
DAILY_TASKS=${DAILY_TASKS}"- [ ] ${T}
"
fi
done
fi
# URL to create new note in bear
NEW_NOTE_URL_TEMPLATE="bear://x-callback-url/create?title=__TITLE__&text=__TEXT__&tags=__TAGS__"
MONTHLY_NOTE_URL_TEMPLATE="bear://x-callback-url/add-text?title=__MONTHLY_NOTE_TITLE__&text=__DAILY_LINK__&mode=append"
DAILY_LINK_TEMPLATE="[__DAILYTITLE__](bear://x-callback-url/open-note?title=__E_NEW_NOTE_TITLE__)"
# grab daily quote to add to note
QUOTE_URL="http://quotes.rest/qod"
QUOTE_JSON=$(curl -s ${QUOTE_URL})
QUOTE=$(echo $QUOTE_JSON | jq '.contents.quotes[0] | .quote')
QUOTE_AUTHOR=$(echo $QUOTE_JSON | jq '.contents.quotes[0] | .author')
# generate link for yesterdays note
YESTERDAY_NOTE_TITLE=$(date -v -1d "+%A, %B %d, %Y")
YESTERDAY_NOTE_LINK=$(echo ${DAILY_LINK_TEMPLATE} | sed "s/__E_NEW_NOTE_TITLE__/${YESTERDAY_NOTE_TITLE}/" | sed "s/__DAILYTITLE__/yesterday/")
# Title of Bear note
# Day, Month Date, Year
NEW_NOTE_TITLE=$(date "+%A, %B %d, %Y")
# Tags for bear note for nested navigation
# dailies/year/month
NEW_NOTE_TAGS=$(date "+journal/dailies/%Y/%B")
# Note template text, new note will be generated on each run matching the below
NEW_NOTE_TEMPLATE="> ${QUOTE}
> - ${QUOTE_AUTHOR}
### do:
- [ ] Carryover incomplete tasks from ${YESTERDAY_NOTE_LINK}
${DAILY_TASKS}
### eat:
- Enter things you ate here
[detailed nutrition info](https://cronometer.com)
### move:
- Enter exercise type things you did here
"
# Title of Monthly tracking note
MONTHLY_NOTE_TITLE=$(date "+%B, %Y")
# urlencode values for generating note
E_NEW_NOTE_TITLE=$(rawurlencode "$NEW_NOTE_TITLE")
E_NEW_NOTE_TEMPLATE=$(rawurlencode "$NEW_NOTE_TEMPLATE")
E_NEW_NOTE_TAGS=$(rawurlencode "$NEW_NOTE_TAGS")
DAILY_LINK=$(echo ${DAILY_LINK_TEMPLATE} | sed "s/__DAILYTITLE__/${NEW_NOTE_TITLE}/" | sed "s/__E_NEW_NOTE_TITLE__/${E_NEW_NOTE_TITLE}/")
E_MONTHLY_NOTE_TITLE=$(rawurlencode "$MONTHLY_NOTE_TITLE")
E_DAILY_LINK=$(rawurlencode "$DAILY_LINK")
E_QUOTE_STRING=$(rawurlencode "$QUOTE_STRING")
# replace placeholders strings in URL with urlencoded values and create note
CREATE_URL=$(echo ${NEW_NOTE_URL_TEMPLATE} | sed "s/__TITLE__/${E_NEW_NOTE_TITLE}/" | sed "s/__TAGS__/${E_NEW_NOTE_TAGS}/" | sed "s/__TEXT__/${E_NEW_NOTE_TEMPLATE}/")
open "$CREATE_URL"
# append link to newly generated note to the monthly tracking note
APPEND_URL=$(echo ${MONTHLY_NOTE_URL_TEMPLATE} | sed "s/__MONTHLY_NOTE_TITLE__/${E_MONTHLY_NOTE_TITLE}/" | sed "s/__DAILY_LINK__/${E_DAILY_LINK}/")
open "$APPEND_URL"
#!/usr/bin/env bash
# function to urlencode the above values
# https://stackoverflow.com/questions/296536/how-to-urlencode-data-for-curl-command
rawurlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
# REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
# Generate bear link to last months note
MONTHLY_URL_TEMPLATE="[__MONTHLYTITLE__](bear://x-callback-url/open-note?title=__E_MONTHLY_NOTE_TITLE__)"
LAST_MONTH_TITLE=$(date -v -1m "+%B, %Y")
LAST_MONTH_URL=$(echo ${MONTHLY_URL_TEMPLATE} | sed "s/__MONTHLYTITLE__/last month/" | sed "s/__E_MONTHLY_NOTE_TITLE__/${LAST_MONTH_TITLE}/")
HABITS_LIST="Gym Read Inbox0 Vitamins"
HABITS="---
"
for h in $HABITS_LIST; do
HABITS=$HABITS"::${h}::
---
"
done
# URL to create new note in bear
NEW_NOTE_URL_TEMPLATE="bear://x-callback-url/create?pin=yes&title=__TITLE__&text=__TEXT__&tags=__TAGS__"
# Title of Bear note
# Day, Month Date, Year
NEW_NOTE_TITLE=$(date "+%B, %Y")
# Tags for bear note for nested navigation
# dailies/year/month
NEW_NOTE_TAGS=$(date "+journal/monthlies/%Y")
# Note template text, new note will be generated on each run matching the below
NEW_NOTE_TEXT="
## Events
- Holidays
-
- Birthdays
-
- Work
-
- Other
-
## Projects
- [ ] Fill out monthly note
- [ ] Holidays
- [ ] Events
- [ ] Birthdays
- [ ] Carry over incomplete projects from ${LAST_MONTH_URL}
## Notable things I did this month
-
## Habits Table
::01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31::
${HABITS}
## Daily Notes
"
# urlencode values for generating note
E_NEW_NOTE_TITLE=$(rawurlencode "$NEW_NOTE_TITLE")
E_NEW_NOTE_TEXT=$(rawurlencode "$NEW_NOTE_TEXT")
E_NEW_NOTE_TAGS=$(rawurlencode "$NEW_NOTE_TAGS")
# replace placeholders strings in URL with urlencoded values
OPENURL=$(echo ${NEW_NOTE_URL_TEMPLATE} | sed "s/__TITLE__/${E_NEW_NOTE_TITLE}/" | sed "s/__TAGS__/${E_NEW_NOTE_TAGS}/" | sed "s/__TEXT__/${E_NEW_NOTE_TEXT}/")
# open the generated URL to create the note in Bear
open "$OPENURL"
@rjorgenson
Copy link
Author

Here are some screenshots of what it might look like in action.

daily note sample
monthly note sample

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment