mirror of
https://github.com/RGBCube/Site
synced 2025-07-29 12:07:47 +00:00
lume: move to 3.0
This commit is contained in:
parent
f49df20c46
commit
7974d7a806
15 changed files with 1142 additions and 4323 deletions
970
LICENSE_GPL.md
970
LICENSE_GPL.md
File diff suppressed because it is too large
Load diff
|
@ -15,9 +15,11 @@ and the site contents will be under the `_site/` directory.
|
|||
## License
|
||||
|
||||
All the human writing (non-HTML and not templating related) under the `site/`
|
||||
directory is licensed under [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/).
|
||||
directory is licensed under
|
||||
[CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/).
|
||||
|
||||
The other HTML and templating code is licensed under the GPU General Public License (`LICENSE_GPL.md`):
|
||||
The other HTML and templating code is licensed under the GPU General Public
|
||||
License (`LICENSE_GPL.md`):
|
||||
|
||||
```
|
||||
Copyright (C) 2023-present RGBCube
|
||||
|
|
21
_config.ts
21
_config.ts
|
@ -9,12 +9,15 @@ import sitemap from "lume/plugins/sitemap.ts";
|
|||
|
||||
const site = lume({
|
||||
src: "./site",
|
||||
|
||||
server: {
|
||||
debugBar: false,
|
||||
},
|
||||
});
|
||||
|
||||
site.use(codeHighlight());
|
||||
site.use(esbuild());
|
||||
site.add(".");
|
||||
|
||||
site.use(jsx());
|
||||
site.use(minifyHTML());
|
||||
|
||||
site.process([".html"], (pages) => {
|
||||
pages.forEach((page) => {
|
||||
|
@ -30,7 +33,7 @@ site.process([".html"], (pages) => {
|
|||
div.appendChild(table);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".hljs").forEach((code) => {
|
||||
document.querySelectorAll("pre code").forEach((code) => {
|
||||
const pre = code.parentElement!;
|
||||
const div = document.createElement("div");
|
||||
|
||||
|
@ -66,10 +69,14 @@ site.use(feed({
|
|||
}));
|
||||
|
||||
site.use(sitemap({
|
||||
// @ts-ignore: We don't want lastmods.
|
||||
lastmod: null,
|
||||
items: {
|
||||
// @ts-ignore: We don't want lastmods.
|
||||
lastmod: null,
|
||||
},
|
||||
}));
|
||||
|
||||
site.copyRemainingFiles();
|
||||
site.use(esbuild());
|
||||
site.use(codeHighlight());
|
||||
site.use(minifyHTML());
|
||||
|
||||
export default site;
|
||||
|
|
18
deno.json
18
deno.json
|
@ -1,18 +1,24 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "npm:react",
|
||||
"jsxImportSource": "lume",
|
||||
"types": [
|
||||
"lume/types.ts",
|
||||
"https://unpkg.com/@types/react@18.2.37/index.d.ts"
|
||||
"lume/types.ts"
|
||||
]
|
||||
},
|
||||
"tasks": {
|
||||
"build": "echo \"import 'lume/cli.ts'\" | deno run --allow-all -",
|
||||
"serve": "deno task build --serve"
|
||||
"lume": "echo \"import 'lume/cli.ts'\" | deno run --allow-all -",
|
||||
"build": "deno task lume",
|
||||
"serve": "deno task lume --serve"
|
||||
},
|
||||
"imports": {
|
||||
"std/": "https://deno.land/std@0.217.0/",
|
||||
"lume/": "https://deno.land/x/lume@v2.1.0/"
|
||||
"lume/": "https://deno.land/x/lume@v3.0.2/",
|
||||
"lume/jsx-runtime": "https://deno.land/x/ssx@v0.1.9/jsx-runtime.ts"
|
||||
},
|
||||
"lint": {
|
||||
"plugins": [
|
||||
"https://deno.land/x/lume@v3.0.1/lint.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
import React, { ReactNode as Node } from "npm:react";
|
||||
|
||||
const empty: Node = <></>;
|
||||
|
||||
interface CubeProps {
|
||||
front?: Node;
|
||||
back?: Node;
|
||||
|
@ -105,12 +101,12 @@ const Cube = (props: CubeProps) => (
|
|||
|
||||
<div className="scene">
|
||||
<div className="cube">
|
||||
<div className="face front">{props.front || empty}</div>
|
||||
<div className="face back">{props.back || empty}</div>
|
||||
<div className="face left">{props.left || empty}</div>
|
||||
<div className="face right">{props.right || empty}</div>
|
||||
<div className="face top">{props.top || empty}</div>
|
||||
<div className="face bottom">{props.bottom || empty}</div>
|
||||
<div className="face front">{props.front}</div>
|
||||
<div className="face back">{props.back}</div>
|
||||
<div className="face left">{props.left}</div>
|
||||
<div className="face right">{props.right}</div>
|
||||
<div className="face top">{props.top}</div>
|
||||
<div className="face bottom">{props.bottom}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,26 +5,27 @@ title: About
|
|||
|
||||
## Hi.
|
||||
|
||||
I'm yet another high schooler that is interested in programming.
|
||||
I'm from Türkiye 🇹🇷.
|
||||
I'm yet another high schooler that is interested in programming. I'm from
|
||||
Türkiye 🇹🇷.
|
||||
|
||||
I primarily use [Rust](https://rust-lang.org) and
|
||||
also know quite a bit of Python, [**Nix**](https://nixos.org/),
|
||||
[Nushell](https://nushell.sh/), a little bit of Java, Kotlin, Go,
|
||||
and JavaScript (No frameworks, though!).
|
||||
I primarily use [Rust](https://rust-lang.org) and also know quite a bit of
|
||||
Python, [**Nix**](https://nixos.org/), [Nushell](https://nushell.sh/), a little
|
||||
bit of Java, Kotlin, Go, and JavaScript (No frameworks, though!).
|
||||
|
||||
I created this site using [Lume](https://lume.land/). It is served
|
||||
by Nginx on my small VPS that runs [NixOS](https://nixos.org/).
|
||||
I created this site using [Lume](https://lume.land/). It is served by Nginx on
|
||||
my small VPS that runs [NixOS](https://nixos.org/).
|
||||
|
||||
I also host other services like Synapse (Matrix homeserver), Forgejo,
|
||||
Nextcloud and Grafana on the VPS, which are all configured using Nix.
|
||||
I also host other services like Synapse (Matrix homeserver), Forgejo, Nextcloud
|
||||
and Grafana on the VPS, which are all configured using Nix.
|
||||
|
||||
Historically, this blog was made using Rust, [Axum](https://lib.rs/crates/axum),
|
||||
[Maud](https://maud.lambda.xyz/) and a bunch of other neat crates (some which
|
||||
I created, like [embd-rs](https://github.com/RGBCube/embd-rs), which sped up
|
||||
development). But I decided to abandon this strategy as I was reinventing too much
|
||||
for just a simple static website. Development was also *really* slow on a i5 from
|
||||
2015 so I decided to ditch it and use Lume.
|
||||
[Maud](https://maud.lambda.xyz/) and a bunch of other neat crates (some which I
|
||||
created, like [embd-rs](https://github.com/RGBCube/embd-rs), which sped up
|
||||
development). But I decided to abandon this strategy as I was reinventing too
|
||||
much for just a simple static website. Development was also _really_ slow on a
|
||||
i5 from 2015 so I decided to ditch it and use Lume.
|
||||
|
||||
Here is the up to date [GitHub repository for said site](https://github.com/RGBCube/Site),
|
||||
and here is the [historical version written in Rust](https://github.com/RGBCube/Site/tree/rust-legacy).
|
||||
Here is the up to date
|
||||
[GitHub repository for said site](https://github.com/RGBCube/Site), and here is
|
||||
the
|
||||
[historical version written in Rust](https://github.com/RGBCube/Site/tree/rust-legacy).
|
||||
|
|
|
@ -156,7 +156,7 @@ const handleMove = (event: MouseEvent) => {
|
|||
|
||||
const newMouse = new Vec3(event.clientX, event.clientY, 0);
|
||||
|
||||
const timeDelta = (window.performance.now() - mouse.lastMove) / 1000;
|
||||
const timeDelta = (globalThis.performance.now() - mouse.lastMove) / 1000;
|
||||
|
||||
if (timeDelta > 0.1) {
|
||||
// This is a fresh scroll.
|
||||
|
@ -166,7 +166,7 @@ const handleMove = (event: MouseEvent) => {
|
|||
const delta = Vec3.sub(newMouse, mouse.previous);
|
||||
|
||||
mouse.previous = newMouse;
|
||||
mouse.lastMove = window.performance.now();
|
||||
mouse.lastMove = globalThis.performance.now();
|
||||
|
||||
const axis = new Vec3(-delta.y, delta.x, 0)
|
||||
.normalize()
|
||||
|
@ -221,7 +221,7 @@ const updateFrame = (timestamp: number) => {
|
|||
velocity.z = 0;
|
||||
}
|
||||
|
||||
if (window.performance.now() - mouse.lastMove > 10000) {
|
||||
if (globalThis.performance.now() - mouse.lastMove > 10000) {
|
||||
const impulse = new Vec3(0.7, 0.7, -0.7);
|
||||
velocity = Vec3.sum(impulse.scale(effectiveDelta * 3), velocity);
|
||||
}
|
||||
|
|
|
@ -9,17 +9,18 @@ tags:
|
|||
- unix-timestamps
|
||||
---
|
||||
|
||||
So, every day I wake up at 6:55, get dressed by 7, walk to the bus stop
|
||||
by 7:13 and board the bus around 7:17. Today was different.
|
||||
So, every day I wake up at 6:55, get dressed by 7, walk to the bus stop by 7:13
|
||||
and board the bus around 7:17. Today was different.
|
||||
|
||||
My alarm that I have set for 6:55 rang at 7:12 and as a result, I missed the bus.
|
||||
My alarm that I have set for 6:55 rang at 7:12 and as a result, I missed the
|
||||
bus.
|
||||
|
||||
> No, I didn't sleep in. There was no note in the UI saying this was a repeat alarm,
|
||||
> which there is if you snooze it or let it expire.
|
||||
> No, I didn't sleep in. There was no note in the UI saying this was a repeat
|
||||
> alarm, which there is if you snooze it or let it expire.
|
||||
|
||||
Surely something was happening. Machines don't break whenever they want, they're
|
||||
mostly deterministic. And I doubt Samsung engineers wrote code to delay the alarm
|
||||
by 12 minutes on the date after April 1st.
|
||||
mostly deterministic. And I doubt Samsung engineers wrote code to delay the
|
||||
alarm by 12 minutes on the date after April 1st.
|
||||
|
||||
So, _what_ was happening? I entered the Python repl to test out a theory:
|
||||
|
||||
|
@ -33,8 +34,8 @@ So, _what_ was happening? I entered the Python repl to test out a theory:
|
|||
The total time was off by about 1020 seconds. Give or take 60, as my phone
|
||||
doesn't display the seconds of the time.
|
||||
|
||||
> Since I'm using a Samsung SM-B310E, I assumed it uses seconds to store
|
||||
> the time. You can't even see seconds noted anywhere so I feel this is a normal
|
||||
> Since I'm using a Samsung SM-B310E, I assumed it uses seconds to store the
|
||||
> time. You can't even see seconds noted anywhere so I feel this is a normal
|
||||
> assumption. Even if it is false, the math still adds up for milliseconds.
|
||||
|
||||
Wow, I thought. That's really close to 1024 (which is 2 to the power of 10).
|
||||
|
@ -50,13 +51,15 @@ Maybe the 11th bit got flipped, making it increment 1024?
|
|||
-4
|
||||
```
|
||||
|
||||
Aha! So the 11th bit got flipped by something. And that something was probably
|
||||
a cosmic ray.
|
||||
Aha! So the 11th bit got flipped by something. And that something was probably a
|
||||
cosmic ray.
|
||||
|
||||
EDIT: It was not a cosmic ray. As pointed out by [@BenjaminRi's comment on lobste.rs](https://lobste.rs/s/jb1o6q/cosmic_drift#c_1ztluj)
|
||||
it was either a bug or storage corruption as the alarm ran late the next day. You should
|
||||
still create more than one alarm just in case if you are using a phone prone to this, however.
|
||||
EDIT: It was not a cosmic ray. As pointed out by
|
||||
[@BenjaminRi's comment on lobste.rs](https://lobste.rs/s/jb1o6q/cosmic_drift#c_1ztluj)
|
||||
it was either a bug or storage corruption as the alarm ran late the next day.
|
||||
You should still create more than one alarm just in case if you are using a
|
||||
phone prone to this, however.
|
||||
|
||||
My main takeaway from this event is to create more than one alarm, for extra redundancy.
|
||||
Who knew being prone to sleeping in could save you from your alarm getting
|
||||
shifted 12 minutes into the future :^).
|
||||
My main takeaway from this event is to create more than one alarm, for extra
|
||||
redundancy. Who knew being prone to sleeping in could save you from your alarm
|
||||
getting shifted 12 minutes into the future :^).
|
||||
|
|
|
@ -11,11 +11,11 @@ tags:
|
|||
- vcs
|
||||
---
|
||||
|
||||
You just started a new project. You ran `cargo init`,
|
||||
`poetry init` and `go mod init`.
|
||||
You just started a new project. You ran `cargo init`, `poetry init` and
|
||||
`go mod init`.
|
||||
|
||||
Those commands created the necessary files to work, it
|
||||
also added the following lines to your .gitignore:
|
||||
Those commands created the necessary files to work, it also added the following
|
||||
lines to your .gitignore:
|
||||
|
||||
```text
|
||||
target
|
||||
|
@ -23,27 +23,23 @@ __pycache__
|
|||
bin
|
||||
```
|
||||
|
||||
All great. You continue implementing features, and when
|
||||
the time comes, you publish your project to your Git
|
||||
hosting platform of choice.
|
||||
All great. You continue implementing features, and when the time comes, you
|
||||
publish your project to your Git hosting platform of choice.
|
||||
|
||||
People start to get interested in your project. One even
|
||||
decides that he's going to implement a new feature!
|
||||
Literally free work done for you!
|
||||
People start to get interested in your project. One even decides that he's going
|
||||
to implement a new feature! Literally free work done for you!
|
||||
|
||||
Alright. That person uses his code editor and tools bundled
|
||||
with his operating system to implement a very cool
|
||||
new feature. He then submits the merge request.
|
||||
Alright. That person uses his code editor and tools bundled with his operating
|
||||
system to implement a very cool new feature. He then submits the merge request.
|
||||
|
||||
You start reviewing the code and notice a file quite
|
||||
out of place: `.DS_Store`. You ask the person what
|
||||
it is, he says he has no clue.
|
||||
You start reviewing the code and notice a file quite out of place: `.DS_Store`.
|
||||
You ask the person what it is, he says he has no clue.
|
||||
|
||||

|
||||
|
||||
Whatever. You just delete the file from the branch and
|
||||
add the file's name to the repositories gitignore:
|
||||
Whatever. You just delete the file from the branch and add the file's name to
|
||||
the repositories gitignore:
|
||||
|
||||
```text
|
||||
target
|
||||
|
@ -52,15 +48,13 @@ bin
|
|||
.DS_Store
|
||||
```
|
||||
|
||||
Nice. Now the code is on master, and your repository only contains relevant
|
||||
information.
|
||||
|
||||
Nice. Now the code is on master, and your repository
|
||||
only contains relevant information.
|
||||
|
||||
Then, someone using an IDE created using web technologies
|
||||
submits another merge request. You look at it, and
|
||||
see that there is a whole directory that is irrelevant.
|
||||
You tell that person to delete the directory from the
|
||||
branch and add it to the gitignore. The gitignore lives on:
|
||||
Then, someone using an IDE created using web technologies submits another merge
|
||||
request. You look at it, and see that there is a whole directory that is
|
||||
irrelevant. You tell that person to delete the directory from the branch and add
|
||||
it to the gitignore. The gitignore lives on:
|
||||
|
||||
```text
|
||||
target
|
||||
|
@ -70,8 +64,8 @@ bin
|
|||
.vscode
|
||||
```
|
||||
|
||||
Then, someone that uses IntelliJ IDEA commits five hundred
|
||||
XML files and the `.idea` directory. You repeat this process:
|
||||
Then, someone that uses IntelliJ IDEA commits five hundred XML files and the
|
||||
`.idea` directory. You repeat this process:
|
||||
|
||||
```text
|
||||
target
|
||||
|
@ -82,27 +76,24 @@ bin
|
|||
.idea
|
||||
```
|
||||
|
||||
Years pass. Now your gitignore is hundreds of lines long,
|
||||
yet people keep accidentally committing in test scripts,
|
||||
foo, a, qux, data.tar.gz, start.sh, bin-release,
|
||||
cat, asd, fgsgskfh.
|
||||
Years pass. Now your gitignore is hundreds of lines long, yet people keep
|
||||
accidentally committing in test scripts, foo, a, qux, data.tar.gz, start.sh,
|
||||
bin-release, cat, asd, fgsgskfh.
|
||||
|
||||
Hell. You feel like a mythic god undergoing punishment
|
||||
for cheating death and deceiving the underworld.
|
||||
Hell. You feel like a mythic god undergoing punishment for cheating death and
|
||||
deceiving the underworld.
|
||||
|
||||

|
||||
|
||||
How do you escape this endless loop of ignoring files
|
||||
that sneak in? Maybe by educating every single merge
|
||||
request author? Nope, that definitely won't work, there
|
||||
should be a way to automatically handle this with tooling,
|
||||
rather than subjective human communication.
|
||||
How do you escape this endless loop of ignoring files that sneak in? Maybe by
|
||||
educating every single merge request author? Nope, that definitely won't work,
|
||||
there should be a way to automatically handle this with tooling, rather than
|
||||
subjective human communication.
|
||||
|
||||
Luckily, you realize that you can turn the blacklist
|
||||
of files (the gitignore) to a whitelist, by just
|
||||
ignoring everything and manually un-ignoring desired
|
||||
files. You change your gitignore to this:
|
||||
Luckily, you realize that you can turn the blacklist of files (the gitignore) to
|
||||
a whitelist, by just ignoring everything and manually un-ignoring desired files.
|
||||
You change your gitignore to this:
|
||||
|
||||
```text
|
||||
*
|
||||
|
@ -123,12 +114,10 @@ files. You change your gitignore to this:
|
|||
!docs/*.md
|
||||
```
|
||||
|
||||
Now, nobody can accidentally commit undesired files,
|
||||
as git automatically ignores them all and only
|
||||
allows the files that are explicitly whitelisted.
|
||||
It's also future proof, future proof until an IDE
|
||||
decides to use the `src/ide.rs` file as a convenient
|
||||
way of storing project specific configuration.
|
||||
And hopefully that future never comes.
|
||||
Now, nobody can accidentally commit undesired files, as git automatically
|
||||
ignores them all and only allows the files that are explicitly whitelisted. It's
|
||||
also future proof, future proof until an IDE decides to use the `src/ide.rs`
|
||||
file as a convenient way of storing project specific configuration. And
|
||||
hopefully that future never comes.
|
||||
|
||||
You feel relieved.
|
||||
|
|
|
@ -9,9 +9,9 @@ tags:
|
|||
- nix
|
||||
---
|
||||
|
||||
So, you may have seen the [HTMNIX](https://github.com/RGBCube/HTMNIX) project I've
|
||||
been working on the last few weeks. If not, no worries. Here is a Nix snippet
|
||||
that uses it:
|
||||
So, you may have seen the [HTMNIX](https://github.com/RGBCube/HTMNIX) project
|
||||
I've been working on the last few weeks. If not, no worries. Here is a Nix
|
||||
snippet that uses it:
|
||||
|
||||
```nix
|
||||
<html>
|
||||
|
@ -26,7 +26,8 @@ that uses it:
|
|||
<.html>
|
||||
```
|
||||
|
||||
> (hightlight.js shits the bed while highlighting this abomination - just ignore it)
|
||||
> (hightlight.js shits the bed while highlighting this abomination - just ignore
|
||||
> it)
|
||||
|
||||
You are probably thinking furiously right now, maybe you've noticed something:
|
||||
|
||||
|
@ -36,11 +37,13 @@ You are probably thinking furiously right now, maybe you've noticed something:
|
|||
> import <nixpkgs> {}
|
||||
> ```
|
||||
>
|
||||
> That means you have to add hundreds of elements to your Nix Path to make this work?
|
||||
> That means you have to add hundreds of elements to your Nix Path to make this
|
||||
> work?
|
||||
|
||||
You are somewhat correct. But not quite.
|
||||
|
||||
Nix `<foo>` expressions actually boil down to a call of the builtin `__findFile`, like so:
|
||||
Nix `<foo>` expressions actually boil down to a call of the builtin
|
||||
`__findFile`, like so:
|
||||
|
||||
```shell
|
||||
❯ nix-instantiate --parse --expr "<foo>"
|
||||
|
@ -48,11 +51,13 @@ Nix `<foo>` expressions actually boil down to a call of the builtin `__findFile`
|
|||
(__findFile __nixPath "foo")
|
||||
```
|
||||
|
||||
> In case you didn't know, [`nix-instantiate`](https://nixos.org/manual/nix/stable/command-ref/nix-instantiate.html)
|
||||
> is a nice tool to see what your Nix code is desugared and un-precedence'd into.
|
||||
> In case you didn't know,
|
||||
> [`nix-instantiate`](https://nixos.org/manual/nix/stable/command-ref/nix-instantiate.html)
|
||||
> is a nice tool to see what your Nix code is desugared and un-precedence'd
|
||||
> into.
|
||||
|
||||
Aha! So this means we can override the builtin `__findFile` and put whatever we would like in
|
||||
its place. So this will work:
|
||||
Aha! So this means we can override the builtin `__findFile` and put whatever we
|
||||
would like in its place. So this will work:
|
||||
|
||||
```nix
|
||||
let
|
||||
|
@ -63,14 +68,16 @@ in
|
|||
<foo>
|
||||
```
|
||||
|
||||
Evaluating this (by running `nix eval -f test.nix`), we get `{ content = "<foo>"; }`
|
||||
Evaluating this (by running `nix eval -f test.nix`), we get
|
||||
`{ content = "<foo>"; }`
|
||||
|
||||
So, then. How do we make it work for multiple tags, all coming after one another
|
||||
(and attribute sets, strings, etc.)?
|
||||
|
||||
Another hack! We need to set the [magic `__functor` attribute](https://noogle.dev/md/tutorials/functors)
|
||||
of the attrset we return, so we can call our set and have it store the tags inside it (while also
|
||||
preserving its callability!).
|
||||
Another hack! We need to set the
|
||||
[magic `__functor` attribute](https://noogle.dev/md/tutorials/functors) of the
|
||||
attrset we return, so we can call our set and have it store the tags inside it
|
||||
(while also preserving its callability!).
|
||||
|
||||
We can do that like so:
|
||||
|
||||
|
@ -88,9 +95,11 @@ in
|
|||
"baz"
|
||||
```
|
||||
|
||||
Great news! When we evaluate this, we get `{ __functor = <LAMBDA>; content = "<foo>barbaz"; }`.
|
||||
Great news! When we evaluate this, we get
|
||||
`{ __functor = <LAMBDA>; content = "<foo>barbaz"; }`.
|
||||
|
||||
We can also add a case to check if the next element is a tag, and use its content if it is:
|
||||
We can also add a case to check if the next element is a tag, and use its
|
||||
content if it is:
|
||||
|
||||
```nix
|
||||
let
|
||||
|
@ -107,8 +116,9 @@ in
|
|||
<endfoo>
|
||||
```
|
||||
|
||||
Enter another hack! We can utilize the `outPath` property that exists on derivations
|
||||
and gets returned whenever you call `toString` with an attrset that has the property to make our code a little simpler:
|
||||
Enter another hack! We can utilize the `outPath` property that exists on
|
||||
derivations and gets returned whenever you call `toString` with an attrset that
|
||||
has the property to make our code a little simpler:
|
||||
|
||||
```nix
|
||||
let
|
||||
|
@ -128,15 +138,17 @@ in
|
|||
|
||||
We also got support for other types for free, as well!
|
||||
|
||||
These are all the hidden builtins that [HTMNIX](https://github.com/RGBCube/HTMNIX) depends on
|
||||
and extends upon, making HTML in Nix an actually usable reality. It also
|
||||
has extra logic like turning attribute sets into HTML tags, which is fairly trivial
|
||||
compared to actaully discovering these hidden builtins in the first place.
|
||||
These are all the hidden builtins that
|
||||
[HTMNIX](https://github.com/RGBCube/HTMNIX) depends on and extends upon, making
|
||||
HTML in Nix an actually usable reality. It also has extra logic like turning
|
||||
attribute sets into HTML tags, which is fairly trivial compared to actaully
|
||||
discovering these hidden builtins in the first place.
|
||||
|
||||
You can read more about it in the project's README and
|
||||
see [an example site using it](https://github.com/RGBCube/NixSite).
|
||||
You can read more about it in the project's README and see
|
||||
[an example site using it](https://github.com/RGBCube/NixSite).
|
||||
|
||||
I might even try to port this site to HTMNIX to ensure it is usable with more complex setups :-)
|
||||
I might even try to port this site to HTMNIX to ensure it is usable with more
|
||||
complex setups :-)
|
||||
|
||||
Soon, maybe...
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@ tags:
|
|||
- nix
|
||||
---
|
||||
|
||||
I was surfing the web a few weeks ago, and I came across
|
||||
this iceberg chart:
|
||||
I was surfing the web a few weeks ago, and I came across this iceberg chart:
|
||||
|
||||

|
||||
|
||||
|
@ -18,8 +17,8 @@ this iceberg chart:
|
|||
created by @leftpaddotpy, @puckipedia,
|
||||
@wiggles and @qyriad on cohost.](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg)
|
||||
|
||||
In this post, I'll be explaining every item in this
|
||||
iceberg with sufficient depth. Let's start:
|
||||
In this post, I'll be explaining every item in this iceberg with sufficient
|
||||
depth. Let's start:
|
||||
|
||||
# Tier 1: I use NixOS (BTW)
|
||||
|
||||
|
@ -27,8 +26,7 @@ iceberg with sufficient depth. Let's start:
|
|||
|
||||
> IFD stands for import-from-derivation.
|
||||
|
||||
IFD is when you import a Nix expression
|
||||
from a derivation in the Nix store.
|
||||
IFD is when you import a Nix expression from a derivation in the Nix store.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -49,19 +47,19 @@ This will evaluate to `"b"`.
|
|||
So, what are we doing in this snippet?
|
||||
|
||||
1. Importing `<nixpkgs>` and getting the packages out of it.
|
||||
2. Creating a derivation that runs an echo command, which
|
||||
writes a Nix expression to the output file.
|
||||
3. Then we import the expression, forcing the derivation to
|
||||
be realized as we accessed the contents of it.
|
||||
2. Creating a derivation that runs an echo command, which writes a Nix
|
||||
expression to the output file.
|
||||
3. Then we import the expression, forcing the derivation to be realized as we
|
||||
accessed the contents of it.
|
||||
|
||||
> Wait, what does _realization_ mean?
|
||||
|
||||
It means to actually build a `.drv` file, using the builder,
|
||||
arguments and inputs described in it.
|
||||
It means to actually build a `.drv` file, using the builder, arguments and
|
||||
inputs described in it.
|
||||
|
||||
Nix does not realize derivations until you access the
|
||||
contents of them or force them to be evaluated using the `:b`
|
||||
command in the Nix REPL, see these two examples:
|
||||
Nix does not realize derivations until you access the contents of them or force
|
||||
them to be evaluated using the `:b` command in the Nix REPL, see these two
|
||||
examples:
|
||||
|
||||
```nix
|
||||
nix-repl> pkgs = import <nixpkgs> {}
|
||||
|
@ -71,8 +69,8 @@ nix-repl> pkgs.runCommand "foo" {} "echo 'bar' > $out"
|
|||
```
|
||||
|
||||
Here, it did create a `.drv` file. But that's it. There is no
|
||||
`/nix/store/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-foo` with contents
|
||||
`bar` to be seen.
|
||||
`/nix/store/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-foo` with contents `bar` to be
|
||||
seen.
|
||||
|
||||
```nix
|
||||
nix-repl> :b pkgs.runCommand "foo" {} "echo 'bar' > $out"
|
||||
|
@ -87,46 +85,44 @@ Where were we again? Right, the 3rd point:
|
|||
`Then we import the expression, forcing the derivation to
|
||||
be realized as we accessed the contents of it.`
|
||||
|
||||
The 3rd point is the important part. A typical Nix expression does
|
||||
not depend on the output contents of any derivation, which in turn
|
||||
makes evaluating a Nix expression not require realizing _any_ derivations.
|
||||
The 3rd point is the important part. A typical Nix expression does not depend on
|
||||
the output contents of any derivation, which in turn makes evaluating a Nix
|
||||
expression not require realizing _any_ derivations.
|
||||
|
||||
But with IFD, you have to realize a derivation to even finish the
|
||||
evaluation of your Nix expression. This will block Nix evaluation
|
||||
for a long time, as Nix is evaluated on a single thread and
|
||||
realizing the derivation needed takes a non-trivial amount of time.
|
||||
But with IFD, you have to realize a derivation to even finish the evaluation of
|
||||
your Nix expression. This will block Nix evaluation for a long time, as Nix is
|
||||
evaluated on a single thread and realizing the derivation needed takes a
|
||||
non-trivial amount of time.
|
||||
|
||||
TL;DR: IFD blocks evaluation because:
|
||||
|
||||
1. Evaluation is single threaded, so naturally everything blocks it.
|
||||
2. You're trying to access a derivation _output_, so obviously
|
||||
you need to realize (build) it first.
|
||||
2. You're trying to access a derivation _output_, so obviously you need to
|
||||
realize (build) it first.
|
||||
|
||||
## `nix-shell` and `nix shell` are completely different
|
||||
|
||||
`nix-shell` is the legacy version of `nix develop`, which
|
||||
enters a devshell created by a Nix expression. It was (and
|
||||
still is) very useful.
|
||||
`nix-shell` is the legacy version of `nix develop`, which enters a devshell
|
||||
created by a Nix expression. It was (and still is) very useful.
|
||||
|
||||
People then realized getting a devshell by passing in the packages
|
||||
you wanted as command line arguments was really convenient,
|
||||
which resulted in the creation of the `--packages/-p` argument for `nix-shell`
|
||||
People then realized getting a devshell by passing in the packages you wanted as
|
||||
command line arguments was really convenient, which resulted in the creation of
|
||||
the `--packages/-p` argument for `nix-shell`
|
||||
|
||||
`nix-shell -p` is similar to `nix shell`. But they are not the same.
|
||||
|
||||
`nix-shell -p` creates a shell using the stdenv by calling `pkgs.mkShell`,
|
||||
which includes all packages in the nixpkgs stdenv plus the ones you specified.
|
||||
`nix-shell -p` creates a shell using the stdenv by calling `pkgs.mkShell`, which
|
||||
includes all packages in the nixpkgs stdenv plus the ones you specified.
|
||||
|
||||
`nix shell` only appends the packages you passed in to the `PATH` environment
|
||||
variable. It is much lighter, as a natural result of not using the stdenv.
|
||||
It also isn't a questionable templated Nix expression and is implemented in
|
||||
the Nix CLI natively.
|
||||
variable. It is much lighter, as a natural result of not using the stdenv. It
|
||||
also isn't a questionable templated Nix expression and is implemented in the Nix
|
||||
CLI natively.
|
||||
|
||||
## Hydra is 17,000 lines of Perl
|
||||
|
||||
As the title says, [Hydra](http://github.com/NixOS/hydra),
|
||||
the Nix-based continuous build system is almost 17,000
|
||||
lines of Perl.
|
||||
As the title says, [Hydra](http://github.com/NixOS/hydra), the Nix-based
|
||||
continuous build system is almost 17,000 lines of Perl.
|
||||
|
||||
Here is the `tokei` output for its GitHub repository:
|
||||
|
||||
|
@ -157,19 +153,19 @@ Here is the `tokei` output for its GitHub repository:
|
|||
|
||||
From <https://nixos.org/guides/nix-pills/>:
|
||||
|
||||
> This is a ported version of the Nix Pills, a series of blog posts written
|
||||
> by Luca Bruno (aka Lethalman) and originally published in 2014 and 2015.
|
||||
> It provides a tutorial introduction into the Nix package manager and Nixpkgs
|
||||
> This is a ported version of the Nix Pills, a series of blog posts written by
|
||||
> Luca Bruno (aka Lethalman) and originally published in 2014 and 2015. It
|
||||
> provides a tutorial introduction into the Nix package manager and Nixpkgs
|
||||
> package collection, in the form of short chapters called 'pills'.
|
||||
>
|
||||
> Since the Nix Pills are considered a classic introduction to Nix, an effort
|
||||
> to port them to the current format was led by Graham Christensen (aka grahamc
|
||||
> / gchristensen) and other contributors in 2017.
|
||||
> Since the Nix Pills are considered a classic introduction to Nix, an effort to
|
||||
> port them to the current format was led by Graham Christensen (aka grahamc /
|
||||
> gchristensen) and other contributors in 2017.
|
||||
|
||||
## `inherit`
|
||||
|
||||
`inherit` is a keyword in the Nix language that brings a variable
|
||||
into an attribute set. It can also be used in `let in`s.
|
||||
`inherit` is a keyword in the Nix language that brings a variable into an
|
||||
attribute set. It can also be used in `let in`s.
|
||||
|
||||
Check out the
|
||||
[Nix reference page](https://nixos.org/manual/nix/stable/language/constructs.html#inheriting-attributes)
|
||||
|
@ -182,35 +178,34 @@ browse dependency graphs of derivations. Made in Haskell, of course.
|
|||
|
||||
## `nix-diff`
|
||||
|
||||
[`nix-diff`](https://github.com/Gabriella439/nix-diff) is a tool to see how
|
||||
two derivations differ with colored output. Again, in Haskell.
|
||||
[`nix-diff`](https://github.com/Gabriella439/nix-diff) is a tool to see how two
|
||||
derivations differ with colored output. Again, in Haskell.
|
||||
|
||||
## `nix-shell -p` gives you a compiler
|
||||
|
||||
As mentioned in the `nix-shell and nix shell are completely different`
|
||||
section, `nix-shell -p` is the nixpkgs stdenv plus your packages.
|
||||
As mentioned in the `nix-shell and nix shell are completely different` section,
|
||||
`nix-shell -p` is the nixpkgs stdenv plus your packages.
|
||||
|
||||
And since the stdenv includes a C compiler, so does the shell
|
||||
you enter after calling `nix-shell -p hello`.
|
||||
And since the stdenv includes a C compiler, so does the shell you enter after
|
||||
calling `nix-shell -p hello`.
|
||||
|
||||
## `nix-output-monitor`
|
||||
|
||||
[`nix-output-monitor`](https://github.com/maralorn/nix-output-monitor),
|
||||
also known as `NOM` is a neat visualizer for Nix builds.
|
||||
See it in action: <https://asciinema.org/a/604200>
|
||||
[`nix-output-monitor`](https://github.com/maralorn/nix-output-monitor), also
|
||||
known as `NOM` is a neat visualizer for Nix builds. See it in action:
|
||||
<https://asciinema.org/a/604200>
|
||||
|
||||
It is also programmed in Haskell. Whew.
|
||||
|
||||
## `nix-top`
|
||||
|
||||
[`nix-top`] is a simple Ruby script to help people
|
||||
see what is building in the local Nix daemon. to help people
|
||||
see what is building in the local Nix daemon.
|
||||
[`nix-top`] is a simple Ruby script to help people see what is building in the
|
||||
local Nix daemon. to help people see what is building in the local Nix daemon.
|
||||
|
||||
## `--debugger`
|
||||
|
||||
The `--debugger` flag is used to halt evaulation and
|
||||
enter the Nix REPL when evaluating a Nix file or expression.
|
||||
The `--debugger` flag is used to halt evaulation and enter the Nix REPL when
|
||||
evaluating a Nix file or expression.
|
||||
|
||||
You set breakpoints using the `builtins.break` function:
|
||||
|
||||
|
@ -229,34 +224,34 @@ in builtins.break {
|
|||
|
||||
> Evaulate this file with `nix eval --debugger --file <filename>` and see.
|
||||
|
||||
It is also _supposed_ to bring the variables in the scope `break`
|
||||
was called into the Nix REPL. However, this does not work. Keep on
|
||||
reading and you'll see why & what do to do bypass this bug!
|
||||
It is also _supposed_ to bring the variables in the scope `break` was called
|
||||
into the Nix REPL. However, this does not work. Keep on reading and you'll see
|
||||
why & what do to do bypass this bug!
|
||||
|
||||
## `tvix`
|
||||
|
||||
[Tvix](https://tvix.dev/) is an alternate implementation of Nix written in Rust.
|
||||
|
||||
It aims to have a modular implementation while also reusing already-written
|
||||
Nix crates in the Rust ecosystem so other people can reuse code instead of
|
||||
It aims to have a modular implementation while also reusing already-written Nix
|
||||
crates in the Rust ecosystem so other people can reuse code instead of
|
||||
reimplementing it! It is licensed under the GPLv3 license.
|
||||
|
||||
## Eelco's Thesis
|
||||
|
||||
Eelco's thesis is about The Purely Functional Software
|
||||
Deployment Model. Which also happens to be about Nix.
|
||||
Eelco's thesis is about The Purely Functional Software Deployment Model. Which
|
||||
also happens to be about Nix.
|
||||
|
||||
You can read the thesis [here](https://edolstra.github.io/pubs/phd-thesis.pdf).
|
||||
|
||||
## Fixed-Output derivations do not rebuild with a changed URL
|
||||
|
||||
Fixed output derivations (also called FODs) do not get rebuilt
|
||||
even if you change any inputs passed to them (a URL string is
|
||||
also an input). The reason for this is simple.
|
||||
Fixed output derivations (also called FODs) do not get rebuilt even if you
|
||||
change any inputs passed to them (a URL string is also an input). The reason for
|
||||
this is simple.
|
||||
|
||||
Nix will see that the output is the same, and since there already
|
||||
is a derivation with the same output in the Nix store, it will
|
||||
assume it is cached and will use that derivation.
|
||||
Nix will see that the output is the same, and since there already is a
|
||||
derivation with the same output in the Nix store, it will assume it is cached
|
||||
and will use that derivation.
|
||||
|
||||
# Tier 2: Package Maintainer
|
||||
|
||||
|
@ -271,14 +266,14 @@ following Nix CLI invokation:
|
|||
nix run github:me/hello-world
|
||||
```
|
||||
|
||||
This is great, you are able to run the binary. But, there is no way for a flake to
|
||||
accept any configuration arguments. If you wanted to run in debug mode, you have
|
||||
to create another output (like `packages.x86_64-linux.{release,debug}`).
|
||||
This is great, you are able to run the binary. But, there is no way for a flake
|
||||
to accept any configuration arguments. If you wanted to run in debug mode, you
|
||||
have to create another output (like `packages.x86_64-linux.{release,debug}`).
|
||||
Same for compiling without support for X/Y/Z. This results in two to the N power
|
||||
of outputs, where N is the feature toggle count.
|
||||
|
||||
A dumb flake input like `github:boolean-option/true` fixes this, even though
|
||||
it is an ugly hack. You can do this in your flake:
|
||||
A dumb flake input like `github:boolean-option/true` fixes this, even though it
|
||||
is an ugly hack. You can do this in your flake:
|
||||
|
||||
```nix
|
||||
{
|
||||
|
@ -301,22 +296,22 @@ And override the `debug-mode` input like so, to run a debug binary instead:
|
|||
nix run github:me/hello-world --override debug-mode github:boolean-option/true
|
||||
```
|
||||
|
||||
[`nix-systems`](https://github.com/nix-systems/nix-systems) is the same idea
|
||||
as `boolean-option`, but for systems instead.
|
||||
[`nix-systems`](https://github.com/nix-systems/nix-systems) is the same idea as
|
||||
`boolean-option`, but for systems instead.
|
||||
|
||||
[See some example usages here.](https://github.com/search?q=boolean-option+language%3ANix&type=code&l=Nix)
|
||||
|
||||
These hacks wouldn't be needed if Nix allowed users to put arbitrary values in
|
||||
inputs - [in fact, there is an open issue from _2021_ that is still being actively
|
||||
inputs -
|
||||
[in fact, there is an open issue from _2021_ that is still being actively
|
||||
discussed](https://github.com/NixOS/nix/issues/5663) - but here we are.
|
||||
|
||||
## `''foo''\n'' == "foo\n"`
|
||||
|
||||
The Nix parser is very buggy, and this is one bug.
|
||||
|
||||
`''` is the character set used to escape `${` in
|
||||
Nix indent strings (No, not multiline strings! All strings in Nix
|
||||
are multiline.):
|
||||
`''` is the character set used to escape `${` in Nix indent strings (No, not
|
||||
multiline strings! All strings in Nix are multiline.):
|
||||
|
||||
```nix
|
||||
''
|
||||
|
@ -328,20 +323,19 @@ This results in the literal string `"export BAR_OR_BAZ=${BAR:-BAZ}"`, without
|
|||
string interpolation.
|
||||
|
||||
Nix will ignore an invalid `\` escape after the `''` escape in an indent string.
|
||||
Or if it is a valid one, it will just append the `\` escape to
|
||||
the string, ignoring the `''` escape.
|
||||
Or if it is a valid one, it will just append the `\` escape to the string,
|
||||
ignoring the `''` escape.
|
||||
|
||||
## `(x: x x) (x: x x)`
|
||||
|
||||
This expression is a way to make Nix recurse forever
|
||||
and stack overflow. Nix can't detect it either, as the
|
||||
evaluated thunk is always different.
|
||||
This expression is a way to make Nix recurse forever and stack overflow. Nix
|
||||
can't detect it either, as the evaluated thunk is always different.
|
||||
|
||||
## Derivations are just memoized `execve`
|
||||
|
||||
Derivations include all required information to build themselves.
|
||||
This also includes output directories (except when they are content-addressed,
|
||||
but that is for a future blog post!). You can dump a `.drv` file as JSON with the
|
||||
Derivations include all required information to build themselves. This also
|
||||
includes output directories (except when they are content-addressed, but that is
|
||||
for a future blog post!). You can dump a `.drv` file as JSON with the
|
||||
`nix derivation show` command, like so:
|
||||
|
||||
<details>
|
||||
|
@ -442,12 +436,13 @@ but that is for a future blog post!). You can dump a `.drv` file as JSON with th
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## `nixos-rebuild --fast --target-host`
|
||||
|
||||
The `--fast` flag in `nixos-rebuild` is an alias to `--no-build-nix`
|
||||
which is explained in the man page like so:
|
||||
The `--fast` flag in `nixos-rebuild` is an alias to `--no-build-nix` which is
|
||||
explained in the man page like so:
|
||||
|
||||
> Normally, nixos-rebuild first builds the `nixUnstable` attribute in Nixpkgs,
|
||||
> and uses the resulting instance of the Nix package manager to build the new
|
||||
|
@ -457,29 +452,29 @@ which is explained in the man page like so:
|
|||
|
||||
And the `--target-host` flag is also documented (rare!), like so:
|
||||
|
||||
> Specifies the NixOS target host. By setting this to something other than
|
||||
> an empty string, the system activation will happen on the remote host
|
||||
> instead of the local machine. The remote host needs to be accessible over
|
||||
> ssh, and for the commands switch, boot and test you need root access.
|
||||
> Specifies the NixOS target host. By setting this to something other than an
|
||||
> empty string, the system activation will happen on the remote host instead of
|
||||
> the local machine. The remote host needs to be accessible over ssh, and for
|
||||
> the commands switch, boot and test you need root access.
|
||||
>
|
||||
> If `--build-host` is not explicitly specified or empty, building will take
|
||||
> place locally.
|
||||
>
|
||||
> You can include a remote user name in the host name (user@host). You can
|
||||
> also set ssh options by defining the `NIX_SSHOPTS` environment variable.
|
||||
> You can include a remote user name in the host name (user@host). You can also
|
||||
> set ssh options by defining the `NIX_SSHOPTS` environment variable.
|
||||
>
|
||||
> Note that nixos-rebuild honors the nixpkgs.crossSystem setting of the
|
||||
> given configuration but disregards the true architecture of the target
|
||||
> host. Hence the nixpkgs.crossSystem setting has to match the target platform
|
||||
> or else activation will fail.
|
||||
> Note that nixos-rebuild honors the nixpkgs.crossSystem setting of the given
|
||||
> configuration but disregards the true architecture of the target host. Hence
|
||||
> the nixpkgs.crossSystem setting has to match the target platform or else
|
||||
> activation will fail.
|
||||
|
||||
## Nix supports floats
|
||||
|
||||
Yup, you heard it. Nix has floats, too!
|
||||
|
||||
Though, note that not every number in Nix is a float.
|
||||
Integers in Nix are stored as 64-bit integers. Floats are also
|
||||
64-bit. [Here's the Nix source code that denotes this](https://github.com/NixOS/nix/blob/d2a07a96ba6275e570b7d84092d08cbe85a2091b/src/libexpr/value.hh#L77-L78)
|
||||
Though, note that not every number in Nix is a float. Integers in Nix are stored
|
||||
as 64-bit integers. Floats are also 64-bit.
|
||||
[Here's the Nix source code that denotes this](https://github.com/NixOS/nix/blob/d2a07a96ba6275e570b7d84092d08cbe85a2091b/src/libexpr/value.hh#L77-L78)
|
||||
|
||||
```nix
|
||||
nix-repl> 0.1 + 0.2
|
||||
|
@ -494,8 +489,7 @@ true
|
|||
|
||||
## `attrset ? key` and `attrset ? "key"`
|
||||
|
||||
This syntax is a way to check for the existence of a key
|
||||
in an attribute set.
|
||||
This syntax is a way to check for the existence of a key in an attribute set.
|
||||
|
||||
`{ foo = 42; } ? foo` evaulates to `true`. The same applies for
|
||||
`{ foo = 42; } ? "foo"`, which is just using a string identifier instead.
|
||||
|
@ -512,31 +506,31 @@ in an attribute set.
|
|||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3
|
||||
```
|
||||
|
||||
</h2>
|
||||
|
||||
_(taken verbatim from `man nix-shell`)_
|
||||
|
||||
You can use nix-shell as a script interpreter
|
||||
to allow scripts written in arbitrary languages
|
||||
to obtain their own dependencies via Nix. This
|
||||
is done by starting the script with the following lines:
|
||||
You can use nix-shell as a script interpreter to allow scripts written in
|
||||
arbitrary languages to obtain their own dependencies via Nix. This is done by
|
||||
starting the script with the following lines:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i real-interpreter --packages packages
|
||||
```
|
||||
|
||||
Where `real-interpreter` is the "real" script interpreter
|
||||
that will be invoked by nix-shell after it has obtained the
|
||||
dependencies and initialised the environment, and packages
|
||||
are the attribute names of the dependencies in `<nixpkgs>`.
|
||||
Where `real-interpreter` is the "real" script interpreter that will be invoked
|
||||
by nix-shell after it has obtained the dependencies and initialised the
|
||||
environment, and packages are the attribute names of the dependencies in
|
||||
`<nixpkgs>`.
|
||||
|
||||
The lines starting with `#!nix-shell` specify nix-shell options
|
||||
(see above). Note that you cannot write `#!/usr/bin/env nix-shell -i ...`
|
||||
because many operating systems only allow one argument in `#!` lines.
|
||||
The lines starting with `#!nix-shell` specify nix-shell options (see above).
|
||||
Note that you cannot write `#!/usr/bin/env nix-shell -i ...` because many
|
||||
operating systems only allow one argument in `#!` lines.
|
||||
|
||||
For example, here is a Python script that
|
||||
depends on Python and the prettytable package:
|
||||
For example, here is a Python script that depends on Python and the prettytable
|
||||
package:
|
||||
|
||||
```python
|
||||
#!/usr/bin/env nix-shell
|
||||
|
@ -556,12 +550,11 @@ TODO
|
|||
|
||||
## Zilch
|
||||
|
||||
ZilchOS is a decidedly tiny Nix-based distro. It is a great project
|
||||
to see how NixOS actually works behind the scenes without too much
|
||||
noise to distract.
|
||||
ZilchOS is a decidedly tiny Nix-based distro. It is a great project to see how
|
||||
NixOS actually works behind the scenes without too much noise to distract.
|
||||
|
||||
It was created by [t184256](https://github.com/t184256) on GitHub,
|
||||
here is the [ZilchOS GitHub organization](https://github.com/ZilchOS).
|
||||
It was created by [t184256](https://github.com/t184256) on GitHub, here is the
|
||||
[ZilchOS GitHub organization](https://github.com/ZilchOS).
|
||||
|
||||
## `set.a or "meow"` is set-specific
|
||||
|
||||
|
@ -571,8 +564,8 @@ TODO
|
|||
|
||||
I find it weird that this is in the 3rd tier. It's actually pretty simple:
|
||||
|
||||
Nix converts `true` to `"1"` and `false` to `"" (empty string)` when
|
||||
asked to convert a boolean to a string.
|
||||
Nix converts `true` to `"1"` and `false` to `"" (empty string)` when asked to
|
||||
convert a boolean to a string.
|
||||
|
||||
And when you convert a list to a string, it converts individual items and then
|
||||
joins them with a space character (0xA).
|
||||
|
@ -581,10 +574,9 @@ So `builtins.toString [true false true]` makes `1 1`
|
|||
|
||||
## `__structuredAttrs`
|
||||
|
||||
`__structuredAttrs`, when set to `true` in a derivation argument,
|
||||
will set the `NIX_ATTRS_JSON_FILE` and `NIX_ATTRS_SH_FILE` file
|
||||
paths to that arguments contents serialized in the respective
|
||||
format.
|
||||
`__structuredAttrs`, when set to `true` in a derivation argument, will set the
|
||||
`NIX_ATTRS_JSON_FILE` and `NIX_ATTRS_SH_FILE` file paths to that arguments
|
||||
contents serialized in the respective format.
|
||||
|
||||
Here is an example:
|
||||
|
||||
|
@ -643,14 +635,14 @@ get something similar to this:
|
|||
"system": "x86_64-linux"
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## `__functor`
|
||||
|
||||
`__functor` is a magic attribute you can add on a set to make it
|
||||
callable. The lambda you assign to it must "accept 2 arguments".
|
||||
The first being itself (commonly named "self") and the second
|
||||
being the argument that was passed in.
|
||||
`__functor` is a magic attribute you can add on a set to make it callable. The
|
||||
lambda you assign to it must "accept 2 arguments". The first being itself
|
||||
(commonly named "self") and the second being the argument that was passed in.
|
||||
|
||||
Here's an example:
|
||||
|
||||
|
@ -677,17 +669,17 @@ This outputs the following:
|
|||
|
||||
(later renamed to `--output-format`)
|
||||
|
||||
You know how the new `nix-command` CLI has that bar at the bottom,
|
||||
which looks like `[4/0/804 built, 7.7/112.5 MiB DL] downloading '...'`?
|
||||
You know how the new `nix-command` CLI has that bar at the bottom, which looks
|
||||
like `[4/0/804 built, 7.7/112.5 MiB DL] downloading '...'`?
|
||||
|
||||
This option allows you to have that output format in the old CLI by
|
||||
passing in `--log-format bar-with-logs`.
|
||||
This option allows you to have that output format in the old CLI by passing in
|
||||
`--log-format bar-with-logs`.
|
||||
|
||||
## `traceVerbose`
|
||||
|
||||
`builtins.traceVerbose` behaves like `builtins.trace` when you pass
|
||||
`--trace-verbose` to the Nix CLI. If you don't pass in that option,
|
||||
it completely ignores the first argument and returns the second one.
|
||||
`--trace-verbose` to the Nix CLI. If you don't pass in that option, it
|
||||
completely ignores the first argument and returns the second one.
|
||||
|
||||
# Tier 4: Nix is Easy We Promise
|
||||
|
||||
|
@ -695,13 +687,12 @@ it completely ignores the first argument and returns the second one.
|
|||
|
||||
This evaluates to `[ false true ]`. Why?
|
||||
|
||||
Normally, Functions in Nix cannot be compared. Comparing
|
||||
two functions will _always_ return false, at least when done
|
||||
directly.
|
||||
Normally, Functions in Nix cannot be compared. Comparing two functions will
|
||||
_always_ return false, at least when done directly.
|
||||
|
||||
But if two attribute sets that are compared have the same address,
|
||||
Nix ignores this and does a pointer comparision, totally ignoring
|
||||
all members. This is a hack.
|
||||
But if two attribute sets that are compared have the same address, Nix ignores
|
||||
this and does a pointer comparision, totally ignoring all members. This is a
|
||||
hack.
|
||||
|
||||
[Link to code that does this.](https://github.com/NixOS/nix/blob/aa165301d1ae3b306319a6a834dc1d4e340a7112/src/libexpr/eval.cc#L2525-L2528)
|
||||
Here's the snippet:
|
||||
|
@ -718,74 +709,77 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
|
|||
if (&v1 == &v2) return true;
|
||||
```
|
||||
|
||||
This "temporary hack" was commited in 14 years ago. You can do whatever
|
||||
you want with this information.
|
||||
This "temporary hack" was commited in 14 years ago. You can do whatever you want
|
||||
with this information.
|
||||
|
||||
## Nix Plugins
|
||||
|
||||
As suprising as it sounds, Nix does indeed supports plugins. You can load plugins
|
||||
using the [`plugin-files`](https://nix.dev/manual/nix/2.22/command-ref/conf-file#conf-plugin-files)
|
||||
As suprising as it sounds, Nix does indeed supports plugins. You can load
|
||||
plugins using the
|
||||
[`plugin-files`](https://nix.dev/manual/nix/2.22/command-ref/conf-file#conf-plugin-files)
|
||||
configuration option.
|
||||
|
||||
From the configuration reference:
|
||||
|
||||
> A list of plugin files to be loaded by Nix. Each of these files will be dlopened by
|
||||
> Nix. If they contain the symbol nix_plugin_entry(), this symbol will be called.
|
||||
> Alternatively, they can affect execution through static initialization. In particular,
|
||||
> these plugins may construct static instances of RegisterPrimOp to add new primops
|
||||
> or constants to the expression language, RegisterStoreImplementation to add new
|
||||
> store implementations, RegisterCommand to add new subcommands to the nix command,
|
||||
> and RegisterSetting to add new nix config settings. See the constructors for those
|
||||
> types for more details.
|
||||
>
|
||||
> Warning! These APIs are inherently unstable and may change from release to release.
|
||||
>
|
||||
> Since these files are loaded into the same address space as Nix itself, they must
|
||||
> be DSOs compatible with the instance of Nix running at the time (i.e. compiled
|
||||
> against the same headers, not linked to any incompatible libraries). They should
|
||||
> not be linked to any Nix libs directly, as those will be available already at load time.
|
||||
>
|
||||
> A list of plugin files to be loaded by Nix. Each of these files will be
|
||||
> dlopened by Nix. If they contain the symbol nix_plugin_entry(), this symbol
|
||||
> will be called. Alternatively, they can affect execution through static
|
||||
> initialization. In particular, these plugins may construct static instances of
|
||||
> RegisterPrimOp to add new primops or constants to the expression language,
|
||||
> RegisterStoreImplementation to add new store implementations, RegisterCommand
|
||||
> to add new subcommands to the nix command, and RegisterSetting to add new nix
|
||||
> config settings. See the constructors for those types for more details.
|
||||
>
|
||||
> Warning! These APIs are inherently unstable and may change from release to
|
||||
> release.
|
||||
>
|
||||
> Since these files are loaded into the same address space as Nix itself, they
|
||||
> must be DSOs compatible with the instance of Nix running at the time (i.e.
|
||||
> compiled against the same headers, not linked to any incompatible libraries).
|
||||
> They should not be linked to any Nix libs directly, as those will be available
|
||||
> already at load time.
|
||||
>
|
||||
> If an entry in the list is a directory, all files in the directory are loaded
|
||||
> as plugins (non-recursively).
|
||||
|
||||
Some example plugins are [`nix-doc`](https://github.com/lf-/nix-doc)
|
||||
and [`nix-extra-builtins`](https://github.com/shlevy/nix-plugins).
|
||||
Some example plugins are [`nix-doc`](https://github.com/lf-/nix-doc) and
|
||||
[`nix-extra-builtins`](https://github.com/shlevy/nix-plugins).
|
||||
|
||||
## `/bin/sh` and sandbox impurity
|
||||
|
||||
By setting the [`sandbox-paths`](https://nix.dev/manual/nix/2.22/command-ref/conf-file#conf-sandbox-paths)
|
||||
option to `/bin/sh=/bin/sh`, Nix will bind the `/bin/sh` path in the
|
||||
build sandbox (left) to the `/bin/sh` path in the host (right).
|
||||
This is of course impure, but is useful for bootstrapping from
|
||||
absolute scratch without copying impure binaries to the Nix store.
|
||||
By setting the
|
||||
[`sandbox-paths`](https://nix.dev/manual/nix/2.22/command-ref/conf-file#conf-sandbox-paths)
|
||||
option to `/bin/sh=/bin/sh`, Nix will bind the `/bin/sh` path in the build
|
||||
sandbox (left) to the `/bin/sh` path in the host (right). This is of course
|
||||
impure, but is useful for bootstrapping from absolute scratch without copying
|
||||
impure binaries to the Nix store.
|
||||
|
||||
## `rec { a = 5; b = a + 1; __overrides.a = 6; }`
|
||||
|
||||
There is a special field named `__overrides` in recursive attrset expressions,
|
||||
which simply overrides the parent attribute set with the keys inside it. This
|
||||
is different from the update operator (`//`) because that will not override the
|
||||
which simply overrides the parent attribute set with the keys inside it. This is
|
||||
different from the update operator (`//`) because that will not override the
|
||||
self-referneces in the recursive attribute set.
|
||||
|
||||
`rec { a = 5; b = a + 1; __overrides.a = 6; }.b` will evaluate to 7,
|
||||
while `(rec { a = 5; b = a + 1; } // { a = 6; }).b` will evaluate to 6.
|
||||
`rec { a = 5; b = a + 1; __overrides.a = 6; }.b` will evaluate to 7, while
|
||||
`(rec { a = 5; b = a + 1; } // { a = 6; }).b` will evaluate to 6.
|
||||
|
||||
## `let __div = c: map (__mul c); in 2 / [ 1 2 3 ]`
|
||||
|
||||
As mentioned in my [HTMNIX blog post](/blog/htmnix), Nix operators get
|
||||
desugared into normal function calls before execution. All operators
|
||||
have their "hidden" equivalents that they get desugared into (`__div` is for `/`, etc.),
|
||||
so you can override them using `let in`.
|
||||
As mentioned in my [HTMNIX blog post](/blog/htmnix), Nix operators get desugared
|
||||
into normal function calls before execution. All operators have their "hidden"
|
||||
equivalents that they get desugared into (`__div` is for `/`, etc.), so you can
|
||||
override them using `let in`.
|
||||
|
||||
`let __div = c: map (__mul c); in 2 / [ 1 2 3 ]` is equivalent to
|
||||
`map (x: 2 * x) [ 1 2 3 ]` which evaluates to `[ 2 4 6 ]`.
|
||||
|
||||
You can also check what a Nix snippet desugars into
|
||||
using `nix-instantiate --parse --expr 'expression here'`
|
||||
You can also check what a Nix snippet desugars into using
|
||||
`nix-instantiate --parse --expr 'expression here'`
|
||||
|
||||
## `let __lessThan = a: b: b - a; in 1 > 2`
|
||||
|
||||
As mentioned above, this expression will desugar into
|
||||
`let __lessThan = a: b: b - a; in __lessThan 1 2` which
|
||||
will evaluate to 1.
|
||||
`let __lessThan = a: b: b - a; in __lessThan 1 2` which will evaluate to 1.
|
||||
|
||||
## `__impure`
|
||||
|
|
|
@ -9,38 +9,39 @@ tags:
|
|||
- modal-editors
|
||||
---
|
||||
|
||||
If you have ever used a Turkish-Q keyboard in combination with a modal
|
||||
editor before, you might have noticed that the `i` key is pretty far off
|
||||
to the side:
|
||||
If you have ever used a Turkish-Q keyboard in combination with a modal editor
|
||||
before, you might have noticed that the `i` key is pretty far off to the side:
|
||||
|
||||

|
||||
|
||||
This blog post will guide you on how to swap the `ı` key with the `i` key
|
||||
(but not the `I` and `İ` keys). This will be a great change if you write primarily
|
||||
in English but need the Turkish symbols sometimes.
|
||||
This blog post will guide you on how to swap the `ı` key with the `i` key (but
|
||||
not the `I` and `İ` keys). This will be a great change if you write primarily in
|
||||
English but need the Turkish symbols sometimes.
|
||||
|
||||
> There is `tr(us)` in the `xkeyboard_config` package that does something similar to this:
|
||||
>
|
||||
> There is `tr(us)` in the `xkeyboard_config` package that does something
|
||||
> similar to this:
|
||||
>
|
||||
> ```cpp
|
||||
> // The basic Turkish layout with "i" and "ı" swapped.
|
||||
> // Originally by Ali Riza KESKIN <parduscix@yandex.ru>, 2021.
|
||||
> partial
|
||||
> xkb_symbols "us" {
|
||||
>
|
||||
>
|
||||
> include "tr(basic)"
|
||||
>
|
||||
>
|
||||
> name[Group1]="Turkish (i and ı swapped)";
|
||||
>
|
||||
>
|
||||
> key <AC11> { type[group1] = "FOUR_LEVEL_SEMIALPHABETIC",
|
||||
> [ i, I, paragraph, none ]};
|
||||
> key <AD08> { type[group1] = "FOUR_LEVEL_SEMIALPHABETIC",
|
||||
> [ idotless, Iabovedot, apostrophe, dead_caron ]};
|
||||
> };
|
||||
> ```
|
||||
>
|
||||
> However, this only swaps the uppercase letters, so the `i` key is unchanged but
|
||||
> the uppercase of that key is `I` like in English. However, this is usually not
|
||||
> desired as this still reduces your typing speed (as the `iI` key is too far).
|
||||
>
|
||||
> However, this only swaps the uppercase letters, so the `i` key is unchanged
|
||||
> but the uppercase of that key is `I` like in English. However, this is usually
|
||||
> not desired as this still reduces your typing speed (as the `iI` key is too
|
||||
> far).
|
||||
|
||||
Let's create our own layout that does something similar but swaps the lowercase
|
||||
letters instead. Here is the code for that:
|
||||
|
@ -60,8 +61,8 @@ xkb_symbols "basic" {
|
|||
```
|
||||
|
||||
The `default` key is needed because we are going to make this a standalone file.
|
||||
Save this to `~/.config/xkb/symbols/tr-swapped-i` and you can tell your WM/DE
|
||||
to use the `tr-swapped-i` XKB layout.
|
||||
Save this to `~/.config/xkb/symbols/tr-swapped-i` and you can tell your WM/DE to
|
||||
use the `tr-swapped-i` XKB layout.
|
||||
|
||||
In Hyprland (The WM I use) you can do it like this:
|
||||
|
||||
|
@ -72,14 +73,15 @@ input {
|
|||
}
|
||||
```
|
||||
|
||||
That should swap the `ı` and `i` keys on your WM/DE successfully. However, we are not done
|
||||
yet.
|
||||
That should swap the `ı` and `i` keys on your WM/DE successfully. However, we
|
||||
are not done yet.
|
||||
|
||||
The TTY (swap to TTY 2 by doing `CTRL-ALT-F2`) still doesn't use this layout, which is a problem.
|
||||
And it seems that the format the TTY uses is a little different.
|
||||
Looking at the `kbd` package, it uses a format called `.map`.
|
||||
The TTY (swap to TTY 2 by doing `CTRL-ALT-F2`) still doesn't use this layout,
|
||||
which is a problem. And it seems that the format the TTY uses is a little
|
||||
different. Looking at the `kbd` package, it uses a format called `.map`.
|
||||
|
||||
Here is a `.map` file that overrides the `trq` layout and swaps the `ı` and `i` keys:
|
||||
Here is a `.map` file that overrides the `trq` layout and swaps the `ı` and `i`
|
||||
keys:
|
||||
|
||||
```cpp
|
||||
include "/usr/share/keymaps/i386/qwerty/trq.map"
|
||||
|
@ -96,7 +98,8 @@ Save it to the directory where you store your maps.
|
|||
Note that the path `/usr/share/keymaps` might differ based on your distro. You
|
||||
can check what it is it by doing `man loadkeys` and scrolling to the bottom.
|
||||
|
||||
After that, consult your distro's docs on how to change the system keyboard locale.
|
||||
After that, consult your distro's docs on how to change the system keyboard
|
||||
locale.
|
||||
|
||||
This is how it is done on NixOS:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue