mirror of
https://git.sr.ht/~magic_rb/website
synced 2024-11-24 09:06:15 +01:00
Changes
Signed-off-by: Magic_RB <magic_rb@redalder.org>
This commit is contained in:
parent
35c8893dc8
commit
6b441371bf
|
@ -1,5 +1,14 @@
|
|||
@font-face {
|
||||
font-family: "Ubuntu Medium";
|
||||
src: url(/ttf/ubuntu-medium.ttf) format("truetype");
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "monospace";
|
||||
font-family: "Ubuntu Medium";
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0 0 0 1rem;
|
||||
}
|
||||
|
||||
code {
|
||||
|
@ -7,3 +16,45 @@ code {
|
|||
background: #ACACAC;
|
||||
padding: 0.1rem;
|
||||
}
|
||||
|
||||
#table-of-contents {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#content :is(h1, h2, h3, h4, h5, h6) {
|
||||
display: inline;
|
||||
border-bottom: 0.15rem solid #165578;
|
||||
width: 100%;
|
||||
padding-bottom: 0.1rem;
|
||||
line-height: 1.75em;
|
||||
}
|
||||
|
||||
#organizer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#content p {
|
||||
flex-basis: auto;
|
||||
text-align: justify;
|
||||
text-justify: inter-word;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 768px) {
|
||||
#organizer {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#content {
|
||||
flex-basis: 80%;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex-basis: 10%;
|
||||
}
|
||||
}
|
||||
|
|
BIN
assets/ttf/ubuntu-medium.ttf
Normal file
BIN
assets/ttf/ubuntu-medium.ttf
Normal file
Binary file not shown.
|
@ -1,34 +1,33 @@
|
|||
#+TITLE: Emacs, the Journey to an Operating System
|
||||
* Emacs, the Journey to an Operating System
|
||||
** The Age without Emacs
|
||||
It's the 12th of February, I'm playing Factorio on my laptop, when the bell rings and not long
|
||||
after my Biology teacher enters the classroom, I quickly save and exit out of Factorio. After the
|
||||
usual formalities I sit down and open my editor, so that I can take notes during the lesson. As
|
||||
you might have guessed, I didn't open Emacs, instead I opened VSCode, yes I know, not even
|
||||
VSCodium, but the prorietary spyware-filled version. I then open a new Markdown file and started
|
||||
typing away. This procedure repeated multiple times during the day, until school ended and I got
|
||||
home, I sat down in front of my desktop and opened CLion, because I wanted to do some coding in
|
||||
Rust. I had VSCode opened on my desktop too, as I needed access to my notes, when one of my
|
||||
classmates wanted them. I had two completely different editors opened almost all the time and
|
||||
even vim, when I logged into remote servers and got to editing some =Dockerfile=. \\
|
||||
\\
|
||||
That is roughly how my day went, before I switched full time to Emacs and learned of all the
|
||||
features the Emacs operating system has. I didn't even realize, how much I was missing out on
|
||||
and how painful my existence was. Let's go over the different pain points I now, in retrospect,
|
||||
realize existed.
|
||||
* The Age without Emacs
|
||||
It's the 12th of February, I'm playing Factorio on my laptop, when the bell rings and not long
|
||||
after my Biology teacher enters the classroom, I quickly save and exit out of Factorio. After the
|
||||
usual formalities I sit down and open my editor, so that I can take notes during the lesson. As
|
||||
you might have guessed, I didn't open Emacs, instead I opened VSCode, yes I know, not even
|
||||
VSCodium, but the prorietary spyware-filled version. I then open a new Markdown file and started
|
||||
typing away. This procedure repeated multiple times during the day, until school ended and I got
|
||||
home, I sat down in front of my desktop and opened CLion, because I wanted to do some coding in
|
||||
Rust. I had VSCode opened on my desktop too, as I needed access to my notes, when one of my
|
||||
classmates wanted them. I had two completely different editors opened almost all the time and
|
||||
even vim, when I logged into remote servers and got to editing some =Dockerfile=. \\
|
||||
\\
|
||||
That is roughly how my day went, before I switched full time to Emacs and learned of all the
|
||||
features the Emacs operating system has. I didn't even realize, how much I was missing out on
|
||||
and how painful my existence was. Let's go over the different pain points I now, in retrospect,
|
||||
realize existed.
|
||||
|
||||
*** The Pain
|
||||
If you're an Emacs veteran, you surely have already noticed everything I'll point out in the
|
||||
next few paragraphs, but please do read on as I present my unique view on the issues.
|
||||
** The Pain
|
||||
If you're an Emacs veteran, you surely have already noticed everything I'll point out in the
|
||||
next few paragraphs, but please do read on as I present my unique view on the issues.
|
||||
|
||||
**** Multiple Editors
|
||||
Let's start with the most obvious one, during "A day in the Life of Me", I would switch between
|
||||
3 different editors, being, in increasing order of time spent in each, VSCode, CLion and Vim.
|
||||
This brings with it many issues, including but not limited to: keybindings, plugins/addons,
|
||||
look&feel, features and even supported files/projects. The editors could be split into two
|
||||
categories, classic: "CLion, VSCode" and "Vim". If you've spend even a minute on a *nix system,
|
||||
you must know what Vim is and that, let's be honest, it has a weird, alien control scheme. This
|
||||
"Weirdness" is even supported by a multitude of memes, such as:
|
||||
*** Multiple Editors
|
||||
Let's start with the most obvious one, during "A day in the Life of Me", I would switch between
|
||||
3 different editors, being, in increasing order of time spent in each, VSCode, CLion and Vim.
|
||||
This brings with it many issues, including but not limited to: keybindings, plugins/addons,
|
||||
look&feel, features and even supported files/projects. The editors could be split into two
|
||||
categories, classic: "CLion, VSCode" and "Vim". If you've spend even a minute on a *nix system,
|
||||
you must know what Vim is and that, let's be honest, it has a weird, alien control scheme. This
|
||||
"Weirdness" is even supported by a multitude of memes, such as:
|
||||
|
||||
|
||||
|
||||
|
|
79
blog/on-databases-docker-and-nix.org
Normal file
79
blog/on-databases-docker-and-nix.org
Normal file
|
@ -0,0 +1,79 @@
|
|||
#+TITLE: On Docker Databases and Nixos
|
||||
While learning Hashicorp Nomad+Vault+Consul, I decided that I'd convert all the Docker containers I use currently,
|
||||
into their Nix-ified forms. In other words, I'd rewrite the ones I had, but I'd based them on NixOS, a truly
|
||||
declarative enviroment, unlike /ehm/ all the other base images... Well, I didn't realize how *hard* it is to
|
||||
"dockerize" databases, databases are inherently programs, which deal almost exclusively with state, as opposed to Nix
|
||||
and Docker, which are both declarative systems (one of them is trying and failing really hard).
|
||||
|
||||
** Configuration
|
||||
Configuration is a rather big part of what systems administrator(DevOps engineer for the cool kids) does, one must
|
||||
correctly configure a program, most of the time dynamically. And because this is such an important thing, it baffles
|
||||
me, why 90% of all containers primarily use and support environment variables. I get that it's a convenient way to do
|
||||
it, it's simple widely supported, uniform, all around great, but *really* cumbersome. Say your config file looks like
|
||||
this:
|
||||
|
||||
#+BEGIN_SRC conf
|
||||
# stripped down Gitea configuration, I kept the parts that nicely illustrate my point
|
||||
[server]
|
||||
APP_DATA_PATH = /data/gitea
|
||||
ROOT_URL = https://gitea.redalder.org/
|
||||
DOMAIN = gitea.redalder.org
|
||||
|
||||
[database]
|
||||
DB_TYPE = postgres
|
||||
HOST = database-postgres
|
||||
NAME = gitea
|
||||
#+END_SRC
|
||||
|
||||
The config has two sections, =server= and =database=, each of these sections has =n= key-value pairs. This has
|
||||
structure, it has multiple layers and configuration files can get much, much more complex than that. Now, for the
|
||||
sake of argument, let's imagine that we want to "environment-ize" this config. The natural, and frankly only way to
|
||||
do this is to essentially flatten the config file, so we'd get something like this:
|
||||
|
||||
#+BEGIN_SRC conf
|
||||
SERVER_APP_DATA_PATH="/data/gitea"
|
||||
SERVER_ROOT_URL="https://gitea.redalder.org/"
|
||||
SERVER_DOMAIN="gitea.redalder.org"
|
||||
|
||||
DATABASE_DB_TYPE="postgres"
|
||||
DATABASE_HOST="database-postgres"
|
||||
DATABASE_NAME="gitea"
|
||||
#+END_SRC
|
||||
|
||||
Now, you might think that this is completely fine, even reasonable, but let me explain to you why that is horrible.
|
||||
First of, there is no imposed structure and structure is always good, nothing is preventing you from mixing the
|
||||
=server= and =database= sections and while a "good" admin should not do that, it's best if they don't even have the
|
||||
ability. Next depending on the parser, which parses this "configuration", you might encounter issues when you leave
|
||||
out =""=, some are better at this than others, but once again, it's an implicit rule, which is bad. I hope you're
|
||||
starting to understand the bigger picture, implicitness is *bad*, period. It introduces unnecessary mistakes that
|
||||
could have been avoided if just the computer yelled at you. So why not give it the option to do that?
|
||||
|
||||
** Configuration and Databases
|
||||
Now, it's finally time to combine databases with configuration. What we get is an all out war between immutable,
|
||||
declarative environments holding stateful and infinitely changing data. You must make sure that your configuration
|
||||
gets applied only at first start, so you must keep state yourself! In a Docker container! Madness! Then comes the
|
||||
joy of updating the configuration. Say you give your user the option to specify the default authentication method
|
||||
([[https://hub.docker.com/_/postgres][PostgreSQL]]), the user specifies that they want =scram-sha-256=, that's nice and all, so you apply it, but *only* on
|
||||
the first boot. Why? Because now that the value is in the config file, if the user changed it, you'd have to figure
|
||||
out *if* they changed it and then update the configuration file and that's really hard. The user might have gone into
|
||||
where they store the state for PostgreSQL and manually changed the config file, they might have even completely
|
||||
deleted your configuration and replaced it with their own? What should you do? Most Docker containers just take the
|
||||
easy way out and do as PostgreSQL does and I don't blame them, there is nothing really that you can do.
|
||||
|
||||
** Nix - The Solution?
|
||||
Similar to some good literature, this rant has gone full circle. We're back at the start, back on the topic of
|
||||
Nix. How can Nix save us? By removing unnecessary state. The mutable configuration file? Gone, it's immutable
|
||||
now. Not knowing whether a setting changed? Poof, gone too, Nix is fully declarative, which means it identifies
|
||||
*everything* by a sha256 hash in addition to its developer configured name. Nix also serves as a single point of
|
||||
truth, which means even if the user modifies the config files, they will be overwritten before they are used
|
||||
again. This makes mix ups are impossible. Messy and flat "configuration" files? Solved too, the Nix expression language can be
|
||||
as flat or as deep as you need it to be, you can create complex APIs with functions and all that jazz. Basically Nix
|
||||
is awesome!
|
||||
|
||||
** Conclusion
|
||||
The take-away from this rant, is that the best course of action is to figure out either how to completely replace
|
||||
Docker and all the other container runtimes with something based on Nix, but since I'm a realist, I propose another
|
||||
possible solution. We must get Nix to nicely work with Docker, so instead of clumsy environment variables, you'd
|
||||
write your configuration in the form of Nix expressions and build a new docker image based on one common base. This
|
||||
ensure that all configuration would be properly hashed and declarative, while allowing for much more complex config
|
||||
files than environment variables or even templates.
|
92
make.el
92
make.el
|
@ -5,11 +5,101 @@
|
|||
;;; Code:
|
||||
(load-file "./org-thtml/ox-thtml.el")
|
||||
(require 'org)
|
||||
(require 'ox)
|
||||
(require 'ox-html)
|
||||
|
||||
(dolist (d '("public_html"))
|
||||
(unless (file-exists-p d)
|
||||
(make-directory d)))
|
||||
|
||||
;; https://alhassy.github.io/AlBasmala.html#Floating-TOC
|
||||
(advice-add 'org-html--translate :before-until 'display-toc-as-toc)
|
||||
(defun display-toc-as-toc (phrase info)
|
||||
(when (equal phrase "Table of Contents")
|
||||
"<a>
|
||||
TOC
|
||||
</a>"))
|
||||
|
||||
;; https://github.com/alphapapa/unpackaged.el#export-to-html-with-useful-anchors
|
||||
(advice-add #'org-export-get-reference :override #'unpackaged/org-export-get-reference)
|
||||
|
||||
(defun unpackaged/org-export-get-reference (datum info)
|
||||
"Like `org-export-get-reference', except uses heading titles instead of random numbers."
|
||||
(let ((cache (plist-get info :internal-references)))
|
||||
(or (car (rassq datum cache))
|
||||
(let* ((crossrefs (plist-get info :crossrefs))
|
||||
(cells (org-export-search-cells datum))
|
||||
;; Preserve any pre-existing association between
|
||||
;; a search cell and a reference, i.e., when some
|
||||
;; previously published document referenced a location
|
||||
;; within current file (see
|
||||
;; `org-publish-resolve-external-link').
|
||||
;;
|
||||
;; However, there is no guarantee that search cells are
|
||||
;; unique, e.g., there might be duplicate custom ID or
|
||||
;; two headings with the same title in the file.
|
||||
;;
|
||||
;; As a consequence, before re-using any reference to
|
||||
;; an element or object, we check that it doesn't refer
|
||||
;; to a previous element or object.
|
||||
(new (or (cl-some
|
||||
(lambda (cell)
|
||||
(let ((stored (cdr (assoc cell crossrefs))))
|
||||
(when stored
|
||||
(let ((old (org-export-format-reference stored)))
|
||||
(and (not (assoc old cache)) stored)))))
|
||||
cells)
|
||||
(when (org-element-property :raw-value datum)
|
||||
;; Heading with a title
|
||||
(unpackaged/org-export-new-title-reference datum cache))
|
||||
;; NOTE: This probably breaks some Org Export
|
||||
;; feature, but if it does what I need, fine.
|
||||
(org-export-format-reference
|
||||
(org-export-new-reference cache))))
|
||||
(reference-string new))
|
||||
;; Cache contains both data already associated to
|
||||
;; a reference and in-use internal references, so as to make
|
||||
;; unique references.
|
||||
(dolist (cell cells) (push (cons cell new) cache))
|
||||
;; Retain a direct association between reference string and
|
||||
;; DATUM since (1) not every object or element can be given
|
||||
;; a search cell (2) it permits quick lookup.
|
||||
(push (cons reference-string datum) cache)
|
||||
(plist-put info :internal-references cache)
|
||||
reference-string))))
|
||||
|
||||
(defun unpackaged/org-export-new-title-reference (datum cache)
|
||||
"Return new reference for DATUM that is unique in CACHE."
|
||||
(cl-macrolet ((inc-suffixf (place)
|
||||
`(progn
|
||||
(string-match (rx bos
|
||||
(minimal-match (group (1+ anything)))
|
||||
(optional "--" (group (1+ digit)))
|
||||
eos)
|
||||
,place)
|
||||
;; HACK: `s1' instead of a gensym.
|
||||
(-let* (((s1 suffix) (list (match-string 1 ,place)
|
||||
(match-string 2 ,place)))
|
||||
(suffix (if suffix
|
||||
(string-to-number suffix)
|
||||
0)))
|
||||
(setf ,place (format "%s--%s" s1 (cl-incf suffix)))))))
|
||||
(let* ((title (org-element-property :raw-value datum))
|
||||
(ref (url-hexify-string (substring-no-properties title)))
|
||||
(parent (org-element-property :parent datum)))
|
||||
(while (--any (equal ref (car it))
|
||||
cache)
|
||||
;; Title not unique: make it so.
|
||||
(if parent
|
||||
;; Append ancestor title.
|
||||
(setf title (concat (org-element-property :raw-value parent)
|
||||
"--" title)
|
||||
ref (url-hexify-string (substring-no-properties title))
|
||||
parent (org-element-property :parent parent))
|
||||
;; No more ancestors: add and increment a number.
|
||||
(inc-suffixf ref)))
|
||||
ref)))
|
||||
|
||||
(defvar org-publish-project-alist)
|
||||
(setq org-publish-project-alist
|
||||
`(("blog-org"
|
||||
|
@ -28,7 +118,7 @@
|
|||
:base-directory ,(expand-file-name "assets/")
|
||||
:publishing-directory ,(expand-file-name "public_html/")
|
||||
:recursive t
|
||||
:base-extension "\\(jpg\\|gif\\|png\\|css\\|js\\|el\\|nb\\|ipynb\\|pdf\\|xml\\)"
|
||||
:base-extension "\\(ttf\\|jpg\\|gif\\|png\\|css\\|js\\|el\\|nb\\|ipynb\\|pdf\\|xml\\)"
|
||||
:publishing-function org-publish-attachment)
|
||||
("blog"
|
||||
:components ("blog-org" "blog-assets"))))
|
||||
|
|
|
@ -2,17 +2,14 @@
|
|||
<html lang="en">
|
||||
{{:include "head.html"}}
|
||||
<body>
|
||||
|
||||
<div id="layout" class="pure-g">
|
||||
<div class="content pure-u-1 pure-u-md-2-3">
|
||||
|
||||
<div id="content">
|
||||
{{:if with-title}}<h1>{{title}}</h1>{{:endif}}
|
||||
{{:if date}}<div class="post-meta">Published on {{format-time-string "%b %d, %Y" date}}</div>{{:endif}}
|
||||
{{contents}}
|
||||
</div>
|
||||
|
||||
<div id="organizer">
|
||||
<div class="sidebar">{{org-html-toc 2 info}}</div>
|
||||
<div id="content">
|
||||
{{:if with-title}}<h1>{{title}}</h1>{{:endif}}
|
||||
{{:if date}}<div class="post-meta">Published on {{format-time-string "%b %d, %Y" date}}</div>{{:endif}}
|
||||
{{contents}}
|
||||
</div>
|
||||
<div class="sidebar"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue