Flytte dag - og hvorfor org-mode egentlig bare er sejere end alt andet

Jeg har brugt den seneste uge på at flytte væk fra Ghost blogplatformen. Ikke fordi platformen var ringe på nogen måde (den kan varmt anbefales til andre som gerne vil igang), men mere fordi jeg har fundet noget som passer mig meget bedre. Da jeg startede med at blogge ville jeg bare igang med det samme, og jeg valgte derfor at købe mig til start, og finde ud af hvad der var det bedste: det har jeg fundet ud af nu. Valget faldt på:
- hugo
- org-mode
Jeg har i lang tid sværget til org formatet (og derved også org-mode (og derved også emacs)). Jeg prøvede derfor at finde noget som kunne understøtte org ud af boksen, og jeg fandt hugo, en statisk site generator. Jeg har i den seneste tid flyttet alle mine indlæg over, sat en pipeline op i gitlab, som kan bygge sitet, og udgive det, og du sidder pt og læser resultatet heraf.
Hvis du gerne selv vil igang giver jeg dig her nogle fifs og tricks til hvordan du kan komme igang, og jeg vil til sidst forklare hvorfor org (og org-mode) er langt bedre end alle andre formater (this will blow your mind). Så vær forberedt.
Tips og tricks til hugo start
Hugo, Gitlab, Cloudflare
Man skal selvfølgelig have hugo
installeret. Når det er gjort, kan man gå igang. Jeg vil anbefale at følge quickstart'en, så har du et site sat op på ingen tid (med et meget grimt theme). Jeg har sat et repo op i gitlab, som hoster sitet (faktisk hoster den alle mine noter, og en folderne er en posts folder). Jeg har en pipeline, som flytter alle posts over i på mit site, bygger det, og releaser det. Serveren som hoster sitet er en meget lille server placeret i Finland. Den er frontet af Cloudflare. Opsummering:
- en gitlab repo med posts og site
- en server til at hoste sitet
-
en pipeline som
- bygger sitet
- releaser sitet
- eventuel host det som en gitlab side (det har jeg dog ingen erfaring med)
- Prop en CDN ind foran (Fx Cloudflare)
Pipeline siger du?
Yes! Og jeg vil med glæde del den
image: alpine
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- compile
- release
compile:
stage: compile
script:
- apk update
- apk add hugo
- mkdir -p hugo/content/danish/post
- mkdir hugo/images
- cp posts/*.jpg hugo/static/images
- cp posts/*.png hugo/static/images
- cp posts/*.svg hugo/static/images
- cp -r posts/* hugo/content/danish/post
- rm -rf hugo/content/danish/post/drafts
- cp notes/*-links.org hugo/content/danish/post/2020-01-01-links.org
- hugo version
- cd hugo
- sed -i "s/\$DISQUS_SHORTNAME/$DISQUS_SHORTNAME_KEY/g" config.toml
- sed -i "s/\$GOOGLE_ANALYTICS_ID/$GOOGLE_ANALYTICS_ID_KEY/g" config.toml
- hugo -d ../public
artifacts:
paths:
- public
expire_in: 1 hour
release:
stage: release
script:
- apk update
- apk add openssh-client rsync
- eval $(ssh-agent -s)
- mkdir ~/.ssh
- touch ~/.ssh/config
- echo "$SSH_DOCS_DEPLOY_KEY" | tr -d '\r' | ssh-add -
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- rsync -r public/* user@host:/usr/share/nginx/html
Jeg deployer med ssh. Det theme jeg har skal bruge en disqus shortname og google analytics key. Disse har jeg som variabler i min config.toml
og udskifter dem med sed
. Det samme gør jeg med ssh key'en. Alle disse nøgler er gemt i en gitlab library, som er nem og ligetil at udfylde via UI'et.
Jeg kopierer enkelte noter over som jeg gerne vil have som posts, samt billeder og andet. Det er egentlig meget ligetil.
Org
Og nu til hvorfor jeg skriver dette indlæg: orgmode (og org-roam, og org-babel). Jeg har lavet hele dette setup fordi: jeg elsker org (som er formatet) og orgmode, som er en major mode til emacs, som kan vise formatet. Jeg vil i dette afsnit, og de efterfølgende afsnit prøve at vise hvorfor
orgmode (og hele økosystemet omkring) er betydelig bedre end fx markdown (i alle dens afskygninger). Jeg vil fra nu af referer til org og orgmode, som: orgmode
. Lad mig begynde at slå en ting fast: både orgmode
og fx markdown
kan bruges til at formatere tekst med. I mine øjne er den ene ikke hverken bedre eller værre end den anden. Vil du blot:
- formatere noget tekst, og
- converte det
så er det, i mine øjne ligegyldig hvad du vælger, men her stopper sammenfaldene også. Brat. Orgmode
(og specielt org-roam og org-babel) buldrer videre og efterlader markdown
og alle de andre i støvet. Grædende. Frådende. Efterladt. Tabt.
Orgmode > markdown > text
Man kan i orgmode
formatere alle de ting som man kan i fx markdown. I orgmode
sker dette med #+BEGIN_SRC
og #+END_SRC
#+BEGIN_SRC python
print('hello');
#+END_SRC
Da du læser bloggen kan du også se ved selvsyn hvordan det bliver formateret. Smart. Men kan man ekskrevere det inde i kodeblokken, spørger du (kan jeg høre): JA: 100 gange ja. Man gør det ved, i emacs, at placere cursor'en i kode blokken, og trykke C-c C-c
. org-babel
smider den om til backend'en, ekskrevere koden, og returnere resultatet i en #+RESULTS
. udfører man overstående vil man få følgende tilbage (man kan kun ekskrevere sprog som er understøttet, læs mere her - simpel markup virker dog på et utal af sprog)
#+BEGIN_SRC python
print('hello');
#+END_SRC
#+RESULTS:
: None
Ikke lige hvad vi forventede. Der er flere forskellige modes det kan køres i. Den mode vi leder efter er :results output
. Smider man det på, og udfører koden igen, før man det som man forventer
#+BEGIN_SRC python :results output
print('hello');
#+END_SRC
#+RESULTS:
: hello
Default mode, som er :results code
, gør at man kan returnere fra kode blokken (dvs at det kun er sidste statement som bliver vist i #+RESULTS
, mens :results outout
viser alle print statements
), og derved bruge kode blokken som en funktion (som kan kaldes med #+CALL
andre steder i ens org
dokument … Ja. Det er meta: du kan lave funktioner med kodeblokke, som kan genbruges andre steder i dokumentet host Excel host). Fx har jeg her en kodeblok, som hedder func
og laver efterfølgende en #+CALL: func
som evaluere kodeblokken igen og returnere resultatet igen
#+NAME: func
#+BEGIN_SRC python
return 1-2+100
#+END_SRC
#+RESULTS: func
: 99
Her laver jeg overstående call, som også bliver kaldt når hugo
evaluerer denne org post:
99
En sand meta post jeg har gang i.
Men det kan blive vildere meta endnu
I org-mode
kan man lave tabeller, og det er endda let. Her er en tabel som har fikset sammen til mit interne budget (det bliver lidt personligt men det er ok):
Subscription Name | Monthly Cost (DKK) | Needed | Category |
---|---|---|---|
Netflix | 79 | TV | |
Viaplay | 99 | x | TV |
Yoga | 119 | x | Work |
Disney | 79 | x | TV |
Adobe | 100 | Photo | |
Office 365 | 118 | x | Text |
BackThen | 29 | x | Photo |
Spotify | 149 | x | Music |
Information | 95 | x | News |
Zetland | 129 | x | News |
1Password | 30 | x | Tech |
Server | 80 | x | Tech |
Blog | 220 | Tech |
Kildekoden ser således ud
#+NAME: subscription_table
| Subscription Name | Monthly Cost (DKK) | Needed | Category |
|-------------------+--------------------+--------+----------|
| Netflix | 79 | | TV |
| Viaplay | 99 | x | TV |
| Yoga | 119 | x | Work |
| Disney | 79 | x | TV |
| Adobe | 100 | | Photo |
| Office 365 | 118 | x | Text |
| BackThen | 29 | x | Photo |
| Spotify | 149 | x | Music |
| Information | 95 | x | News |
| Zetland | 129 | x | News |
| 1Password | 30 | x | Tech |
| Server | 80 | x | Tech |
| Blog | 220 | | Tech |
org-mode
har indbygget tabel support, så man bruger blot TAB osv. Den sørger for at indentere, når man laver lange tekster i kolonnerne. Mega fedt, og forventligt, men det kan man jo også (med lidt møje og besvær) i fx notepad, osv: MEN … hvad nu hvis man gerne vil udregne totalen? I Excel kan man bruge SUM
(der findes sådanne indbyggede funktioner i org-mode
også), men hvis man vil lave noget som er lidt mere avanceret, så må man ty til andre midler: programmering. What? Ja! Programmering, som i Excel. Det er her org-babel virkelig kommer til sin ret, da den understøtter et væld af backends, man skal blot have den givne compiler til rådighed. Jeg har valgt at lave udregningen i python
#+NAME: total
#+BEGIN_SRC python :var tabel=subscription_table
total_price = 0;
for row in tabel:
price = row[1]
total_price += price
return total_price
#+END_SRC
#+RESULTS: total
: 1326
Hvis man C-c C-c
selve BEGIN_SRC
så får man, som ved de andre eksempler, vist RESULTS
, tillad mig at gøre det med hugo
total_price = 0;
for row in tabel:
price = row[1]
total_price += price
return total_price
Jeg har lige C-c C-c
'et denne funktion, og den har givet mig følgende resultat
1326
Som i kan se så tager den tabellen som input … OG JA, det jeg lige har kørt, bruger den tabel som du ser ovenover, som input … Det er MINDBLOWN!! Det kan man ikke med markdown
eller med notepad, eller hvad editor man nu lige sidder og bruger. DET ER FEDT! Men det kan blive ViLdErE endnu: grafer :D til det skal vi bruge R
, så det kan lige installeres på din boks. Lad mig vise eksemplet først
#+NAME: only_needed_table
#+BEGIN_SRC python :var tabel=subscription_table
array = []
for row in tabel:
needed = row[2]
if needed == 'x':
array.append(row)
return array
#+END_SRC
#+RESULTS: only_needed_table
| Viaplay | 99 | x | TV |
| Yoga | 119 | x | Work |
| Disney | 79 | x | TV |
| Office 365 | 118 | x | Text |
| BackThen | 29 | x | Photo |
| Spotify | 149 | x | Music |
| Information | 95 | x | News |
| Zetland | 129 | x | News |
| 1Password | 30 | x | Tech |
| Server | 80 | x | Tech |
#+NAME: piechart
#+BEGIN_SRC R :var table=only_needed_table :results file graphics :file ../pie.png
data <- aggregate(x = table[2], by = table[4], FUN = sum)
pie(data[,2], data[,1])
#+END_SRC
Her kører jeg noget python
som outputter de subscriptions som vi SKAL have, til en ny tabel. Den nye tabel bruger jeg som input til noget R
kode som tegner denne piechart
Når man C-c C-c
bliver piechart'en selvfølgelig indsat som et billede i RESULTS
, hvis ens emacs
er bygget med de fornødne visuelle biblioteker (og var R
installeret i gitlab
kom den også med ud når man kørte hugo
)
Excel? Ja: på ketogan, i en natklub med gratis coke.
Konklusion
Jeg er blevet rimelig glad for org-mode
og org-babel
. Jeg har en massiv todo og note struktur, som jeg bruger til både privat og arbejde, hvor jeg hælder alt ned i. Org-mode
kan lave nogle fine TODO
lister, som man kan arbejde med, men det må jeg skrive om en anden gang (man kan lave timere i det og tracke tid!!).
Jeg håber I kunne lide indlægget, og er blevet inspireret til at prøve kræfter med org-mode
, org-babel
, hugo
og git-lab
. Det kan klart anbefales!!