new.sh
#!/bin/sh
set -eu
week="$(date +%Gw%V)"
today="$(date +%Y%m%d)"
clock=""
apply_date() {
local when="$1" mode="$2"
case "$when" in
yesterday) today="$(date -v-1d +%Y%m%d)"; week="$(date -v-1d +%Gw%V)";;
tomorrow) today="$(date -v+1d +%Y%m%d)"; week="$(date -v+1d +%Gw%V)";;
next) today="$(date -v+1w +%Y%m%d)"; week="$(date -v+1w +%Gw%V)";;
last) today="$(date -v-1w +%Y%m%d)"; week="$(date -v-1w +%Gw%V)";;
+[0-9]*)
local n="${when#+}"
if test "$mode" = w; then
today="$(date -v+"${n}"w +%Y%m%d)"; week="$(date -v+"${n}"w +%Gw%V)"
else
today="$(date -v+"${n}"d +%Y%m%d)"; week="$(date -v+"${n}"d +%Gw%V)"
fi;;
-[0-9]*)
local n="${when#-}"
if test "$mode" = w; then
today="$(date -v-"${n}"w +%Y%m%d)"; week="$(date -v-"${n}"w +%Gw%V)"
else
today="$(date -v-"${n}"d +%Y%m%d)"; week="$(date -v-"${n}"d +%Gw%V)"
fi;;
[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
today="$when"
week="$(date -jf %Y%m%d "$when" +%Gw%V)";;
*) echo "Unknown date offset: $when" >&2; exit 1;;
esac
clock="$(date -jf %Y%m%d "$today" "+%Y-%m-%dT12:00:00.00%z" | sed 's/\(..\)$/:\1/')"
}
hugo_new() {
if test -n "$clock"; then
set -- --clock "$clock" "$@"
fi
exec hugo new content --editor code "$@"
}
usage() {
cat <<EOF
Usage: $0 <command> [options] [slug]
Commands:
day [-k kind] [-d when] <slug> Create a day post (default kind: daypost)
week [-d when] [slug] Create a week log (no slug) or week post (with slug)
page <path> Create an arbitrary page
Date offsets (-d):
yesterday, tomorrow — shift by one day
next, last — shift by one week
+N, -N — shift by N days (day) or N weeks (week)
YYYYMMDD — specific date
Examples (today: $today, week: $week):
COMMAND CREATES
$0 day meeting-notes log/$week/${today}-meeting-notes/index.md
$0 day -d yesterday meeting-notes log/$week/${today}-meeting-notes/index.md
$0 week log/$week/_index.md
$0 week projects log/$week/projects/index.md
$0 week -d next log/$week/_index.md
$0 week -d next projects log/$week/projects/index.md
$0 page notes/workstation-setup/index.md notes/workstation-setup/index.md
EOF
}
case "${1:-}" in
day)
shift
kind=daypost
while test $# -gt 0; do
case "$1" in
-k) kind="$2"; shift 2;;
-d) apply_date "$2" d; shift 2;;
-*) echo "Unknown option: $1" >&2; exit 1;;
*) slug="$1"; shift;;
esac
done
if test -z "${slug:-}"; then
echo "Usage: $0 day [-k kind] <slug>" >&2
exit 1
fi
hugo_new --kind "$kind" "log/$week/${today}-${slug}/index.md"
;;
week)
shift
slug=""
while test $# -gt 0; do
case "$1" in
-d) apply_date "$2" w; shift 2;;
-*) echo "Unknown option: $1" >&2; exit 1;;
*) slug="$1"; shift;;
esac
done
if test -z "$slug"; then
hugo_new --kind weeklog "log/$week/_index.md"
else
hugo_new --kind weekpost "log/$week/${slug}/index.md"
fi
;;
page)
shift
if test -z "${1:-}"; then
echo "Usage: $0 page <path>" >&2
exit 1
fi
hugo_new "$1"
;;
-h|--help)
usage
exit 0
;;
*)
usage >&2
exit 1
;;
esac
vscode.settings.json
{
"vim.leader": "<space>",
"vim.normalModeKeyBindingsNonRecursive": [
{
"before": ["<leader>", "H"],
"commands": [
{
"command": "workbench.action.tasks.runTask",
"args": "Open hugo page in browser"
}
]
}
]
}
vscode.tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Open hugo page in browser",
"type": "shell",
"command": "bash",
"args": [
"-c",
"FILE='${relativeFile}'; if [[ $FILE != content/*.md ]]; then exit 0; fi; P=${FILE#content/}; P=${P%.md}; P=${P%_index}; P=${P%index}; P=${P%/}; open \"http://localhost:1313/$P/\""
],
"presentation": {
"reveal": "never",
"panel": "shared",
"clear": true
},
"problemMatcher": []
}
]
}
archetypes.daypost.md
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
tags:
- daypost
---
archetypes.weeklog.md
---
{{- define "isoDateYear" -}}
{{- /* Return the ISO year based on the week number */ -}}
{{ $wd := sub (int now.Weekday) 1 }}{{ if lt $wd 0 }}{{ $wd = 6 }}{{ end }}{{ $thu := now.AddDate 0 0 (sub 3 $wd) }}{{ $week := add 1 (div (sub $thu.YearDay 1) 7) }}{{ printf "%d" $thu.Year }}
{{- end -}}
{{- define "isoDateWeek" -}}
{{- /* Return the ISO week number */ -}}
{{ $wd := sub (int now.Weekday) 1 }}{{ if lt $wd 0 }}{{ $wd = 6 }}{{ end }}{{ $thu := now.AddDate 0 0 (sub 3 $wd) }}{{ $week := add 1 (div (sub $thu.YearDay 1) 7) }}{{ printf "%02d" $week }}
{{- end -}}
title: {{ template "isoDateYear" }} Week {{ template "isoDateWeek" }}
date: {{ .Date }} # Set to the date of the week's Monday
isoDate:
Year: {{ template "isoDateYear" }}
Week: {{ template "isoDateWeek" }}
type: weeklog
---
## Weekposts
{{< weekposts >}}
## Monday
### Goals
...
### Other
...
### Pages
{{< daypostsFromOffset 0 >}}
## Tuesday
### Goals
...
### Other
...
### Pages
{{< daypostsFromOffset 1 >}}
## Wednesday
### Goals
...
### Other
...
### Pages
{{< daypostsFromOffset 2 >}}
## Thursday
### Goals
...
### Other
...
### Pages
{{< daypostsFromOffset 3 >}}
## Friday
### Goals
...
### Other
...
### Pages
{{< daypostsFromOffset 4 >}}
archetypes.weekpost.md
---
{{- define "isoWeekId" -}}
{{- /* Return the ISO year based on the week number */ -}}
{{ $wd := sub (int now.Weekday) 1 }}{{ if lt $wd 0 }}{{ $wd = 6 }}{{ end }}{{ $thu := now.AddDate 0 0 (sub 3 $wd) }}{{ $week := add 1 (div (sub $thu.YearDay 1) 7) }}{{ printf "%dw%02d" $thu.Year $week }}
{{- end -}}
title: '{{ template "isoWeekId" }} {{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
tags:
- weekpost
---
content.user.html
<p>
This tool generates links to look up users by username.
It can't know anything about our real directory, so a typo'd user will generate invalid links.
</p>
<style>
#user-info th,
#user-info td {
text-align: left;
}
#user-info th {
padding-right: 1em;
}
</style>
<template id="user-template">
<h2 data-field="username"></h2>
<table>
<tr><th>Slack</th><td><a target="_blank" data-field="slack"></a></td></tr>
<tr><th>Email</th><td><a data-field="email"></a></td></tr>
</table>
</template>
<div id="user-info">
<h2>No user</h2>
<p>Set <code>?u=USERNAME</code> in the URL bar</p>
</div>
<script>
(function() {
const params = new URLSearchParams(window.location.search);
const username = params.get('u');
if (!username) return;
const template = document.getElementById('user-template');
const clone = template.content.cloneNode(true);
clone.querySelector('[data-field="username"]').textContent = username;
const slack = clone.querySelector('[data-field="slack"]');
slack.href = `https://example.slack.com/team/${username}`;
slack.textContent = `@${username}`;
const emailAddr = `${username}@example.com`;
const email = clone.querySelector('[data-field="email"]');
email.href = `mailto:${emailAddr}`;
email.textContent = emailAddr;
const container = document.getElementById('user-info');
container.replaceChildren(clone);
})();
</script>
<!-- -*- mode: html -*- -->
partials.dayPosts.html
{{- $section := .Section -}}
{{- $start := time (.Date | time.Format "2006-01-02") -}}
{{- $end := $start.AddDate 0 0 1 -}}
{{- $pages := where $section.RegularPages "Date" "ge" $start -}}
{{- $pages = where $pages "Date" "lt" $end -}}
{{- $pages = where $pages "Params.tags" "intersect" (slice "daypost") -}}
{{- if $pages }}
<ul>
{{- range $pages.ByDate }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{- end }}
</ul>
{{- else }}
<p>None</p>
{{- end }}
partials.weekPosts.html
{{- $section := .Section -}}
{{- $pages := where $section.RegularPages "Params.tags" "intersect" (slice "weekpost") -}}
{{- if $pages }}
<ul>
{{- range $pages.ByDate }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{- end }}
</ul>
{{- else }}
<p>None</p>
{{- end }}
shortcodes.dayPostsFromOffset.html
{{- $offset := .Get 0 | default 0 | int -}}
{{- $date := .Page.Date -}}
{{- $dateWithOffset := $date.AddDate 0 0 $offset -}}
{{- partial "dayposts.html" (dict "Section" .Page.CurrentSection "Date" $dateWithOffset) -}}
shortcodes.page.html
{{ with .Site.GetPage (.Get 0) }}<a href="{{ .Permalink }}"><cite>{{ .Title }}</cite></a>{{ end }}
shortcodes.u.html
<a class="userlink" href="{{ .Site.BaseURL }}tools/user/?u={{ .Get 0 }}>~{{ .Get 0 }}</a>
shortcodes.weekposts.html
{{- partial "weekposts.html" (dict "Section" .Page.CurrentSection) -}}