Compare commits

...

2 Commits

Author SHA1 Message Date
7dc964f327 unfinished article is a draft 2026-05-20 17:05:07 +01:00
0b0a64884c new article and nonsense nix something something 2026-05-20 17:02:59 +01:00
2 changed files with 291 additions and 0 deletions

108
posts/been-a-while.norg Normal file
View File

@@ -0,0 +1,108 @@
@document.meta
title: Been a While
description: time passes thats crazy
authors: [
Adumh00man
]
categories: [
neovim
nix
blog
]
created: 2026-05-20T15:49:16+01:00
updated: 2026-05-20T15:49:16+01:00
draft: false
layout: post
version: 1.1.1
@end
* Been a While
So. Nvim 0.12 dropped and kind of made neorg die.
** What the hell, Neorg?
This blog is written using norg, a neovim org mode analog. For those of you unfamiliar with emacs terminology (ew), org mode is basically
what jupyter notebooks were written with before jupyter notebooks existed. It's an enhanced markup language that relies heavily on lisp,
the scripting language for emacs, in order to do some really cool stuff.
For starters, you can write and run code directly within the file, which is pretty useful if that's what you want do do I guess. However,
because of how emacs works, this isn't limeted to a certain file type. Let me explain.
*** Emacs is really cool, but also awful
Emacs, as far as people have told me, is a glorified lisp interpreter. Of course, you have your config, like in neovim, but unlike
neovim, emacs has near to no limits. For starters, there's no lua api nonsense. In the same way that everything on linux is a file,
everything on emacs is a mode. There are major modes, which are analogous to nvim's insert and command modes, and then minor modes,
which alter the functionality of a major mode. But, this isn't just limited to the text buffer. When I said everything, I meant
*everything*. The menu bar is a minor mode for the window, which itself is technically a mode. The buttons within the bar are minor
modes, too! The cursor is a mode, the font is a mode, you get the picture. All of these modes are accesible at runtime, through the
equivalent of the command pallete, alt-x.
Anyway, the point I'm trying to make is that emacs is for insane people. If you ever wanted to edit text in the title of the window as
if it were an intentional feature (totally possible, the window title is just a buffer), then emacs is the editor for you. This
extensible nature is what lets org mode exist. The features are just as insane as emacs itself. It starts simple, with being able to
fold sections based on structured headings, but then extends to transparent tables, that have full function support that you would
expect from something like excel. Not to mention that the whole file can be exported natively to html or latex with the click
of a button. All of this within a text editor, may I remind you. So, what does this have to do with whatever I'm talking about?
*** Neorg is a step in the right direction
Neorg is supposed to be a replacement for this incredible power, just in neovim. The concept is simple, just rewrite everything in lua,
right? Wrong. Unlike emacs, neovim config is surprisingly restrictive. Emacs itself is basically written in lisp, which is what makes
it so powerful. Of course, there's some baseline c code to interpret the initial steps, but the rest is custom built. That means that
everything the developers can do, an end user can do just as easily. There's nothing stopping you from writing a whole new text editor
in lisp, or even something more complex (check out {https://github.com/emacs-exwm/exwm}[exwm], a whole ass window manager in lisp).
It goes without saying that neovim has nowhere near the extensibility to be able to make a whole window manager, which makes it much
harder to make an org mode replacement.
In nvim, you're stuck with whatever the devs give you, through the lua api. This is enough to make something like Telescope, or a
dired ripoff like oil.nvim, but comes way short when trying to rival emacs in extensibility. For instance, when making a plugin,
especially something to do with filetypes, many of the features found in org mode (folding, embedded code blocks) don't have proper
implementations. There are folds in nvim, but they rely on treesitter and lsp heavily, meaning that before long your dependancy tree
is insane, and you need 5 different plugins just to highlight the headers and embed properly. Emacs? Of course, they have an entire
treesitter implementation written in lisp, that also defines languages in lisp, which means that it can be configured at runtime.
Damn, I might have to switch to emacs.
** The neorg problem
Neorg is an incredible project. It works how I want it to, basically as a better markdown, but that means that most of the plugins I'm
installing are useless to me. For one, norg refuses to work at all without treesitter. Due to lack of compliancy with the new spec,
all neorg users are forced to use the old master branch for treesitter, because the main branch no longer accepts scanners written in
cpp. Take a wild guess what language the neorg scanner is written in. The plugin also has an lsp, for all 4 of the different blocks,
one of which isn't even implemented, meaning I have to install a whole lsp stack, which is about 10 plugins by itself, depending on what
you use. Neorg also isn't supported on 0.12, meaning that you have to use an old version of neovim on a seperate config, and set up lazy
because vim.pack isn't supported yet. And then there are the non-negotiable plugins that I use on neovim just to edit files, adding about
10 more random quality of life features (I'm not editing anything without my mini.surround).
This still isn't counting Latex support, by the way, which was a norg feature, but now has to follow a different spec because their
renderer broke. They now advise using snacks' renderer, which works, but adds another plugin and messes up the syntax highlighting for
said latex, or sometimes just doesn't highlight at all. Not that latex is implemented on this website, anyway.
Right now, I have 40 plugins, just to edit a markdown file. To someone who prides themselves in having a clean config, the whole setup
feels bloated and slow.
** The theoretical solution
I could write my own nonsense file type, but I don't have the time or knowledge to come up with anything remotely functional. On top of
making a whole file type, spec and all, from scratch, I would also basically have to write a static site generator for it, so that I
could keep writing this blog, as well as make some kind of transition script so that I can move all of my notes that are written in
neorg over to whatever file type I would end up making. Did I mention I've never even made a neovim plugin?
The real issue is lack of support. Nobody cares about a niche replacement for an already niche file type on a specialist editor, which
means that nobody wants to rewrite the treesitter integration so that it's compliant with the main branch, nobody wants to make a
proper lsp and find some way to distribute it, and nobody wants to implement tables properly for all of the four people out there that
would use them. Other than the creator of the site generator I'm using, {https://norgolith.amartin.beer/}[Norgolith], I might be the only
person on the internet writing a blog in norg. There are alternatives, but they suffer the same problem of overbuilding and the same
lack of modularity. Projects like orgmode for nvim exist, sure, but all the site generators for proper org mode files are intended to be
used from within emacs, meaning that I can't easily publish anything anyway.
What I've been forced to do for now is clone an older version of my repo and use that config. After gutting out all of the lsp nonsense
and some code-specific plugins, everything works as intended again, as is the intention with flakes. Just load up the nix shell and have
everything as you left it.
** Some kind of resolution
After messing about with svelte, I might just make a typescript norg parser and turn this blog into a dynamic site. For starters, I could
remove the direct norgolith input from my flake, which I don't particularly like, and I would also have full control over the look,
unlike whatever stolen theme this is, just refreshed with a catppuccin css file. Worth looking into, but, for now, norg is here to stay.
Atleast until I get bored.
Next up: why I hate neovim
See ya!

183
posts/cool-nix-shit.norg Normal file
View File

@@ -0,0 +1,183 @@
@document.meta
title: Cool shit you can do with nix
description: Nix is surprisingly versatile
authors: [
Adumh00man
]
categories: [
nix
linux
blog
]
created: 2026-03-28T19:03:27+00:00
updated: 2026-03-28T19:59:57+0100
draft: true
layout: post
version: 1.1.1
@end
* Nix is hard
Nix is supposed to be a solve-all to the "it runs on my machine" problem. And it is. If it didn't do that, then there would be no point in
it existing. But, the syntax is a pain in the ass, and the documentation is half baked at best. For reference, everything I talk about
here is coming from my {https://git.voidarc.co.uk/voidarc/nixos}[nixos config repo], so if you need some context, then everything in
there should be functional enough, at least to serve as some kind of guide.
+html.class note
> I am not a professional. If you want to get your info from someone that knows what they're talking about, look on youtube, idiot.
** Starting out
This whole guide is coming from the perspective of someone who has never used nix outside of nixos. I decided to switch one day and had
to learn as I went ({:/posts/nix:}[/If only there was a post about that/]). Of course, at the beginning, my config was very simple. I
basically tried to replicate my arch config, which I already managed the dotfiles for through git. I managed, but my main issue was that
my nixos config had to be edited by the root user, because it was in the `/etc/nixos` directory. This is the default location, which makes
sense, because most linux systems need to be oriented toward having multiple users, and you don't want every person on the system to be
able to change the underlying programs. However, this is irritating, because you have to manage a git repo as the root user, which *sucks*.
There are some workarounds, mostly involving symlinks, that, if broken, will brick your system, so they aren't recommended. The real way
you're supposed to do it is with flakes.
*** Flakes
Flakes aren't real. They can't hurt you. But, they can let you manage your config outside of the `/etc` directory.
@code nix
{
description = "My example flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }: {
packages.x86_64-linux = {
default = self.packages.x86_64-linux.hello;
hello = nixpkgs.legacyPackages.x86_64-linux.hello;
};
};
}
@end
This is the default flake that you get upon running `nix flake init` in a project. What you'll immediately notice is that there are only
2 sections: inputs and outputs (there are more but idk how to use them, except the description). These are not as explanatory as you
might first expect, so I tend to think about it like this:
- Inputs
-- External links / projects
-- Immutable (for the most part)
- Outputs
-- Generated / built code
-- Changable
-- Where you would put anything of interest
I am aware this clears up nothing, so let me explain slightly further.
**** Inputs
Without inputs, you basically can't build anything outside of a hello world with no dependancies. They are the main reason that flakes
were made in the first place. This is because every input is stored in the lock file as a hash of the git repo it is a part of. I went
more in depth in the article I linked to at the start, but for now I'll give you some examples.
The main input that you would need to
know about is the `nixpkgs` input, which provides a fixed version of the nixpkgs git repo that you can use to access whatever packages
you need. This can be unstable, which, as the name suggests, is newer and less supported, a fixed hash, like
`nixpkgs.url = "github:nixos/nixpkgs?ref=f5da6d7f24b8565882487ce7f45c2a7d9d8afdeb";`, or just a branch, like the one in my config:
`nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";`. All have different use cases, which I may or may not get to.
Another common form of input is a repo input. Nixpkgs uses this kind, so it follows the same rules.
@code nix
omnisearch = {
url = "git+https://git.voidarc.co.uk/voidarc/omnisearch";
inputs.nixpkgs.follows = "nixpkgs";
};
@end
The url is slightly different because the repo isn't hosted on github, but the `github:` from before is just a shortcut that expands
into `git+https://github.com/` when you build the flake. Notice that there is another line in the input. This tells nix to use the
version of nixpkgs that the whole system is running on, the one in this repo's flake.lock, instead of the one in the called flake's
repo. This saves storage and prevents you from installing needless copies of apps that are basically the same. Using this syntax is
best practice unless there is a specific version of a dependancy that the app needs.
The last kind of input you're probably going to see is the local input. These come in the form of local paths, relative to the current flake.
These are used when you have submodules that aren't large enough to deserve a whole repo, or modules that you need to reload on the fly.
@code nix
chataigne.url = "./modules/chataigne";
nvim-wrapped = {
url = "git+file:///home/user01/.dotfiles/.config/nvim";
inputs.nixpkgs.follows = "nixpkgs";
};
@end
The first input here is just a relative path, with a specific set of dependancies, hence it doesn't follow nixpkgs like the other.
The second input is still a local module, but it isn't relative. The flake is located in a path above the system flake, that I want
to call it from, so I needed to use a workaround and use the repo input type with a `file://` prefix. This lets me test my nvim config
without pushing to git beforehand, which is useful when I've only added one dependancy and don't want to make a whole commit for 3
lines of code. (don't worry, we'll get back to why it's called nvim-wrapped later)
**** Outputs
Outputs, as I said, are what's produced when the flake is run. There are different types of these, too, so let's start simple.
Before you can even think about compiling an app, you have to allow the outputs access to the inputs. This can be seen as the
function call at the beginning of the output section:
@code nix
outputs =
{ self, nixpkgs }:
{
# Whatever app
};
@end
However, this only allows the outputs to access nixpkgs, which is ok for the first type of output: The humble binary.
Binaries are defined by system. This allows you to have different build instructions for x64 and arm systems in the same flake, but with
modern programming languages that isn't much of an issue. As an example, this flake output would provide fastfetch
@code nix
packages.${system}.default = pkgs.fastfetch;
@end
Simple, right? the `nixpkgs` input provides `pkgs` as a callable parameter, so that would be all you need. This is on display with
the example flake from earlier, providing the `hello` package for x86_64-linux.
This can be added to, by providing a devshell with this package, although that requires slightly more boilerplate.
@code nix
devShells.${system}.default = pkgs.mkShell {
# Packages you want available in your shell
buildInputs = [
pkgs.fastfetch
];
# Environmental variables or shell hooks that you want to run
# when the shell starts
shellHook = ''
export SOME_VAR=foo
echo "Shell started"
'';
};
@end
Of course, a whole shell for fastfetch is a solved issue, with `nix shell` and everything, but for explanatory purposes that's all you
would need to read flakes, and understand what you would need to call in order to get the right package from a repo. There are obviously
building tools, but I have no idea how those work. This is supposed to be from a fully nixos user perspective, and I don't tend to write
too much code.
Finally, there's the main thing that you would need to manage your system, `pkgs.lib.nixosSystem`. Of course, you could use the
function directly, but that's boring, so I made a function to make a system instead:
@code nix
outputs =
{
self,
nixpkgs,
...
}@inputs:
let
mkSystem =
extraModules:
nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = { inherit inputs; };
modules = [
common
hardwareConfig
]
++ extraModules;
};
in
{
nixosConfigurations = {
mobile02 = mkSystem [ ./configs/configuration-laptop.nix ];
};
@end
There are a few things to note here. This is from my system flake, I've just omitted my pc config, because you only really need one to
see what's going on. Starting from the top, there is an extra `@inputs` after the output function. This allows for the `inherit inputs`
inside the mkSystem function, so that you can dynamically access any input from whatever module you're calling for your system.