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

|
to gitignore .DS_Store](/assets/github-ds-store-mr-list.webp)
|
||||||
|
|
||||||
Whatever. You just delete the file from the branch and
|
Whatever. You just delete the file from the branch and add the file's name to
|
||||||
add the file's name to the repositories gitignore:
|
the repositories gitignore:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
target
|
target
|
||||||
|
@ -52,15 +48,13 @@ bin
|
||||||
.DS_Store
|
.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
|
Then, someone using an IDE created using web technologies submits another merge
|
||||||
only contains relevant information.
|
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
|
||||||
Then, someone using an IDE created using web technologies
|
it to the gitignore. The gitignore lives on:
|
||||||
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
|
```text
|
||||||
target
|
target
|
||||||
|
@ -70,8 +64,8 @@ bin
|
||||||
.vscode
|
.vscode
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, someone that uses IntelliJ IDEA commits five hundred
|
Then, someone that uses IntelliJ IDEA commits five hundred XML files and the
|
||||||
XML files and the `.idea` directory. You repeat this process:
|
`.idea` directory. You repeat this process:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
target
|
target
|
||||||
|
@ -82,27 +76,24 @@ bin
|
||||||
.idea
|
.idea
|
||||||
```
|
```
|
||||||
|
|
||||||
Years pass. Now your gitignore is hundreds of lines long,
|
Years pass. Now your gitignore is hundreds of lines long, yet people keep
|
||||||
yet people keep accidentally committing in test scripts,
|
accidentally committing in test scripts, foo, a, qux, data.tar.gz, start.sh,
|
||||||
foo, a, qux, data.tar.gz, start.sh, bin-release,
|
bin-release, cat, asd, fgsgskfh.
|
||||||
cat, asd, fgsgskfh.
|
|
||||||
|
|
||||||
Hell. You feel like a mythic god undergoing punishment
|
Hell. You feel like a mythic god undergoing punishment for cheating death and
|
||||||
for cheating death and deceiving the underworld.
|
deceiving the underworld.
|
||||||
|
|
||||||

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

|

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

|

|
||||||
|
|
||||||
This blog post will guide you on how to swap the `ı` key with the `i` key
|
This blog post will guide you on how to swap the `ı` key with the `i` key (but
|
||||||
(but not the `I` and `İ` keys). This will be a great change if you write primarily
|
not the `I` and `İ` keys). This will be a great change if you write primarily in
|
||||||
in English but need the Turkish symbols sometimes.
|
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
|
> ```cpp
|
||||||
> // The basic Turkish layout with "i" and "ı" swapped.
|
> // The basic Turkish layout with "i" and "ı" swapped.
|
||||||
|
@ -38,9 +38,10 @@ in English but need the Turkish symbols sometimes.
|
||||||
> };
|
> };
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> However, this only swaps the uppercase letters, so the `i` key is unchanged but
|
> However, this only swaps the uppercase letters, so the `i` key is unchanged
|
||||||
> the uppercase of that key is `I` like in English. However, this is usually not
|
> but the uppercase of that key is `I` like in English. However, this is usually
|
||||||
> desired as this still reduces your typing speed (as the `iI` key is too far).
|
> 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
|
Let's create our own layout that does something similar but swaps the lowercase
|
||||||
letters instead. Here is the code for that:
|
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.
|
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
|
Save this to `~/.config/xkb/symbols/tr-swapped-i` and you can tell your WM/DE to
|
||||||
to use the `tr-swapped-i` XKB layout.
|
use the `tr-swapped-i` XKB layout.
|
||||||
|
|
||||||
In Hyprland (The WM I use) you can do it like this:
|
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
|
That should swap the `ı` and `i` keys on your WM/DE successfully. However, we
|
||||||
yet.
|
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.
|
The TTY (swap to TTY 2 by doing `CTRL-ALT-F2`) still doesn't use this layout,
|
||||||
And it seems that the format the TTY uses is a little different.
|
which is a problem. And it seems that the format the TTY uses is a little
|
||||||
Looking at the `kbd` package, it uses a format called `.map`.
|
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
|
```cpp
|
||||||
include "/usr/share/keymaps/i386/qwerty/trq.map"
|
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
|
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.
|
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:
|
This is how it is done on NixOS:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue