24 Commits

Author SHA1 Message Date
Tom Alexander
862829c57c Preserve firefox cache. 2024-12-20 21:38:19 -05:00
Tom Alexander
aba96213c3 Enable the nixd language server in emacs. 2024-12-20 21:19:22 -05:00
Tom Alexander
e7ab762ee4 Fix firefox launch time. 2024-12-20 21:06:04 -05:00
Tom Alexander
b314982196 Set up firefox. 2024-12-20 18:30:35 -05:00
Tom Alexander
27060fed8d Preserve gpg directory. 2024-12-20 16:50:27 -05:00
Tom Alexander
20c1c46d12 Set up fonts. 2024-12-20 16:07:12 -05:00
Tom Alexander
3b133ed86c Do not launch alacritty at the start. 2024-12-20 15:34:02 -05:00
Tom Alexander
0aad0c39f4 Enable wayland support for emacs.
This unfortunately means pinning to a specific version (or using 3rd party emacs-overlay).
2024-12-20 15:30:51 -05:00
Tom Alexander
fe1033fa4b Switch to uid/gid 11235. 2024-12-20 15:22:46 -05:00
Tom Alexander
2ce635d028 Fix emacs config. 2024-12-20 15:03:33 -05:00
Tom Alexander
ba3a6e74eb Add git config and initial emacs config. 2024-12-20 13:17:13 -05:00
Tom Alexander
7e768022e7 Add hotkeys and window management to sway. 2024-12-19 23:08:19 -05:00
Tom Alexander
a76bd4ebd3 Fix wifi config 2024-12-19 22:20:55 -05:00
Tom Alexander
df89d1b973 Enable redistributable firmware. 2024-12-19 19:52:27 -05:00
Tom Alexander
50811aad77 Set up building an ISO from the config. 2024-12-19 19:36:10 -05:00
Tom Alexander
df3528d62a Enable graphics acceleration. 2024-12-19 18:59:38 -05:00
Tom Alexander
e97c570bb2 Trust wheel. 2024-12-19 18:09:48 -05:00
Tom Alexander
fbcb0826d2 Extremely minimal sway setup. 2024-12-19 17:33:21 -05:00
Tom Alexander
74499fb6a0 Switch to a different way of building the VM. 2024-12-19 16:28:40 -05:00
Tom Alexander
fbbff409a0 Add a build for a qemu virtual machine. 2024-12-19 16:14:47 -05:00
Tom Alexander
05da118d8f Start module for sway. 2024-12-19 15:13:56 -05:00
Tom Alexander
033d695fd9 Only set bootloader when in VM. 2024-12-19 15:06:57 -05:00
Tom Alexander
6953cdb81f Set up a minimal initial config. 2024-12-17 16:46:44 -05:00
Tom Alexander
48f700b803 Add script for managing nix testing vm. 2024-12-17 16:46:43 -05:00
47 changed files with 2647 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
{ config, lib, pkgs, ... }:
{
imports = [];
boot.loader.grub.enable = false;
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
# TODO: make not write bootx64.efi
boot.loader.efi.canTouchEfiVariables = false;
# Automatically delete old generations
boot.loader.systemd-boot.configurationLimit = 3;
}
# efibootmgr -c -d /dev/sda -p 1 -L NixOS-boot -l '\EFI\NixOS-boot\grubx64.efi'
# Text-only:
# sudo cp "$(nix-build '<nixpkgs>' --no-out-link -A 'refind')/share/refind/refind_x64.efi" /boot/EFI/boot/bootx64.efi
# Full graphics:
# $ sudo nix-shell -p refind efibootmgr
# $ refind-install

View File

@@ -0,0 +1,199 @@
{ config, lib, pkgs, pkgs-unstable, home-manager, ... }:
{
imports =
[
./roles/reset
./hosts/odo
"${builtins.fetchTarball {url="https://github.com/nix-community/disko/archive/refs/tags/v1.9.0.tar.gz";sha256="0j76ar4qz320fakdii4659w5lww8wiz6yb7g47npywqvf2lbp388";}}/module.nix"
./boot.nix
./zfs.nix
./network.nix
./roles/firewall
./roles/graphics
./roles/sound
./roles/sway
./roles/firefox
./roles/emacs
./roles/git
./roles/fonts
./roles/gpg
];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.trusted-users = [ "@wheel" ];
boot.kernelPackages = pkgs.linuxPackages_6_11;
hardware.enableRedistributableFirmware = true;
users.mutableUsers = false;
users.users.talexander = {
isNormalUser = true;
createHome = true; # https://github.com/NixOS/nixpkgs/issues/6481
group = "talexander";
extraGroups = [ "wheel" ];
uid = 11235;
packages = with pkgs; [
tree
];
# Generate with `mkpasswd -m scrypt`
hashedPassword = "$7$CU..../....VXvNQ8za3wSGpdzGXNT50/$HcFtn/yvwPMCw4888BelpiAPLAxe/zU87fD.d/N6U48";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGu+k5lrirokdW5zVdRVBOqEOAvAPlIkG/MdJNc9g5ky"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIEI6mu6I5Jp+Ib0vJxapGHbEShZjyvzV8jz5DnzDrI39AAAABHNzaDo="
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAFNcSXwvy+brYTOGo56G93Ptuq2MmZsjvRWAfMqbmMLAAAABHNzaDo="
];
};
users.groups.talexander.gid = 11235;
home-manager.users.talexander = { pkgs, ... }: {
home.packages = [ pkgs.atool pkgs.httpie ];
programs.bash.enable = true;
# The state version is required and should stay at the version you
# originally installed.
home.stateVersion = "24.11";
};
# Automatic garbage collection
nix.gc = {
# Runs nix-collect-garbage --delete-older-than 5d
automatic = true;
randomizedDelaySec = "14m";
options = "--delete-older-than 5d";
};
# Use doas instead of sudo
security.doas.enable = true;
security.doas.wheelNeedsPassword = false;
security.sudo.enable = false;
security.doas.extraRules = [{
# Retain environment (for example NIX_PATH)
keepEnv = true;
persist = true; # Only ask for a password the first time.
}];
# Do not use default packages (nixos includes some defaults like nano)
environment.defaultPackages = lib.mkForce [];
environment.systemPackages = with pkgs; [
wget
mg
rsync
libinput
htop
tmux
file
usbutils # for lsusb
pciutils # for lspci
mesa-demos # for glxgears TODO move to better role
vulkan-tools # for vkcube TODO move to better role
xorg.xeyes # to test which windows are using x11 TODO move to better role
ripgrep
strace
tcpdump
];
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
hostKeys = [
{
path = "/persist/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
{
path = "/persist/ssh/ssh_host_rsa_key";
type = "rsa";
bits = 4096;
}
];
};
# Check what will be lost with `zfs diff zroot/linux/root@blank`
boot.initrd.systemd.enable = lib.mkDefault true;
boot.initrd.systemd.services.zfs-rollback = {
description = "Rollback ZFS root dataset to blank snapshot";
wantedBy = [
"initrd.target"
];
after = [
"zfs-import-zroot.service"
];
before = [
"sysroot.mount"
];
path = with pkgs; [
zfs
];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
zfs rollback -r zroot/linux/nix/root@blank
zfs rollback -r zroot/linux/nix/home@blank
echo "rollback complete"
'';
};
environment.persistence."/persist" = {
hideMounts = true;
directories = [
"/var/lib/iwd" # Wifi settings
"/var/lib/nixos" # Contains user information (uids/gids)
];
files = [
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
];
# users.talexander = {
# directories = [];
# files = [];
# };
};
# Write a list of the currently installed packages to /etc/current-system-packages
environment.etc."current-system-packages".text =
let
packages = builtins.map (p: "${p.name}") config.environment.systemPackages;
sortedUnique = builtins.sort builtins.lessThan (lib.unique packages);
formatted = builtins.concatStringsSep "\n" sortedUnique;
in
formatted;
# nixpkgs.overlays = [
# (final: prev: {
# nix = pkgs-unstable.nix;
# })
# ];
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.11"; # Did you read the comment?
}

99
nix/configuration/flake.lock generated Normal file
View File

@@ -0,0 +1,99 @@
{
"nodes": {
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1734366194,
"narHash": "sha256-vykpJ1xsdkv0j8WOVXrRFHUAdp9NXHpxdnn1F4pYgSw=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "80b0fdf483c5d1cb75aaad909bd390d48673857f",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-24.11",
"repo": "home-manager",
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1734200366,
"narHash": "sha256-0NursoP4BUdnc+wy+Mq3icHkXu/RgP1Sjo0MJxV2+Dw=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "c6323585fa0035d780e3d8906eb1b24b65d19a48",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1734323986,
"narHash": "sha256-m/lh6hYMIWDYHCAsn81CDAiXoT3gmxXI9J987W5tZrE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "394571358ce82dff7411395829aa6a3aad45b907",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-b93b4e9b5": {
"locked": {
"lastModified": 1713721570,
"narHash": "sha256-R0s+O5UjTePQRb72XPgtkTmEiOOW8n+1q9Gxt/OJnKU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b93b4e9b527904aadf52dba6ca35efde2067cbd4",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b93b4e9b527904aadf52dba6ca35efde2067cbd4",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1734424634,
"narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"impermanence": "impermanence",
"nixpkgs": "nixpkgs",
"nixpkgs-b93b4e9b5": "nixpkgs-b93b4e9b5",
"nixpkgs-unstable": "nixpkgs-unstable"
}
}
},
"root": "root",
"version": 7
}

115
nix/configuration/flake.nix Normal file
View File

@@ -0,0 +1,115 @@
# Build ISO image
# doas nix run github:nix-community/nixos-generators -- --flake .#odo --format iso
{
description = "My system configuration";
inputs = {
impermanence.url = "github:nix-community/impermanence";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-b93b4e9b5.url = "github:NixOS/nixpkgs/b93b4e9b527904aadf52dba6ca35efde2067cbd4";
home-manager.url = "github:nix-community/home-manager/release-24.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-b93b4e9b5, impermanence, home-manager, ... }@inputs: let
base-system = {};
odoqemu = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
specialArgs = {
pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 {
inherit system;
# config.allowUnfree = true;
};
pkgs-unstable = import nixpkgs-unstable {
inherit system;
# config.allowUnfree = true;
};
};
modules = [
impermanence.nixosModules.impermanence
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
}
./configuration.nix
({lib, ...}: {
imports = [ <nixpkgs/nixos/modules/virtualisation/qemu-vm.nix> ];
virtualisation.qemu.options = [
"-device virtio-vga"
];
virtualisation.vmVariant = {
# following configuration is added only when building VM with build-vm
virtualisation = {
memorySize = 2048; # Use 2048MiB memory.
cores = 3;
graphics = false;
};
};
networking.dhcpcd.enable = lib.mkForce true;
networking.useDHCP = lib.mkForce true;
boot.loader.efi.canTouchEfiVariables = lib.mkForce true;
# doas nixos-rebuild build-vm --flake .#odoqemu
#./result/bin/run-nixos-vm
})
];
};
odo = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
specialArgs = {
pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 {
inherit system;
# config.allowUnfree = true;
};
pkgs-unstable = import nixpkgs-unstable {
inherit system;
# config.allowUnfree = true;
};
};
modules = [
impermanence.nixosModules.impermanence
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
}
./configuration.nix
];
};
in
{
# doas nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#vms.odo
# ./result/bin/run-nixos-vim
vms.odo = odoqemu.config.system.build.vm;
odoiso = odo.config.system.build.isoImage;
nixosConfigurations.odo = odo;
nixosConfigurations.odovm = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
specialArgs = {
pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 {
inherit system;
# config.allowUnfree = true;
};
pkgs-unstable = import nixpkgs-unstable {
inherit system;
# config.allowUnfree = true;
};
};
modules = [
impermanence.nixosModules.impermanence
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
}
./configuration.nix
({lib, ...}: {
networking.dhcpcd.enable = lib.mkForce true;
networking.useDHCP = lib.mkForce true;
boot.loader.efi.canTouchEfiVariables = lib.mkForce true;
})
];
};
};
}

View File

@@ -0,0 +1,14 @@
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
];
# Generate with `head -c4 /dev/urandom | od -A none -t x4`
networking.hostId = "908cbf04";
networking.hostName = "odo"; # Define your hostname.
time.timeZone = "America/New_York";
}

View File

@@ -0,0 +1,110 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" "noatime" "discard" ];
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
};
zpool = {
zroot = {
type = "zpool";
# mode = "mirror";
# Workaround: cannot import 'zroot': I/O error in disko tests
options.cachefile = "none";
options = {
ashift = "12";
compatibility = "openzfs-2.2-freebsd";
autotrim = "on";
};
rootFsOptions = {
acltype = "posixacl";
atime = "off";
relatime = "off";
xattr = "sa";
mountpoint = "none";
compression = "lz4";
canmount = "off";
utf8only = "on";
dnodesize = "auto";
normalization = "formD";
};
datasets = {
"linux/nix" = {
type = "zfs_fs";
options.mountpoint = "none";
options = {
encryption = "aes-256-gcm";
keyformat = "passphrase";
# keylocation = "file:///tmp/secret.key";
};
};
"linux/nix/root" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/root@blank$' || zfs snapshot zroot/linux/nix/root@blank";
};
"linux/nix/nix" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/nix";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/nix@blank$' || zfs snapshot zroot/linux/nix/nix@blank";
options = {
recordsize = "16MiB";
compression = "zstd-19";
};
};
"linux/nix/home" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/home";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/home@blank$' || zfs snapshot zroot/linux/nix/home@blank";
};
"linux/nix/persist" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/persist";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/persist@blank$' || zfs snapshot zroot/linux/nix/persist@blank";
};
"linux/nix/state" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/state";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/state@blank$' || zfs snapshot zroot/linux/nix/state@blank";
};
};
};
};
};
# Make sure all persistent volumes are marked as neededForBoot
#
# Also mounts /home so it is mounted before the user home directories are created.
fileSystems."/persist".neededForBoot = true;
fileSystems."/state".neededForBoot = true;
fileSystems."/home".neededForBoot = true;
}

View File

@@ -0,0 +1,26 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp58s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -0,0 +1,39 @@
{ config, lib, pkgs, ... }:
{
imports = [];
networking.dhcpcd.enable = false;
networking.useDHCP = false;
networking.nameservers = [ "194.242.2.2#doh.mullvad.net" "2a07:e340::2#doh.mullvad.net" ];
services.resolved = {
enable = true;
dnssec = "true";
domains = [ "~." ];
fallbackDns = [ ];
dnsovertls = "true";
};
# Without this, systemd-resolved will send DNS requests for <X>.home.arpa to the per-link DNS server (172.16.0.1) which does not support DNS-over-TLS. This leads to the connection anging and timing out. This causes firefox startup to take an extra 10+ seconds.
#
# Test with: drill @127.0.0.53 odo.home.arpa
networking.extraHosts = "127.0.0.1 odo.home.arpa";
networking.wireless.iwd = {
enable = true;
settings = {
General = {
EnableNetworkConfiguration = true;
AddressRandomization = "network";
ControlPortOverNL80211 = false;
};
};
};
environment.systemPackages = with pkgs; [
iw
iwd
ldns # for drill
];
}

View File

@@ -0,0 +1,7 @@
{ config, lib, pkgs, ... }:
{
imports = [];
}

View File

@@ -0,0 +1,69 @@
{ config, lib, pkgs, ... }:
let
plainmacs = pkgs.writeShellScriptBin "plainmacs" ''
INIT_SCRIPT=$(cat <<EOF
(progn
(setq make-backup-files nil auto-save-default nil create-lockfiles nil)
(load-theme 'tango-dark t)
(set-face-attribute 'default nil :background "black")
;; Bright yellow highlighting for selected region
(set-face-attribute 'region nil :background "#ffff50" :foreground "black")
;; Bright green cursor to distinguish from yellow region
(set-cursor-color "#ccff66")
;; Hightlight the current line
(set-face-attribute 'line-number-current-line nil :foreground "white")
;; Set default font
(set-face-attribute 'default nil :height 100 :width 'regular :weight 'regular :family "Cascadia Mono")
;; Set fallback font for unicode glyphs
(when (display-graphic-p)
(set-fontset-font "fontset-default" nil (font-spec :name "Noto Color Emoji")))
(menu-bar-mode -1)
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when ( fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
(pixel-scroll-precision-mode)
(setq frame-resize-pixelwise t)
)
EOF
)
exec ${pkgs.emacs29-pgtk}/bin/emacs -q --eval "$INIT_SCRIPT" "''${@}"
'';
in
{
imports = [];
environment.systemPackages = with pkgs; [
plainmacs
emacs29-pgtk
clang # To compile tree-sitter grammars
nixd # nix language server
];
home-manager.users.talexander = { pkgs, ... }: {
home.file.".config/emacs" = {
source = ./files/emacs;
recursive = true;
};
};
environment.persistence."/state" = {
hideMounts = true;
users.talexander = {
directories = [
".config/emacs/eln-cache" # Installed packages
".config/emacs/elpa" # Installed packages
".config/emacs/private" # For recentf
".config/emacs/tree-sitter" # Compiled tree-sitter grammars
];
files = [
".config/emacs/history" # For savehist
".config/emacs/.last-package-update-day" # For use-package
];
};
};
environment.variables.EDITOR = "${plainmacs}/bin/plainmacs";
}

View File

@@ -0,0 +1,25 @@
(setq gc-cons-threshold (* 128 1024 1024)) ;; 128MiB Increase garbage collection threshold for performance (default 800000)
;; Increase amount of data read from processes, default 4k
(when (version<= "27.0" emacs-version)
(setq read-process-output-max (* 10 1024 1024)) ;; 10MiB
)
;; Suppress warnings
(setq byte-compile-warnings '(not obsolete))
(setq warning-suppress-log-types '((comp) (bytecomp)))
(setq native-comp-async-report-warnings-errors 'silent)
;; Set up default visual settings
(setq frame-resize-pixelwise t)
;; Disable toolbar & menubar
(menu-bar-mode -1)
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when (display-graphic-p)
(context-menu-mode +1))
(setq default-frame-alist '((fullscreen . maximized)
(vertical-scroll-bars . nil)
(horizontal-scroll-bars . nil)
;; Set dark colors in early-init to prevent flashes of white.
(background-color . "#000000")))

View File

@@ -0,0 +1,86 @@
(use-package diminish)
;; Eglot recommends pulling the latest of the standard libraries it
;; uses from ELPA if you're not tracking the current.config/emacsevelopment
;; branch.
(use-package xref
:pin gnu
)
(use-package eldoc
:pin gnu
:diminish
)
;; Other packages
(use-package emacs
:config
(setq enable-recursive-minibuffers t)
;; Filter the M-x list base on the current mode
(setq read-extended-command-predicate #'command-completion-default-include-p)
;; Enable triggering completion with the tab key.
(setq tab-always-indent 'complete)
)
(use-package dashboard
:config
(dashboard-setup-startup-hook))
(when (version<= "26.0.50" emacs-version )
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'prog-mode-hook 'column-number-mode)
)
;; Display a horizontal line instead of ^L for page break characters
(use-package page-break-lines
:diminish
:config
(global-page-break-lines-mode +1)
)
(use-package recentf
;; This is an emacs built-in but we're pulling the latest version
:config
(setq recentf-max-saved-items 100)
(setq recentf-save-file (recentf-expand-file-name "~/.config/emacs/private/cache/recentf"))
(recentf-mode 1))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
;; This is an emacs built-in but we're pulling the latest version
:config
(savehist-mode))
(use-package which-key
:diminish
:config
(which-key-mode))
(use-package windmove
:config
(windmove-default-keybindings))
(setq tramp-default-method "ssh")
(use-package nginx-mode
:mode (
("headers\\.include\\'" . nginx-mode)
)
:config
(setq nginx-indent-level 4))
(use-package systemd
:mode
(("\\.service\\'" . systemd-mode)
("\\.timer\\'" . systemd-mode))
)
(use-package pkgbuild-mode
:mode
(("PKGBUILD\\'" . pkgbuild-mode))
)
(provide 'base-extensions)

View File

@@ -0,0 +1,127 @@
;; ========== Function to reload current file =================
(defun reload-file ()
"Revert buffer without confirmation."
(interactive)
(revert-buffer :ignore-auto :noconfirm))
;; ===========================================================
;; ============= Run commands ================================
(defun run-command-on-buffer (cmd &rest args)
"Run a command using the current buffer as stdin and replacing its contents if the command succeeds with the stdout from the command. This is useful for code formatters."
(let (
(stdout-buffer (generate-new-buffer "tmp-stdout" t))
(full-cmd (append '(call-process-region nil nil cmd nil stdout-buffer nil) args))
)
(unwind-protect
(let ((exit-status (eval full-cmd)))
(if (eq exit-status 0)
(save-excursion
(replace-buffer-contents stdout-buffer)
)
(message "FAILED running command on buffer %s" (append (list cmd) args))
)
)
(kill-buffer stdout-buffer)
)
)
)
(defun run-command-in-directory (dir cmd &rest args)
"Run a command in the specified directory. If the directory is nil, the directory of the file is used. The stdout result is trimmed of whitespace and returned."
(let (
(default-directory (or dir default-directory))
(stdout-buffer (generate-new-buffer "tmp-stdout" t))
(full-cmd (append '(call-process cmd nil (list stdout-buffer nil) nil) args))
)
(unwind-protect
(let ((exit-status (condition-case nil (eval full-cmd) (file-missing nil))))
(if (eq exit-status 0)
(progn
(with-current-buffer stdout-buffer
(string-trim (buffer-string))
)
)
)
)
(kill-buffer stdout-buffer)
)
)
)
(defun load-directory (dir)
(let ((load-it (lambda (f)
(load-file (concat (file-name-as-directory dir) f)))
))
(mapc load-it (directory-files dir nil "\\.el$"))))
(defun generate-vc-link ()
(interactive)
(or
(generate-github-link)
(generate-source-hut-link)
)
)
(defun generate-github-link ()
"Generate a permalink to the current line."
(interactive)
(let (
(current-rev (vc-working-revision buffer-file-name))
(line-number (line-number-at-pos))
(repository-url (vc-git-repository-url buffer-file-name))
(relative-path (file-relative-name buffer-file-name (vc-root-dir)))
)
(save-match-data
(and (string-match "\\(git@github\.com:\\|https://github\.com/\\)\\([^/]+\\)/\\([^.]+\\).git" repository-url)
(let* (
(gh-org (match-string 2 repository-url))
(gh-repo (match-string 3 repository-url))
(full-url (format "https://github.com/%s/%s/blob/%s/%s?plain=1#L%s" gh-org gh-repo current-rev relative-path line-number))
)
(message "%s" full-url)
(kill-new full-url)
t
)
)
)
)
)
(defun generate-source-hut-link ()
"Generate a permalink to the current line."
(interactive)
(let (
(current-rev (vc-working-revision buffer-file-name))
(line-number (line-number-at-pos))
(repository-url (vc-git-repository-url buffer-file-name))
(relative-path (file-relative-name buffer-file-name (vc-root-dir)))
)
(message "Using repo url %s" repository-url)
(save-match-data
(and (string-match "https://git.sr.ht/\\([^/]+\\)/\\([^/]+\\)" repository-url)
(let* (
(sh-org (match-string 1 repository-url))
(sh-repo (match-string 2 repository-url))
(full-url (format "https://git.sr.ht/%s/%s/tree/%s/%s#L%s" sh-org sh-repo current-rev relative-path line-number))
)
(message "%s" full-url)
(kill-new full-url)
t
)
)
)
)
)
(defmacro when-linux (&rest body)
"Execute only when on Linux."
(declare (indent defun))
`(when (eq system-type 'gnu/linux) ,@body))
(defmacro when-freebsd (&rest body)
"Execute only when on FreeBSD."
(declare (indent defun))
`(when (eq system-type 'berkeley-unix) ,@body))
(provide 'base-functions)

View File

@@ -0,0 +1,12 @@
;; Add your keys here, as such
;; Disable the suspend frame hotkeys
(global-unset-key (kbd "C-z"))
(global-unset-key (kbd "C-x C-z"))
;; dabbrev-expand. Seems to be some sort of dumb-expand. Accidentally hitting it when trying to use M-?
(global-unset-key (kbd "M-/"))
(global-set-key (kbd "C-x g l") 'generate-vc-link)
(provide 'base-global-keys)

View File

@@ -0,0 +1,15 @@
;; Set theme
(load-theme 'tango-dark t)
(set-face-attribute 'default nil :background "black")
;; Bright yellow highlighting for selected region
(set-face-attribute 'region nil :background "#ffff50" :foreground "black")
;; Bright green cursor to distinguish from yellow region
(set-face-attribute 'cursor nil :background "#ccff66")
;; Hightlight the current line
(set-face-attribute 'line-number-current-line nil :foreground "white")
;; Set default font
(set-face-attribute 'default nil :height 100 :width 'regular :weight 'regular :family "Cascadia Mono")
;; Set fallback font for unicode glyphs
(set-fontset-font t 'emoji (font-spec :name "Noto Color Emoji") nil 'prepend)
(provide 'base-theme)

View File

@@ -0,0 +1,94 @@
(package-initialize)
(use-package use-package)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/")
)
(use-package auto-package-update
:ensure t
:config
(setq auto-package-update-delete-old-versions t
auto-package-update-interval 14)
(auto-package-update-maybe))
(defun assert-directory (p)
(unless (file-exists-p p) (make-directory p t))
p
)
(defconst private-dir (expand-file-name "private" user-emacs-directory))
(defconst temp-dir (format "%s/cache" private-dir)
"Hostname-based elisp temp directories")
(assert-directory (concat temp-dir "/auto-save-list/"))
(setq autoload-directory (concat user-emacs-directory (file-name-as-directory "elisp") (file-name-as-directory "autoload")))
(add-to-list 'load-path (assert-directory autoload-directory))
(setq-default
;; Disable backup files and lockfiles
make-backup-files nil
auto-save-default nil
create-lockfiles nil
;; Unless otherwise specified, always install packages if they are absent.
use-package-always-ensure t
;; Point custom-file at /dev/null so emacs does not write any settings to my dotfiles.
custom-file "/dev/null"
;; Don't pop up a small window at the bottom of emacs at launch.
inhibit-startup-screen t
inhibit-startup-message t
;; Don't show the list of buffers when opening many files.
inhibit-startup-buffer-menu t
;; Give the scratch buffer a clean slate.
initial-major-mode 'fundamental-mode
initial-scratch-message nil
;; Send prompts to mini-buffer not the GUI
use-dialog-box nil
;; End files with line break
require-final-newline t
;; Use spaces, not tabs
indent-tabs-mode nil
;; Use a better frame title
frame-title-format '("" invocation-name ": "(:eval (if (buffer-file-name)
(abbreviate-file-name (buffer-file-name))
"%b")))
;; Use 'y' or 'n' instead of 'yes' or 'no'
use-short-answers t
;; Natively compile packages
package-native-compile t
;; Confirm when opening a file that does not exist
confirm-nonexistent-file-or-buffer t
;; Do not require double space to end a sentence.
sentence-end-double-space nil
;; Show trailing whitespace
show-trailing-whitespace t
;; Remove the line when killing it with ctrl-k
kill-whole-line t
)
;; (setq-default fringes-outside-margins t)
;; Per-pixel scrolling instead of per-line
(pixel-scroll-precision-mode)
;; Typed text replaces selection
(delete-selection-mode)
;; Delete trailing whitespace before save
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;; If the underlying file changes, reload it automatically. This is useful for moving around in git without confusing language servers.
(setopt auto-revert-avoid-polling t)
(setopt auto-revert-interval 5)
(setopt auto-revert-check-vc-info t)
(global-auto-revert-mode)
;;;;; Performance
;; Run garbage collect when emacs is idle
(run-with-idle-timer 5 t (lambda () (garbage-collect)))
(add-function :after after-focus-change-function
(lambda ()
(unless (frame-focus-state)
(garbage-collect))))
(provide 'base)

View File

@@ -0,0 +1,47 @@
(use-package eglot
:pin gnu
:commands (eglot eglot-ensure)
:bind (:map eglot-mode-map
;; M-.
;; ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
;; M-?
;; ([remap xref-find-references] . lsp-ui-peek-find-references)
("C-c C-a" . eglot-code-actions)
;; C-M-.
([remap xref-find-apropos] . #'consult-eglot-symbols)
)
;; :hook (
;; (eglot-managed-mode . (lambda ()
;; (when (eglot-managed-p)
;; (corfu-mode +1)
;; )
;; ))
;; )
:config
(fset #'jsonrpc--log-event #'ignore) ;; Disable logging LSP traffic for performance boost
(set-face-attribute 'eglot-highlight-symbol-face nil :background "#0291a1" :foreground "black")
(set-face-attribute 'eglot-mode-line nil :inherit 'mode-line :bold nil)
:custom
(eglot-autoshutdown t "Shut down server when last buffer is killed.")
(eglot-sync-connect 0 "Don't block on language server starting.")
(eglot-send-changes-idle-time 0.1)
)
(use-package consult-eglot
:commands (consult-eglot-symbols)
)
(use-package company
:after eglot
:hook (eglot-managed-mode . company-mode)
:config
(setq company-backends '((company-capf)))
(setq company-idle-delay 0) ;; Default 0.2
)
;; (use-package company-box
;; :hook (company-mode . company-box-mode))
(provide 'common-lsp)

View File

@@ -0,0 +1,16 @@
(require 'util-tree-sitter)
(use-package bash-ts-mode
:ensure nil
:commands (bash-ts-mode)
:hook (
(bash-ts-mode . (lambda ()
(flymake-mode +1)
)))
:init
(add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode))
(add-to-list 'treesit-language-source-alist '(bash "https://github.com/tree-sitter/tree-sitter-bash"))
(unless (treesit-ready-p 'bash) (treesit-install-language-grammar 'bash))
)
(provide 'lang-bash)

View File

@@ -0,0 +1,49 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun locate-compile-commands-file ()
"See if compile_commands.json exists."
;; This can be generated by prefixing the make command with `intercept-build15 --append`
(let ((compile-commands-file (locate-dominating-file (buffer-file-name) "compile_commands.json")))
compile-commands-file
)
)
(defun activate-c-eglot ()
"Activate eglot for the c family of languages."
(when (locate-compile-commands-file)
(eglot-ensure)
(defclass my/eglot-c (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(c-ts-mode . (my/eglot-c "/usr/local/bin/clangd15")))
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
)
)
(use-package c-mode
:mode (
("\\.c\\'" . c-ts-mode)
("\\.h\\'" . c-or-c++-ts-mode)
)
:commands (c-mode c-ts-mode)
:pin manual
:ensure nil
:hook (
(c-ts-mode . (lambda ()
(activate-c-eglot)
))
)
:init
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
(add-to-list 'major-mode-remap-alist '(c-or-c++-mode . c-or-c++-ts-mode))
(add-to-list 'treesit-language-source-alist '(c "https://github.com/tree-sitter/tree-sitter-c"))
(add-to-list 'treesit-language-source-alist '(cpp "https://github.com/tree-sitter/tree-sitter-cpp"))
(unless (treesit-ready-p 'c) (treesit-install-language-grammar 'c))
(unless (treesit-ready-p 'cpp) (treesit-install-language-grammar 'cpp))
)
(provide 'lang-c)

View File

@@ -0,0 +1,13 @@
(use-package dockerfile-ts-mode
:pin manual
:mode (
("Dockerfile\\'" . dockerfile-ts-mode)
)
:commands (dockerfile-mode dockerfile-ts-mode)
:init
(add-to-list 'major-mode-remap-alist '(dockerfile-mode . dockerfile-ts-mode))
(add-to-list 'treesit-language-source-alist '(dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile"))
(unless (treesit-ready-p 'dockerfile) (treesit-install-language-grammar 'dockerfile))
)
(provide 'lang-dockerfile)

View File

@@ -0,0 +1,33 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(use-package go-ts-mode
:pin manual
:mode (
("\\.go\\'" . go-ts-mode)
("/go\\.mod\\'" . go-mod-ts-mode)
)
:commands (go-ts-mode go-mod-ts-mode)
:hook (
(go-ts-mode . (lambda ()
(when-linux
(eglot-ensure)
)
))
(go-mod-ts-mode . (lambda ()
(when-linux
(eglot-ensure)
)
))
;; (before-save . lsp-format-buffer)
)
:init
(add-to-list 'treesit-language-source-alist '(go "https://github.com/tree-sitter/tree-sitter-go"))
(add-to-list 'treesit-language-source-alist '(gomod "https://github.com/camdencheek/tree-sitter-go-mod"))
(unless (treesit-ready-p 'go) (treesit-install-language-grammar 'go))
(unless (treesit-ready-p 'gomod) (treesit-install-language-grammar 'gomod))
)
(provide 'lang-go)

View File

@@ -0,0 +1,177 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(use-package json-ts-mode
:ensure nil
:pin manual
:mode (
("\\.json\\'" . json-ts-mode)
)
:commands (json-ts-mode)
:hook (
(json-ts-mode . (lambda ()
(add-hook 'before-save-hook 'json-fmt-jq nil 'local)
))
)
:init
(add-to-list 'treesit-language-source-alist '(json "https://github.com/tree-sitter/tree-sitter-json"))
(unless (treesit-ready-p 'json) (treesit-install-language-grammar 'json))
)
(defun json-fmt-jq ()
"Run jq."
(run-command-on-buffer "jq" "--monochrome-output" ".")
)
(defun configure-typescript-language-server ()
"Configures the typescript language server."
(when-linux
;; Either initializationOptions or workspace/didChangeConfiguration works.
(setq eglot-workspace-configuration
(list (cons ':typescript '(:inlayHints (:includeInlayParameterNameHints
"all"
:includeInlayParameterNameHintsWhenArgumentMatchesName
t
:includeInlayFunctionParameterTypeHints
t
:includeInlayVariableTypeHints
t
:includeInlayVariableTypeHintsWhenTypeMatchesName
t
:includeInlayPRopertyDeclarationTypeHints
t
:includeInlayFunctionLikeReturnTypeHints
t
:includeInlayEnumMemberValueHints
t)))))
(eglot-ensure)
;; (defclass my/eglot-typescript (eglot-lsp-server) ()
;; :documentation
;; "Own eglot server class.")
;; (add-to-list 'eglot-server-programs
;; '((js-mode js-ts-mode tsx-ts-mode typescript-ts-mode typescript-mode) . (my/eglot-typescript "typescript-language-server" "--stdio" :initializationOptions (:preferences (:includeInlayParameterNameHints
;; "all"
;; :includeInlayParameterNameHintsWhenArgumentMatchesName
;; t
;; :includeInlayFunctionParameterTypeHints
;; t
;; :includeInlayVariableTypeHints
;; t
;; :includeInlayVariableTypeHintsWhenTypeMatchesName
;; t
;; :includeInlayPRopertyDeclarationTypeHints
;; t
;; :includeInlayFunctionLikeReturnTypeHints
;; t
;; :includeInlayEnumMemberValueHints
;; t)))))
)
)
(use-package tsx-ts-mode
:ensure nil
:pin manual
:mode (
("\\.tsx\\'" . tsx-ts-mode)
)
:commands (tsx-ts-mode)
:hook (
(tsx-ts-mode . (lambda ()
(when-linux
(configure-typescript-language-server)
)
))
)
:init
(add-to-list 'treesit-language-source-alist '(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")))
(unless (treesit-ready-p 'tsx) (treesit-install-language-grammar 'tsx))
)
(use-package typescript-ts-mode
:ensure nil
:pin manual
:mode (
("\\.ts\\'" . typescript-ts-mode)
)
:commands (typescript-ts-mode)
:hook (
(typescript-ts-mode . (lambda ()
(configure-typescript-language-server)
))
)
:init
(add-to-list 'treesit-language-source-alist '(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")))
(unless (treesit-ready-p 'typescript) (treesit-install-language-grammar 'typescript))
)
(use-package js-ts-mode
:ensure nil
:pin manual
:mode (
("\\.js\\'" . js-ts-mode)
)
:commands (js-ts-mode)
:hook (
(js-ts-mode . (lambda ()
(when-linux
(eglot-ensure)
)
))
)
:init
(add-to-list 'treesit-language-source-alist '(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")))
(unless (treesit-ready-p 'javascript) (treesit-install-language-grammar 'javascript))
)
(defun prettier-fmt ()
"Run prettier."
(run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name)
)
(use-package css-ts-mode
:ensure nil
:pin manual
:mode (
("\\.css\\'" . css-ts-mode)
)
:commands (css-ts-mode)
:custom (css-indent-offset 2)
:init
(add-to-list 'treesit-language-source-alist '(css "https://github.com/tree-sitter/tree-sitter-css"))
(unless (treesit-ready-p 'css) (treesit-install-language-grammar 'css))
:hook (
(css-ts-mode . (lambda ()
(eglot-ensure)
(defclass my/eglot-css (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(css-ts-mode . (my/eglot-css "vscode-css-language-server" "--stdio")))
;; (add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
(add-hook 'before-save-hook 'prettier-fmt nil 'local)
))
)
)
(use-package web-mode
:mode (("\\.dust\\'" . dust-mode)
)
:config
(setq web-mode-markup-indent-offset 2)
(setq web-mode-enable-current-element-highlight t)
)
;; Define a custom mode for dust so that org-mode handle #+BEGIN_SRC dust blocks
(define-derived-mode dust-mode web-mode "WebDust"
"Major mode for editing dust templates in web-mode."
(web-mode)
(web-mode-set-engine "dust")
;; (setq web-mode-content-type "html")
)
(provide 'lang-javascript)

View File

@@ -0,0 +1,21 @@
(defun lua-format-buffer ()
"Run stylua."
(interactive)
(run-command-on-buffer "stylua" "--search-parent-directories" "--stdin-filepath" buffer-file-name "-")
)
(use-package lua-mode
:mode
(("\\.lua\\'" . lua-mode)
("\\.rockspec\\'" . lua-mode))
:commands lua-mode
:hook (
(lua-mode . (lambda ()
(add-hook 'before-save-hook 'lua-format-buffer nil 'local)
))
)
:custom
(lua-indent-level 4)
)
(provide 'lang-lua)

View File

@@ -0,0 +1,14 @@
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown"))
;; For code block editing
(use-package edit-indirect
:commands (edit-indirect-region edit-indirect-save edit-indirect-abort edit-indirect-commit edit-indirect-display-active-buffer)
)
(provide 'lang-markdown)

View File

@@ -0,0 +1,22 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(use-package nix-mode
:mode (("\\.nix\\'" . nix-mode)
)
:commands nix-mode
:hook (
(nix-mode . (lambda ()
(eglot-ensure)
(defclass my/eglot-nix (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(nix-mode . (my/eglot-nix "nixd")))
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
))
)
)
(provide 'lang-nix)

View File

@@ -0,0 +1,81 @@
(use-package org
:ensure nil
:commands org-mode
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C--" . org-timestamp-down)
("C-=" . org-timestamp-up)
)
:hook (
(org-mode . (lambda ()
(org-indent-mode +1)
))
)
:config
(require 'org-tempo)
(setq org-export-latex-listings t)
(setq org-startup-truncated nil)
(setq org-startup-folded nil)
(setq org-src-fontify-natively t
org-src-tab-acts-natively t
org-confirm-babel-evaluate nil
)
;; Show the full source of org-mode links instead of condensing them. I.E. render "[[foo]]" instead of "foo"
(setq org-descriptive-links nil)
;; Only interpret _ and ^ and sub and superscripts if they're of the form _{subscript} and ^{superscript}
(setq org-export-with-sub-superscripts '{})
;; Don't include a "validate" link at the bottom of html export
(setq org-html-validation-link nil)
(setq org-latex-listings 'minted)
(setq org-latex-minted-options '(("breaklines" "true")
("breakanywhere" "true")
("bgcolor" "mintedbg") ("frame" "single") ("framesep" "6pt") ("fontsize" "\\footnotesize")))
;; TODO: There is an option to set the compiler, could be better than manually doing this here https://orgmode.org/manual/LaTeX_002fPDF-export-commands.html
;; (setq org-latex-compiler "lualatex")
(setq org-latex-pdf-process
'("lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
(add-to-list 'org-latex-packages-alist '("cache=false" "minted"))
(add-to-list 'org-latex-packages-alist '("" "svg"))
(add-to-list 'org-latex-packages-alist '("margin=2cm" "geometry" nil))
(add-to-list 'org-src-lang-modes '("dot" . "graphviz-dot"))
(org-babel-do-load-languages 'org-babel-load-languages
'((shell . t)
(js . t)
(emacs-lisp . t)
(python . t)
(dot . t)
(css . t)
(gnuplot . t)
(sqlite . t)
))
(require 'color)
(let ((bg (face-attribute 'default :background)))
(custom-set-faces
`(org-block ((t (:inherit default :background ,(color-lighten-name bg 15) :extend ,t))))
`(org-block-begin-line ((t (:inherit default :background ,"#472300" :extend ,t))))
`(org-block-end-line ((t (:inherit default :background ,"#472300" :extend ,t))))
))
)
(use-package org-bullets
:commands org-bullets-mode
:hook (org-mode . org-bullets-mode)
)
(use-package gnuplot-mode)
(use-package gnuplot)
(use-package graphviz-dot-mode)
(provide 'lang-org)

View File

@@ -0,0 +1,92 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun python-backspace (arg)
"Special handling of python backspace."
(interactive "*p")
(if mark-active
(backward-delete-char-untabify arg)
(python-indent-dedent-line-backspace arg)
)
)
(defun locate-venv-poetry ()
"Find a poetry venv."
(run-command-in-directory nil "poetry" "env" "info" "-p")
)
(defun locate-pyproject-directory ()
"Adapt lsp-python-ms for poetry."
(let ((pypoetry-file (locate-dominating-file (buffer-file-name) "pyproject.toml")))
pypoetry-file
)
)
(defun python-fmt ()
"format python."
(python-fmt-black)
(python-fmt-isort)
)
(defun python-fmt-black ()
"Run black."
(run-command-on-buffer "black" "--quiet" "--fast" "-")
)
(defun python-fmt-isort ()
"Run isort."
(run-command-on-buffer "isort" "-")
)
(defun add-poetry-venv-to-path ()
"Add the bin folder in the poetry venv to exec-path."
(let (
(venv-path (locate-venv-poetry))
)
(when venv-path
(make-local-variable 'exec-path)
(add-to-list 'exec-path (concat venv-path "/bin"))
)
)
)
(use-package python
:mode ("\\.py\\'" . python-ts-mode)
:commands (python-mode python-ts-mode)
:pin manual
:hook (
(python-ts-mode . (lambda ()
(when-linux
(when (executable-find "poetry")
(add-poetry-venv-to-path)
(let ((venv (locate-venv-poetry))) (when venv
(setq eglot-workspace-configuration
(list (cons ':python (list ':venvPath venv ':pythonPath (concat venv "/bin/python")))))
))
)
(eglot-ensure)
)
;; (when-freebsd
;; (eglot-ensure)
;; (defclass my/eglot-pylyzer (eglot-lsp-server) ()
;; :documentation
;; "Own eglot server class.")
;; (add-to-list 'eglot-server-programs
;; '(python-ts-mode . (my/eglot-pylyzer "pylyzer" "--server")))
;; )
(add-hook 'before-save-hook 'python-fmt nil 'local)
))
)
:bind ((:map python-ts-mode-map ([backspace] . python-backspace))
)
:init
(add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
(add-to-list 'treesit-language-source-alist '(python "https://github.com/tree-sitter/tree-sitter-python"))
(unless (treesit-ready-p 'python) (treesit-install-language-grammar 'python))
)
(provide 'lang-python)

View File

@@ -0,0 +1,92 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun locate-rust-analyzer ()
"Find rust-analyzer."
(let ((rust-analyzer-paths (list (locate-rust-analyzer-rustup) (locate-rust-analyzer-ansible-built) (locate-rust-analyzer-in-path))))
(let ((first-non-nil-path (seq-find (lambda (elt) elt) rust-analyzer-paths)))
first-non-nil-path
)
)
)
(defun locate-rust-analyzer-rustup ()
"Find rust-analyzer through rustup."
(run-command-in-directory nil "rustup" "which" "rust-analyzer")
)
(defun locate-rust-analyzer-ansible-built ()
"Find rust-analyzer where the ansible playbook built it."
(let ((rust-analyzer-path "/opt/rust-analyzer/target/release/rust-analyzer"))
(when (file-exists-p rust-analyzer-path)
rust-analyzer-path
)
)
)
(defun locate-rust-analyzer-in-path ()
"Find rust-analyzer in $PATH."
(executable-find "rust-analyzer")
)
(use-package rust-ts-mode
:pin manual
:mode (
("\\.rs\\'" . rust-ts-mode)
)
:commands (rust-ts-mode)
:hook (
(rust-ts-mode . (lambda ()
(eglot-ensure)
;; Disable on-type formatting which was incorrectly injecting parenthesis into my code.
(make-local-variable 'eglot-ignored-server-capabilities)
(add-to-list 'eglot-ignored-server-capabilities :documentOnTypeFormattingProvider)
;; Configure initialization options
(let ((rust-analyzer-command (locate-rust-analyzer)))
(when rust-analyzer-command
;; (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command)))
(add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command :initializationOptions (:imports (:granularity (:enforce t :group "item")
:merge (:glob nil)
:prefix "self")
))))
)
)
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
))
)
:init
(add-to-list 'major-mode-remap-alist '(rust-mode . rust-ts-mode))
(add-to-list 'treesit-language-source-alist '(rust "https://github.com/tree-sitter/tree-sitter-rust"))
(unless (treesit-ready-p 'rust) (treesit-install-language-grammar 'rust))
:config
;; Add keybindings for interacting with Cargo
(use-package cargo
:hook (rust-ts-mode . cargo-minor-mode))
)
(use-package toml-ts-mode
:ensure nil
:pin manual
:mode (
("\\.toml\\'" . toml-ts-mode)
)
:commands (toml-ts-mode)
:init
(add-to-list 'treesit-language-source-alist '(toml "https://github.com/tree-sitter/tree-sitter-toml"))
(unless (treesit-ready-p 'toml) (treesit-install-language-grammar 'toml))
)
;; Set additional rust-analyzer settings:
;;
;; (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command :initializationOptions (:cargo (:features "all")))))
;;
;; In addition to the above, directory-specific settings can be written to a .dir-locals.el with the contents:
;;
;; (
;; (rust-ts-mode . ((eglot-workspace-configuration
;; . (:rust-analyzer (:cargo (:noDefaultFeatures t :features ["compare" "tracing"]))))
;; ))
;; )
(provide 'lang-rust)

View File

@@ -0,0 +1,38 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun terraform-fmt ()
"Run terraform fmt."
(run-command-on-buffer "terraform" "fmt" "-")
)
(use-package hcl-mode
:mode (("\\.hcl\\'" . hcl-mode))
:commands hcl-mode
:custom (hcl-indent-level 2)
:hook (
(hcl-mode . (lambda () (unless (derived-mode-p 'terraform-mode) (add-hook 'before-save-hook 'terraform-fmt nil 'local))))
)
)
(use-package terraform-mode
:mode (("\\.tf\\'" . terraform-mode)
("\\.tfvars\\'" . terraform-mode))
:commands terraform-mode
:custom (terraform-indent-level 2)
:hook (
(terraform-mode . (lambda ()
(eglot-ensure)
(defclass my/eglot-terraform (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(terraform-mode . (my/eglot-terraform "terraform-ls" "serve")))
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
))
)
)
(provide 'lang-terraform)

View File

@@ -0,0 +1,17 @@
(defun xml-fmt ()
"Run xmllint --format."
(run-command-on-buffer "xmllint" "--format" "-")
)
(use-package nxml-mode
:commands (nxml-mode)
:pin manual
:ensure nil
:hook (
(nxml-mode . (lambda ()
(add-hook 'before-save-hook 'xml-fmt nil 'local)
))
)
)
(provide 'lang-xml)

View File

@@ -0,0 +1,27 @@
(defun yaml-format-buffer ()
"Run prettier."
(interactive)
(run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name)
)
(use-package yaml-ts-mode
:mode
(
("\\.y[a]?ml\\'" . yaml-ts-mode)
("playbook\\.tmp\\'" . yaml-ts-mode)
("environments/[^/]*/group_vars/[^/]*\\'" . yaml-ts-mode)
("environments/[^/]*/host_vars/[^/]*\\'" . yaml-ts-mode)
)
:commands (yaml-ts-mode)
:hook (
(yaml-ts-mode . (lambda ()
(add-hook 'before-save-hook 'yaml-format-buffer nil 'local)
))
)
:init
(add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode))
(add-to-list 'treesit-language-source-alist '(yaml "https://github.com/ikatyang/tree-sitter-yaml"))
(unless (treesit-ready-p 'yaml) (treesit-install-language-grammar 'yaml))
)
(provide 'lang-yaml)

View File

@@ -0,0 +1,10 @@
(use-package flymake
:pin manual
:ensure nil
:commands (flymake-mode)
:config
;; Set the text before the brackets for flymake's modeline output to an empty string to make it less verbose.
(setq flymake-mode-line-lighter "")
)
(provide 'util-flymake)

View File

@@ -0,0 +1,16 @@
(use-package treesit
:pin manual
:ensure nil
:commands (treesit-install-language-grammar treesit-ready-p)
:init
(setq treesit-language-source-alist '())
:config
;; Default to the max level of detail in treesitter highlighting. This
;; can be overridden in each language's use-package call with:
;;
;; :custom
;; (treesit-font-lock-level 3)
(setq treesit-font-lock-level 4)
)
(provide 'util-tree-sitter)

View File

@@ -0,0 +1,61 @@
(defun my/minibuffer-delete (arg)
"When looking for files, go up an entire directory with the backspace button if theres no text after the directory."
(interactive "p")
(if minibuffer-completing-file-name
(if (string-match-p ".*/$" (minibuffer-contents))
(vertico-directory-delete-word arg)
(vertico-directory-delete-char arg))
(delete-backward-char arg)))
(use-package vertico
:config
(vertico-mode)
(vertico-mouse-mode)
;; Remove prefix when switching to tilde or root ("/")
(setq file-name-shadow-properties '(invisible t intangible t))
(file-name-shadow-mode +1)
(set-face-attribute 'vertico-current nil :inherit nil :background "#383b01")
:custom
(vertico-count 20)
)
;; Create an ido/ivy-like experience when selecting files.
(use-package vertico-directory
:after vertico
:ensure nil
:bind ( :map vertico-map
("RET" . vertico-directory-enter)
:map minibuffer-local-map
("DEL" . my/minibuffer-delete)
)
)
(use-package consult
:custom
(completion-in-region-function #'consult-completion-in-region)
(xref-show-xrefs-function #'consult-xref)
(xref-show-definitions-function #'consult-xref)
(consult-project-root-function #'deadgrep--project-root)
:bind (
("C-. s" . consult-ripgrep)
("C-s" . consult-line)
("M-g g" . consult-goto-line)
("C-. e" . consult-flymake)
)
)
;; (use-package corfu
;; :commands (corfu-mode global-corfu-mode)
;; :custom
;; (corfu-auto t)
;; )
(use-package marginalia
:config (marginalia-mode))
(use-package orderless
:custom (completion-styles '(orderless)))
(provide 'util-vertico)

View File

@@ -0,0 +1,41 @@
(add-to-list 'load-path (concat user-emacs-directory "elisp"))
(require 'base)
(require 'base-theme)
(require 'base-extensions)
(require 'base-functions)
(require 'base-global-keys)
(require 'util-vertico)
(require 'util-flymake)
(require 'lang-python)
(require 'lang-javascript)
(require 'lang-rust)
(require 'lang-yaml)
(require 'lang-org)
(require 'lang-bash)
(require 'lang-markdown)
(require 'lang-lua)
(require 'lang-terraform)
(require 'lang-go)
(require 'lang-dockerfile)
(require 'lang-c)
(require 'lang-xml)
(require 'lang-nix)
(load-directory autoload-directory)

View File

@@ -0,0 +1,97 @@
{ config, lib, pkgs, ... }:
{
imports = [];
programs.firefox = {
enable = true;
package = (pkgs.wrapFirefox (pkgs.firefox-unwrapped.override { pipewireSupport = true;}) {});
languagePacks = [ "en-US" ];
preferences = {
# "identity.sync.tokenserver.uri": "https://ffsync.fizz.buzz/token/1.0/sync/1.5";
"media.hardware-video-decoding.force-enabled" = true;
"media.ffmpeg.vaapi.enabled" = true;
"doh-rollout.doorhanger-decision" = "UIDisabled";
"dom.security.https_only_mode" = true;
"dom.security.https_only_mode_ever_enabled" = true;
"extensions.activeThemeID" = "firefox-compact-dark@mozilla.org";
# Disable ads
"extensions.pocket.enabled" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.pinned" = "[]";
"browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
"browser.topsites.contile.enabled" = false;
# Disable cache when devtools are open.
"devtools.cache.disabled" = true;
# Do not track header.
"privacy.donottrackheader.enabled" = true;
# Tell websites not to share or sell my data.
"privacy.globalprivacycontrol.enabled" = true;
# Disable "studies" (slice testing)
"app.shield.optoutstudies.enabled" = false;
# Disable attribution which is used by advertisers to track you.
"dom.private-attribution.submission.enabled" = false;
# Disable battery status, used to track users.
"dom.battery.enabled" = false;
# Disable that websites can get notifications if you copy, paste, or cut something from a web page, and it lets them know which part of the page had been selected.
#
# This breaks copying from BigQuery https://github.com/microsoft/monaco-editor/issues/1540
# dom.event.clipboardevents.enabled: false
# Isolates all browser identifier sources (e.g. cookies) to the first party domain, with the goal of preventing tracking across different domains.
"privacy.firstparty.isolate" = true;
# Do not preload URLs that auto-complete in the address bar.
"browser.urlbar.speculativeConnect.enabled" = false;
# Do not resist fingerprinting because that tells websites to use light mode.
# https://bugzilla.mozilla.org/show_bug.cgi?id=1732114
"privacy.resistFingerprinting" = false; # (default false)
# Instead, enable fingerprinting protection, which allows configuring an override.
"privacy.fingerprintingProtection" = true;
# Allow sending dark mode preference to websites.
# Allow sending timezone to websites.
"privacy.fingerprintingProtection.overrides" = "+AllTargets,-CSSPrefersColorScheme,-JSDateTimeUTC,-CanvasExtractionBeforeUserInputIsBlocked";
# Disable weather on new tab page
"browser.newtabpage.activity-stream.showWeather" = false;
};
# Check about:policies#documentation and https://mozilla.github.io/policy-templates/ for options.
policies = {
DisableTelemetry = true;
DisplayBookmarksToolbar = "newtab";
# Check about:support for extension/add-on ID strings.
# Valid strings for installation_mode are "allowed", "blocked",
# "force_installed" and "normal_installed".
ExtensionSettings = {
# "*".installation_mode = "blocked"; # blocks all addons except the ones specified below
"uBlock0@raymondhill.net" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi";
installation_mode = "force_installed";
};
"firefox@teleparty.com" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/netflix-party-is-now-teleparty/latest.xpi";
installation_mode = "normal_installed";
};
};
};
};
environment.persistence."/persist" = {
hideMounts = true;
users.talexander = {
directories = [
{ directory = ".mozilla"; user = "talexander"; group = "talexander"; mode = "0700"; }
];
};
};
environment.persistence."/state" = {
hideMounts = true;
users.talexander = {
directories = [
{ directory = ".cache/mozilla"; user = "talexander"; group = "talexander"; mode = "0700"; }
];
};
};
}

View File

@@ -0,0 +1,15 @@
{ config, lib, pkgs, ... }:
{
imports = [];
# Open ports in the firewall.
networking.firewall.allowedTCPPorts = [
22 # ssh
];
networking.firewall.allowedUDPPorts = [
5353 # mDNS
];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
}

View File

@@ -0,0 +1,118 @@
{ config, lib, pkgs, ... }:
{
imports = [];
fonts = {
enableDefaultPackages = true;
packages = with pkgs; [
cascadia-code
source-sans-pro
source-serif-pro
];
fontconfig = {
localConf = ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!-- reject all bitmap fonts, with the exception of 'terminus' -->
<selectfont>
<!-- <acceptfont> -->
<!-- <pattern> -->
<!-- <patelt name="family"> <string>Terminus</string> </patelt> -->
<!-- </pattern> -->
<!-- </acceptfont> -->
<rejectfont>
<pattern>
<patelt name="scalable"> <bool>false</bool> </patelt>
</pattern>
</rejectfont>
<rejectfont>
<!-- You don't want ghostscript fonts in your web browsing because of annoying ligatures like ffi -->
<glob>/usr/share/fonts/gsfonts/*</glob>
</rejectfont>
</selectfont>
<!-- preferred aliases -->
<alias>
<family>serif</family>
<prefer>
<family>Source Serif Pro</family>
<family>Source Sans Pro</family>
</prefer>
</alias>
<!-- preferred aliases -->
<alias>
<family>sans-serif</family>
<prefer>
<family>Source Sans Pro</family>
<family>Source Serif Pro</family>
</prefer>
</alias>
<!-- preferred aliases -->
<alias>
<family>monospace</family>
<prefer>
<family>Cascadia Mono</family>
<family>Cascadia Code</family>
</prefer>
</alias>
<!-- Screw it. Force Liberation Mono to be source code pro. -->
<match target="pattern">
<test qual="any" name="family"><string>Liberation Mono</string></test>
<edit name="family" mode="assign" binding="same"><string>Cascadia Mono</string></edit>
</match>
<!-- Dejavu Sans Mono keeps coming back when I query "monospace". Doesn't happen when I'm using Souce Code Pro but does happen with cascadia... force it to cascadia -->
<match target="pattern">
<test qual="any" name="family"><string>monospace</string></test>
<edit name="family" mode="assign" binding="same"><string>Cascadia Mono</string></edit>
</match>
<!-- Disable ligatures in monospace fonts. -->
<match target="font">
<test name="family" compare="eq" ignore-blanks="true">
<string>Cascadia Code</string>
</test>
<edit name="fontfeatures" mode="append">
<string>liga off</string>
<string>dlig off</string>
</edit>
</match>
<!-- Font Display Settings -->
<match target="font" >
<edit mode="assign" name="rgba" >
<const>rgb</const>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="hinting" >
<bool>true</bool>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="hintstyle" >
<const>hintslight</const>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="antialias" >
<bool>true</bool>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="lcdfilter" >
<const>lcddefault</const>
</edit>
</match>
</fontconfig>
'';
};
};
}

View File

@@ -0,0 +1,15 @@
{ config, lib, pkgs, ... }:
{
imports = [];
environment.systemPackages = with pkgs; [
git
];
home-manager.users.talexander = { pkgs, ... }: {
home.file.".gitconfig" = {
source = ./files/gitconfig_home;
};
};
}

View File

@@ -0,0 +1,35 @@
[user]
email = tom@fizz.buzz
name = Tom Alexander
signingkey = D3A179C9A53C0EDE
[push]
default = simple
[alias]
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
bh = log --oneline --branches=* --remotes=* --graph --decorate
amend = commit --amend --no-edit
[core]
excludesfile = ~/.gitignore_global
[commit]
gpgsign = true
[pull]
rebase = true
[log]
date = local
[init]
defaultBranch = main
# Use meld for `git difftool` and `git mergetool`
[diff]
tool = meld
[difftool]
prompt = false
[difftool "meld"]
cmd = meld "$LOCAL" "$REMOTE"
[merge]
tool = meld
[mergetool "meld"]
# Make the middle pane start with partially-merged contents:
cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
# Make the middle pane start without any merge progress:
# cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"

View File

@@ -0,0 +1,25 @@
{ config, lib, pkgs, ... }:
{
imports = [];
# Fetch public keys:
# gpg --locate-keys tom@fizz.buzz
#
# gpg -vvv --auto-key-locate local,wkd --locate-keys tom@fizz.buzz
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
environment.persistence."/persist" = {
hideMounts = true;
users.talexander = {
directories = [
{ directory = ".gnupg"; user = "talexander"; group = "talexander"; mode = "0700"; } # Local keyring
];
};
};
}

View File

@@ -0,0 +1,7 @@
{ config, lib, pkgs, ... }:
{
imports = [];
hardware.graphics.enable = true;
}

View File

@@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
imports = [];
# Reset some defaults to start from a minimal more-arch-linux-like state. Think of this like a CSS reset sheet.
}

View File

@@ -0,0 +1,20 @@
{ config, lib, pkgs, ... }:
{
imports = [];
environment.systemPackages = with pkgs; [
pavucontrol
];
# rtkit is optional but recommended
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
};
}

View File

@@ -0,0 +1,250 @@
{ config, lib, pkgs, ... }:
let
sway-config = pkgs.writeTextFile {
name = "config";
text = ''
# Default config for sway
#
# Copy this to ~/.config/sway/config and edit it to your liking.
#
# Read `man 5 sway` for a complete reference.
### Variables
#
# Logo key. Use Mod1 for Alt.
set $mod Mod4
# set $mod Mod1
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term ${pkgs.alacritty}/bin/alacritty
# Your preferred application launcher
# Note: it's recommended that you pass the final command to sway
# set $menu dmenu_path | dmenu | xargs swaymsg exec
set $menu ${pkgs.wofi}/bin/wofi --show drun --gtk-dark
# Do not show a title bar on windows
default_border pixel 2
bindsym $mod+grave exec $term
include ${base-hotkeys}
include ${display-configs}
include ${window-management}
include ${movement}
include ${disable-focus-follows-mouse}
include ~/.config/sway/config.d/*.conf
include /etc/sway/config.d/*
'';
};
base-hotkeys = pkgs.writeTextFile {
name = "base-hotkeys.conf";
text = ''
### Key bindings
#
# Basics:
#
# kill focused window
bindsym $mod+Shift+q kill
# start your launcher
bindsym $mod+Return exec $menu
# Drag floating windows by holding down $mod and left mouse button.
# Resize them with right mouse button + $mod.
# Despite the name, also works for non-floating windows.
# Change normal to inverse to use left mouse button for resizing and right
# mouse button for dragging.
floating_modifier $mod normal
# reload the configuration file
bindsym $mod+Shift+c reload
# exit sway (logs you out of your Wayland session)
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
'';
};
display-configs = pkgs.writeTextFile {
name = "display-configs.conf";
text = ''
output 'Unknown 0x095F 0x00000000' scale 1.5
output 'BOE 0x095F Unknown' scale 1.5
output 'BOE 0x0BCA Unknown' scale 1.5
'';
};
window-management = pkgs.writeTextFile {
name = "window-management.conf";
text = ''
#
# Layout stuff:
#
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
bindsym $mod+h splith
bindsym $mod+v splitv
# Switch the current container between different layout styles
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# Make the current focus fullscreen
bindsym $mod+f fullscreen
# Toggle the current focus between tiling and floating mode
bindsym $mod+Shift+space floating toggle
# Swap focus between the tiling area and the floating area
bindsym $mod+space focus mode_toggle
# move focus to the parent container
bindsym $mod+a focus parent
#
# Scratchpad:
#
# Sway has a "scratchpad", which is a bag of holding for windows.
# You can send windows there and get them back later.
# Move the currently focused window to the scratchpad
bindsym $mod+Shift+minus move scratchpad
# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
bindsym $left resize shrink width 10px
bindsym $down resize grow height 10px
bindsym $up resize shrink height 10px
bindsym $right resize grow width 10px
# ditto, with arrow keys
bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px
# return to default mode
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
'';
};
movement = pkgs.writeTextFile {
name = "movement.conf";
text = ''
#
# Moving around:
#
# Move your focus around
# bindsym $mod+$left focus left
# bindsym $mod+$down focus down
# bindsym $mod+$up focus up
# bindsym $mod+$right focus right
# or use $mod+[up|down|left|right]
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
# _move_ the focused window with the same, but add Shift
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
# ditto, with arrow keys
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
#
# Workspaces:
#
# switch to workspace
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
bindsym $mod+4 workspace 4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace 7
bindsym $mod+8 workspace 8
bindsym $mod+9 workspace 9
bindsym $mod+0 workspace 10
# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace 1
bindsym $mod+Shift+2 move container to workspace 2
bindsym $mod+Shift+3 move container to workspace 3
bindsym $mod+Shift+4 move container to workspace 4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace 7
bindsym $mod+Shift+8 move container to workspace 8
bindsym $mod+Shift+9 move container to workspace 9
bindsym $mod+Shift+0 move container to workspace 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
'';
};
disable-focus-follows-mouse = pkgs.writeTextFile {
name = "disable-focus-follows-mouse.conf";
text = ''
# Disable focus following mouse
focus_follows_mouse no
'';
};
in
{
imports = [];
environment.systemPackages = with pkgs; [
alacritty
pcmanfm
];
environment.sessionVariables = {
WLR_RENDERER_ALLOW_SOFTWARE = "1";
};
programs.sway = {
enable = true;
wrapperFeatures.gtk = true;
extraOptions = [
"--debug"
"--config"
"${sway-config}"
"--unsupported-gpu"
];
};
environment.persistence."/state" = {
hideMounts = true;
users.talexander = {
files = [
".cache/wofi-drun" # Execution history for wofi to sort results
];
};
};
xdg = {
portal = {
enable = true;
extraPortals = with pkgs; [
xdg-desktop-portal-wlr
xdg-desktop-portal-gtk
];
};
};
}

16
nix/configuration/zfs.nix Normal file
View File

@@ -0,0 +1,16 @@
{ config, lib, pkgs, ... }:
{
imports = [];
boot.zfs.devNodes = "/dev/disk/by-partuuid";
services.zfs = {
autoScrub = {
enable = true;
interval = "monthly";
};
trim.enable = true;
};
}

113
nix/virtual_machine/nix_vm.bash Executable file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/env bash
#
# Manage a nix vm for testing.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
: ${VM_ROOT_ZFS:="zroot/linux/archmain/vm/nix"}
: ${VM_ROOT_MOUNT:="/vm/nix"}
: ${VM_DISK_SIZE:="100G"}
# Manual Steps:
#
# Download the nixos livecd from https://channels.nixos.org/nixos-24.11/latest-nixos-gnome-x86_64-linux.iso
############## Setup #########################
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
local cmd="$1"
shift 1
if [ "$cmd" = "init" ]; then
vm_init "${@}"
elif [ "$cmd" = "install" ]; then
vm_install "${@}"
elif [ "$cmd" = "run" ]; then
vm_run "${@}"
elif [ "$cmd" = "iso_ssh" ]; then
vm_iso_ssh "${@}"
elif [ "$cmd" = "iso_sync" ]; then
vm_iso_sync "${@}"
elif [ "$cmd" = "ssh" ]; then
vm_ssh "${@}"
elif [ "$cmd" = "sync" ]; then
vm_sync "${@}"
else
die 1 "Unknown command: $cmd"
fi
}
function vm_init {
zfs create -o mountpoint=none -o canmount=off "$VM_ROOT_ZFS"
zfs create -u -o "mountpoint=$VM_ROOT_MOUNT" -o canmount=on "$VM_ROOT_ZFS/settings"
zfs create -s "-V${VM_DISK_SIZE}" -o volmode=dev -o primarycache=metadata -o secondarycache=none -o volblocksize=64K "${VM_ROOT_ZFS}/disk0"
zfs snapshot -r "$VM_ROOT_ZFS@empty"
zfs mount "$VM_ROOT_ZFS/settings"
# Empty EFI variables
cp /usr/share/edk2/x64/OVMF_VARS.4m.fd "${VM_ROOT_MOUNT}/"
}
function vm_install {
VM_CDROM="$1"
shift 1
vm_run "${@}"
}
function vm_run {
local additional_args=()
if [ -n "${VM_CDROM:-}" ]; then
log "Using CD $VM_CDROM"
additional_args+=("-cdrom" "$VM_CDROM")
fi
exec qemu-system-x86_64 \
-accel kvm \
-cpu host \
-smp cores=8 \
-m 32768 \
-drive file=/usr/share/edk2/x64/OVMF_CODE.4m.fd,if=pflash,format=raw,readonly=on \
-drive if=pflash,format=raw,file="$(readlink -f "${VM_ROOT_MOUNT}/OVMF_VARS.4m.fd")" \
-drive "if=none,file=/dev/zvol/${VM_ROOT_ZFS}/disk0,format=raw,id=hd0" \
-device nvme,serial=deadbeef,drive=hd0 \
-nic user,hostfwd=tcp::60022-:22 \
-boot order=d \
"${additional_args[@]}"
}
function vm_iso_ssh {
exec gpg_auth ssh -p 60022 nixos@127.0.0.1
}
function vm_iso_sync {
gpg_auth rsync -av --delete --progress -e 'ssh -p 60022' "$DIR/../configuration" nixos@127.0.0.1:~/
gpg_auth ssh -p 60022 nixos@127.0.0.1 'sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount ./configuration/hosts/odo/disk-config.nix'
gpg_auth ssh -t -p 60022 nixos@127.0.0.1 sudo nixos-install --flake ./configuration#odovm
}
function vm_ssh {
exec gpg_auth ssh -p 60022 127.0.0.1
}
function vm_sync {
gpg_auth rsync -av --delete --progress -e 'ssh -p 60022' "$DIR/../configuration" 127.0.0.1:~/
gpg_auth ssh -t -p 60022 127.0.0.1 doas nixos-rebuild boot --flake ./configuration#odovm
}
main "${@}"