Compare commits
54 commits
Author | SHA1 | Date | |
---|---|---|---|
b8257363d3 | |||
ffd48fa9ea | |||
332bc9ca76 | |||
d7e64ff1d6 | |||
071577b83d | |||
d066e930a4 | |||
afc03fe0cf | |||
3bdb545681 | |||
0a946e4b70 | |||
5919f10719 | |||
02989b844d | |||
e6a9c3b503 | |||
c08a99f4a4 | |||
1410b20e7d | |||
76119aef0f | |||
db168ad3a4 | |||
16d45d2bc2 | |||
2b4aa8fd66 | |||
0782b0cdba | |||
78b2cc7988 | |||
81099d2644 | |||
feff5a9f1b | |||
64dbffb53f | |||
8c3be332ab | |||
49e6949a20 | |||
c7110cee03 | |||
11e08fc437 | |||
f398775552 | |||
b706942195 | |||
60cd61444e | |||
8415b856a9 | |||
ae41b3ae55 | |||
5247a535b1 | |||
a59a56da09 | |||
91473a3972 | |||
d0e49183a0 | |||
55a7cb8b00 | |||
a646e3e016 | |||
b313f64189 | |||
8af394d0bd | |||
fc7ff7f450 | |||
a66aaef42e | |||
2e7f2257d4 | |||
c911037516 | |||
953383d576 | |||
030e457600 | |||
a1a09c4b17 | |||
7c75d415ff | |||
d427da7804 | |||
1f66bc0a71 | |||
d2cc84899a | |||
048d5e012f | |||
cff0a2cf5b | |||
9b49e2eefa |
49 changed files with 1717 additions and 831 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
configuration.nix
|
21
README.md
Normal file
21
README.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# NixOS config
|
||||
|
||||
NixOS configurations for a number of my machines.
|
||||
|
||||
I use home-manager to manage my dotfiles.
|
||||
|
||||
## Layout
|
||||
|
||||
`machines/` has a folder for each machine (identified by hostname) with its
|
||||
`configuration.nix` and `hardware-configuration.nix`. Modules specific to each machine
|
||||
also go in their respective directories.
|
||||
|
||||
Config values that are common to all my machines are in `common.nix`.
|
||||
|
||||
`scripts/` contains shell scripts and small, trivial utilities that are intended to be
|
||||
invoked on the command line.
|
||||
|
||||
`modules/` contains NixOS modules that configure things like git, ssh, my window manager
|
||||
and my editor.
|
||||
|
||||
`overlays/` contains nix overlays.
|
200
colors.nix
200
colors.nix
|
@ -2,120 +2,120 @@
|
|||
|
||||
let inherit (builtins) mapAttrs map; in rec {
|
||||
|
||||
# A simple dark theme with vibrant colors.
|
||||
"dark" = rec {
|
||||
# A simple dark theme with vibrant colors.
|
||||
"dark" = rec {
|
||||
|
||||
# Determines the background for applications such as the terminal,
|
||||
# status bars or WM elements.
|
||||
background = {
|
||||
|
||||
primary = "1a1a1a";
|
||||
# Determines the background for applications such as the terminal,
|
||||
# status bars or WM elements.
|
||||
background = {
|
||||
|
||||
normal = "212121";
|
||||
slight = "535353";
|
||||
primary = "1a1a1a";
|
||||
|
||||
};
|
||||
normal = "212121";
|
||||
slight = "535353";
|
||||
|
||||
# Determines the foreground color of text.
|
||||
foreground = {
|
||||
|
||||
primary = "fafafa";
|
||||
|
||||
normal = "efefef";
|
||||
slight = "bdbdbd";
|
||||
};
|
||||
|
||||
};
|
||||
# Determines the foreground color of text.
|
||||
foreground = {
|
||||
|
||||
grayscales = [
|
||||
"121212"
|
||||
background.primary
|
||||
background.normal
|
||||
"2a2a2a"
|
||||
"323232"
|
||||
"424242"
|
||||
"4a4a4a"
|
||||
background.slight
|
||||
"646464"
|
||||
"6a6a6a"
|
||||
"757575"
|
||||
"7a7a7a"
|
||||
"868686"
|
||||
"8a8a8a"
|
||||
"979797"
|
||||
"9a9a9a"
|
||||
"a8a8a8"
|
||||
"aaaaaa"
|
||||
"b9b9b9"
|
||||
foreground.slight
|
||||
"cacaca"
|
||||
"dadada"
|
||||
"eaeaea"
|
||||
foreground.normal
|
||||
foreground.primary
|
||||
];
|
||||
primary = "fafafa";
|
||||
|
||||
red = {
|
||||
normal = "ff6161";
|
||||
bright = "ff3b3b";
|
||||
pastel = "ff5369";
|
||||
};
|
||||
normal = "efefef";
|
||||
slight = "bdbdbd";
|
||||
|
||||
green = {
|
||||
bright = "29f26c";
|
||||
normal = "8aff80";
|
||||
pastel = "";
|
||||
};
|
||||
};
|
||||
|
||||
blue = {
|
||||
normal = "30c7ff";
|
||||
bright = "00e1ff";
|
||||
pastel = "";
|
||||
};
|
||||
grayscales = [
|
||||
"121212"
|
||||
background.primary
|
||||
background.normal
|
||||
"2a2a2a"
|
||||
"323232"
|
||||
"424242"
|
||||
"4a4a4a"
|
||||
background.slight
|
||||
"646464"
|
||||
"6a6a6a"
|
||||
"757575"
|
||||
"7a7a7a"
|
||||
"868686"
|
||||
"8a8a8a"
|
||||
"979797"
|
||||
"9a9a9a"
|
||||
"a8a8a8"
|
||||
"aaaaaa"
|
||||
"b9b9b9"
|
||||
foreground.slight
|
||||
"cacaca"
|
||||
"dadada"
|
||||
"eaeaea"
|
||||
foreground.normal
|
||||
foreground.primary
|
||||
];
|
||||
|
||||
yellow = {
|
||||
normal = "fcfc51";
|
||||
bright = "fcfc51";
|
||||
pastel = "";
|
||||
};
|
||||
|
||||
purple = {
|
||||
normal = "bd78fa";
|
||||
bright = "c97ffa";
|
||||
pastel = "00e1ff";
|
||||
};
|
||||
|
||||
cyan = {
|
||||
normal = "29f8ff";
|
||||
bright = "26e3fc";
|
||||
pastel = "";
|
||||
};
|
||||
red = {
|
||||
normal = "ff6161";
|
||||
bright = "ff3b3b";
|
||||
pastel = "ff7588";
|
||||
};
|
||||
|
||||
pink = {
|
||||
normal = "f74ddb";
|
||||
bright = "ff63e5";
|
||||
pastel = "";
|
||||
};
|
||||
green = {
|
||||
normal = "8aff80";
|
||||
bright = "29f26c";
|
||||
pastel = "";
|
||||
};
|
||||
|
||||
orange = {
|
||||
normal = "ff5e69";
|
||||
bright = "fca151";
|
||||
pastel = "";
|
||||
};
|
||||
blue = {
|
||||
normal = "30c7ff";
|
||||
bright = "00e1ff";
|
||||
pastel = "";
|
||||
};
|
||||
|
||||
misc = {
|
||||
blueGrey = "9ccdd9";
|
||||
teal = "00ccad";
|
||||
lime = "d5ff63";
|
||||
};
|
||||
yellow = {
|
||||
normal = "fcfc51";
|
||||
bright = "fcfc51";
|
||||
pastel = "e9ff87";
|
||||
};
|
||||
|
||||
hex = mapAttrs (name: value:
|
||||
if name == "grayscales"
|
||||
then map (v: "#" + v) value
|
||||
else if name == "hex"
|
||||
then value
|
||||
else mapAttrs (n: v: "#" + v) value
|
||||
) (dark);
|
||||
purple = {
|
||||
normal = "b58aff";
|
||||
bright = "c97ffa";
|
||||
pastel = "d9b5ff";
|
||||
};
|
||||
|
||||
};
|
||||
cyan = {
|
||||
normal = "29f8ff";
|
||||
bright = "26e3fc";
|
||||
pastel = "63e8ff";
|
||||
};
|
||||
|
||||
pink = {
|
||||
normal = "ee8fff";
|
||||
bright = "ff63e5";
|
||||
pastel = "ff96e3";
|
||||
};
|
||||
|
||||
orange = {
|
||||
normal = "ff8c26";
|
||||
bright = "fca151";
|
||||
pastel = "";
|
||||
};
|
||||
|
||||
misc = {
|
||||
blueGrey = "9ccdd9";
|
||||
teal = "00ccad";
|
||||
lime = "d5ff63";
|
||||
};
|
||||
|
||||
hex = mapAttrs (name: value:
|
||||
if name == "grayscales"
|
||||
then map (v: "#" + v) value
|
||||
else if name == "hex"
|
||||
then value
|
||||
else mapAttrs (n: v: "#" + v) value
|
||||
) (dark);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
38
common.nix
Normal file
38
common.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Holds common settings for *all* systems, including both servers and
|
||||
# clients.
|
||||
|
||||
{ pkgs, oxalica, ... }: {
|
||||
|
||||
nix = {
|
||||
trustedUsers = [ "riley" ];
|
||||
optimise.automatic = true;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
config = { allowUnfree = true; };
|
||||
overlays = [
|
||||
|
||||
# Import overlays defined under the `overlays/` directory.
|
||||
(import ./overlays)
|
||||
|
||||
# Clients need Rust for development, servers need Rust for
|
||||
# deployment.
|
||||
oxalica.overlay
|
||||
|
||||
];
|
||||
};
|
||||
|
||||
boot.cleanTmpDir = true;
|
||||
|
||||
environment.systemPackages = [
|
||||
|
||||
# Include common packages I use everywhere, like `rg`
|
||||
# and `exa`
|
||||
(import ./env.nix { inherit pkgs; })
|
||||
|
||||
];
|
||||
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
imports = [
|
||||
|
||||
# Home-manager modules
|
||||
<home-manager/nixos>
|
||||
|
||||
./hardware-configuration.nix
|
||||
|
||||
# Programs
|
||||
./modules/kakoune
|
||||
./alacritty.nix
|
||||
./git.nix
|
||||
|
||||
# Display server and related config
|
||||
./display.nix
|
||||
./fonts.nix
|
||||
|
||||
];
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
nix.autoOptimiseStore = true;
|
||||
nix.gc.automatic = true;
|
||||
|
||||
boot = {
|
||||
loader.systemd-boot = {
|
||||
enable = true;
|
||||
editor = false;
|
||||
configurationLimit = 10;
|
||||
};
|
||||
loader.efi.canTouchEfiVariables = true;
|
||||
cleanTmpDir = true;
|
||||
};
|
||||
|
||||
networking.hostName = "thor";
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "Europe/Amsterdam";
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.enp9s0.useDHCP = true;
|
||||
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio.enable = true;
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users."riley" = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
||||
# Some utils
|
||||
|
||||
wget
|
||||
curl
|
||||
git
|
||||
|
||||
# Modern coreutils
|
||||
|
||||
ripgrep
|
||||
bottom
|
||||
skim
|
||||
exa
|
||||
bat
|
||||
lf
|
||||
fd
|
||||
|
||||
];
|
||||
|
||||
# This value determines the NixOS release from which the default
|
||||
# settings for stateful data, like file locations and database versions
|
||||
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||
# this value at the release version of the first install of this system.
|
||||
# Before changing this value read the documentation for this option
|
||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||
system.stateVersion = "21.11"; # Did you read the comment?
|
||||
|
||||
};
|
||||
}
|
15
env.nix
Normal file
15
env.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Packages I tend to use
|
||||
|
||||
{ pkgs }: pkgs.buildEnv {
|
||||
name = "riley-user-utils";
|
||||
paths = with pkgs; [
|
||||
ripgrep
|
||||
bottom
|
||||
delta
|
||||
skim
|
||||
exa
|
||||
bat
|
||||
lf
|
||||
fd
|
||||
];
|
||||
}
|
164
flake.lock
Normal file
164
flake.lock
Normal file
|
@ -0,0 +1,164 @@
|
|||
{
|
||||
"nodes": {
|
||||
"agenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1652712410,
|
||||
"narHash": "sha256-hMJ2TqLt0DleEnQFGUHK9sV2aAzJPU8pZeiZoqRozbE=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "7e5e58b98c3dcbf497543ff6f22591552ebfe65b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1656065134,
|
||||
"narHash": "sha256-oc6E6ByIw3oJaIyc67maaFcnjYOz1mMcOtHxbEf9NwQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "bee6a7250dd1b01844a2de7e02e4df7d8a0a206c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1658750091,
|
||||
"narHash": "sha256-T7wmpoE5UJPuX8VQCpZIG7O8foAC3BCr+DK+GnXA4uM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "8419dfd39d678afd5bc40df48f21fcaad8fc1332",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1638587357,
|
||||
"narHash": "sha256-2ySMW3QARG8BsRPmwe7clTbdCuaObromOKewykP+UJc=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e34c5379866833f41e2a36f309912fa675d687c7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-21.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1654953433,
|
||||
"narHash": "sha256-TwEeh4r50NdWHFAHQSyjCk2cZxgwUfcCCAJOhPdXB28=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "90cd5459a1fd707819b9a3fb9c852beaaac3b79a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1658648081,
|
||||
"narHash": "sha256-RL5nr4Xhp0zQeEGG/I3t3FmqaI9QrBg5PH31NF+7A/A=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e494a908e8895b9cba18e21d5fc83362f64b3f6a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1656401090,
|
||||
"narHash": "sha256-bUS2nfQsvTQW2z8SK7oEFSElbmoBahOPtbXPm0AL3I4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "16de63fcc54e88b9a106a603038dd5dd2feb21eb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"oxalica": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1658717414,
|
||||
"narHash": "sha256-M5piRQdqU680bWhkpyQH09zub75VxfRtuQmNJc+1mhc=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "f612ccd516e97a14e4a7b55c6c88826f575e6805",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"home-manager": "home-manager",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"oxalica": "oxalica"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"locked": {
|
||||
"lastModified": 1653893745,
|
||||
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
65
flake.nix
Normal file
65
flake.nix
Normal file
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
|
||||
inputs = {
|
||||
|
||||
# Living on the edge
|
||||
nixpkgs = {
|
||||
url = github:NixOS/nixpkgs/nixos-unstable;
|
||||
};
|
||||
|
||||
# Used for managing dotfiles
|
||||
home-manager = {
|
||||
url = github:nix-community/home-manager;
|
||||
};
|
||||
|
||||
# Rust overlay, for Rust development
|
||||
oxalica = {
|
||||
url = github:oxalica/rust-overlay;
|
||||
};
|
||||
|
||||
# For managing secrets
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
outputs = args: with args.nixpkgs; {
|
||||
nixosConfigurations = {
|
||||
|
||||
# Desktop client
|
||||
"thor" = lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./machines/thor/configuration.nix
|
||||
./common.nix
|
||||
];
|
||||
specialArgs = args;
|
||||
};
|
||||
|
||||
# Dell XPS laptop client
|
||||
"loki" = lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./machines/loki/configuration.nix
|
||||
./common.nix
|
||||
];
|
||||
specialArgs = args;
|
||||
};
|
||||
|
||||
# TODO: Pinebook Pro
|
||||
|
||||
# Raspberry Pi server
|
||||
"sif" = lib.nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
modules = [
|
||||
./machines/sif/configuration.nix
|
||||
./common.nix
|
||||
];
|
||||
specialArgs = args;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
{
|
||||
fetchFromGitHub, lib, stdenv, pkg-config, installShellFiles, libxcb,
|
||||
xcbutilkeysyms, xcbutil, xcbutilwm, xcbutilxrm, libstartup_notification, libX11, pcre,
|
||||
libev, yajl, xcb-util-cursor, perl, pango, perlPackages, libxkbcommon, xorgserver,
|
||||
xvfb-run, asciidoc, xmlto, docbook_xml_dtd_45, docbook_xsl, findXMLCatalogs,
|
||||
autoconf, autoreconfHook
|
||||
}:
|
||||
|
||||
with stdenv; mkDerivation rec {
|
||||
pname = "i3-gaps-rounded";
|
||||
version = "4.16.1-non-git";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "resloved";
|
||||
repo = "i3";
|
||||
rev = "b521c18ca1bca1c16d3fd69214ad3972bffc9e42";
|
||||
sha256 = "0w4akd7mkdm4xlv2ai2hyjn45f1qgzj5g6n09hrcns1zv4nffcch";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
installShellFiles
|
||||
perl
|
||||
asciidoc
|
||||
xmlto
|
||||
docbook_xml_dtd_45
|
||||
docbook_xsl
|
||||
findXMLCatalogs
|
||||
autoreconfHook
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
libxcb xcbutilkeysyms xcbutil xcbutilwm xcbutilxrm libxkbcommon
|
||||
libstartup_notification libX11 pcre libev yajl xcb-util-cursor perl pango
|
||||
perlPackages.AnyEventI3 perlPackages.X11XCB perlPackages.IPCRun
|
||||
perlPackages.ExtUtilsPkgConfig perlPackages.InlineC
|
||||
xorgserver xvfb-run
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs .
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
cd x86_64-pc-linux-gnu
|
||||
make all
|
||||
'';
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
riley = {
|
||||
gui = true;
|
||||
ide = true;
|
||||
kak.ide = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
|
@ -16,6 +16,18 @@
|
|||
interfaces.wlp6s0.useDHCP = true;
|
||||
};
|
||||
|
||||
boot = {
|
||||
loader.systemd-boot = {
|
||||
enable = true;
|
||||
editor = false;
|
||||
configurationLimit = 10;
|
||||
};
|
||||
|
||||
loader.efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
|
||||
devices = {
|
||||
audio = {
|
||||
|
||||
|
|
3
machines/sif/README.md
Normal file
3
machines/sif/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Sif
|
||||
|
||||
Sif is the server that hosts my website. It's a Raspberry Pi 3.
|
91
machines/sif/configuration.nix
Normal file
91
machines/sif/configuration.nix
Normal file
|
@ -0,0 +1,91 @@
|
|||
{ config, pkgs, lib, agenix, ... }:
|
||||
|
||||
{
|
||||
|
||||
imports = [
|
||||
|
||||
agenix.nixosModule
|
||||
|
||||
../../modules
|
||||
|
||||
# Reverse proxy
|
||||
./services/nginx.nix
|
||||
|
||||
# Website
|
||||
./services/website.nix
|
||||
|
||||
];
|
||||
|
||||
networking.hostName = "sif";
|
||||
|
||||
boot.loader = {
|
||||
grub.enable = false;
|
||||
generic-extlinux-compatible.enable = true;
|
||||
};
|
||||
|
||||
documentation.enable = false;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
];
|
||||
|
||||
age.secrets."website".file = ../../secrets/website.age;
|
||||
|
||||
system.stateVersion = "21.11";
|
||||
|
||||
# Custom modules defined by myself.
|
||||
custom = {
|
||||
|
||||
gui.enable = false;
|
||||
|
||||
kak = {
|
||||
enable = true;
|
||||
ide.nix = true;
|
||||
};
|
||||
|
||||
net.interfaces = [
|
||||
"eth0"
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
|
||||
users.users."riley" = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
};
|
||||
|
||||
networking.interfaces.eth0.useDHCP = true;
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
nix = {
|
||||
distributedBuilds = true;
|
||||
buildMachines = [{
|
||||
|
||||
hostName = "thor";
|
||||
sshUser = "riley";
|
||||
sshKey = "/root/.ssh/id_ed25519";
|
||||
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
supportedFeatures = [
|
||||
"nixos-test"
|
||||
"benchmark"
|
||||
"big-parallel"
|
||||
"kvm"
|
||||
];
|
||||
|
||||
}];
|
||||
};
|
||||
|
||||
}
|
66
machines/sif/services/nginx.nix
Normal file
66
machines/sif/services/nginx.nix
Normal file
|
@ -0,0 +1,66 @@
|
|||
{ ... }:
|
||||
|
||||
let enableACME = false;
|
||||
port = toString 3000;
|
||||
in {
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "me@riley.lgbt";
|
||||
};
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts = {
|
||||
|
||||
"192.168.2.22" = {
|
||||
listen = [{
|
||||
port = 80;
|
||||
addr = "192.168.2.22";
|
||||
}];
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${port}";
|
||||
};
|
||||
};
|
||||
|
||||
# Main domain that hosts my website
|
||||
"riley.lgbt" = {
|
||||
|
||||
inherit enableACME;
|
||||
|
||||
listen = [{
|
||||
port = if enableACME then 443 else 80;
|
||||
addr = "77.169.117.112";
|
||||
}];
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${port}";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
"rly.cx" = {
|
||||
|
||||
inherit enableACME;
|
||||
|
||||
listen = [{
|
||||
port = if enableACME then 443 else 80;
|
||||
addr = "77.169.117.112";
|
||||
}];
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${port}";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
38
machines/sif/services/website.nix
Normal file
38
machines/sif/services/website.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
|
||||
let secret = config.age.secrets."website".path;
|
||||
builder = pkgs.rustPlatform.buildRustPackage.override {
|
||||
rustc = (pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.minimal)).overrideAttrs (old: {
|
||||
meta.platforms = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
});
|
||||
};
|
||||
website = builder {
|
||||
pname = "website";
|
||||
version = "0.1.0";
|
||||
cargoSha256 = "sha256-4v45QaZKyjifn2MGyuy+SovfFBWu55FYR9nWRWlaQOM=";
|
||||
|
||||
postInstall = ''
|
||||
cp ./links.toml $out/links.toml
|
||||
cp -r ./static/ $out/static/
|
||||
'';
|
||||
|
||||
src = pkgs.fetchgit {
|
||||
url = "https://im.badat.dev/riley/website.git";
|
||||
rev = "refs/heads/mistress";
|
||||
sha256 = "sha256-QONZR4zpgifEQByH3rtfkHQjwQVrjRy89RVvVLMciKs=";
|
||||
};
|
||||
};
|
||||
in {
|
||||
systemd.services."website" = {
|
||||
enable = true;
|
||||
description = "Run my website :)";
|
||||
path = [ website ];
|
||||
script = ''
|
||||
cd ${website}
|
||||
SITE_API_SECRET=$(cat ${secret}) ${website}/bin/website
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -1,20 +1,66 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, agenix, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
];
|
||||
imports = [
|
||||
agenix.nixosModule
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
];
|
||||
|
||||
riley = {
|
||||
ide = true;
|
||||
gui = true;
|
||||
};
|
||||
custom = {
|
||||
gui = {
|
||||
enable = true;
|
||||
theme = (import ../../colors.nix).dark;
|
||||
};
|
||||
kak = {
|
||||
|
||||
networking = {
|
||||
hostName = "thor";
|
||||
interfaces.enp9s0.useDHCP = true;
|
||||
};
|
||||
enable = true;
|
||||
|
||||
haskell = true;
|
||||
rust = true;
|
||||
nix = true;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "21.11";
|
||||
|
||||
networking = {
|
||||
hostName = "thor";
|
||||
interfaces.enp9s0.useDHCP = true;
|
||||
};
|
||||
|
||||
boot = {
|
||||
loader.systemd-boot = {
|
||||
enable = true;
|
||||
editor = false;
|
||||
configurationLimit = 10;
|
||||
};
|
||||
|
||||
loader.efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
home-manager.users.riley.home.stateVersion = "21.11";
|
||||
|
||||
users.users."riley".packages = with pkgs; [
|
||||
minecraft
|
||||
cockatrice
|
||||
];
|
||||
|
||||
programs.steam = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
hardware.opengl = {
|
||||
enable = true;
|
||||
driSupport = true;
|
||||
driSupport32Bit = true;
|
||||
};
|
||||
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
|
||||
age.secrets."website-secret".file = ../../secrets/website.age;
|
||||
|
||||
devices = {
|
||||
|
||||
|
@ -26,7 +72,7 @@
|
|||
external = "alsa_output.pci-0000_0a_00.1.hdmi-stereo";
|
||||
headset = null; # Thor doesn't have bluetooth support (yet)
|
||||
|
||||
# Inputs
|
||||
# Inputs
|
||||
main-mic = "alsa_input.usb-046d_C922_Pro_Stream_Webcam_CC9E75BF-02.analog-stereo";
|
||||
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/f3cdd2ab-62ba-4d72-8a28-b3adc0ec3997";
|
||||
|
|
|
@ -1,183 +1,188 @@
|
|||
# Global config
|
||||
# Modules used by most systems.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, home-manager, ... }:
|
||||
|
||||
with lib; with types;
|
||||
let named = submodule {
|
||||
options = {
|
||||
normal = mkOption { type = str; };
|
||||
bright = mkOption { type = str; };
|
||||
pastel = mkOption { type = str; };
|
||||
};
|
||||
};
|
||||
special = submodule {
|
||||
options = {
|
||||
primary = mkOption { type = str; };
|
||||
normal = mkOption { type = str; };
|
||||
slight = mkOption { type = str; };
|
||||
};
|
||||
};
|
||||
themeType = submodule {
|
||||
options = {
|
||||
foreground = mkOption { type = special; };
|
||||
background = mkOption { type = special; };
|
||||
grayscales = mkOption { type = listOf str; };
|
||||
red = mkOption { type = named; };
|
||||
green = mkOption { type = named; };
|
||||
blue = mkOption { type = named; };
|
||||
yellow = mkOption { type = named; };
|
||||
purple = mkOption { type = named; };
|
||||
cyan = mkOption { type = named; };
|
||||
pink = mkOption { type = named; };
|
||||
orange = mkOption { type = named; };
|
||||
misc = mkOption { type = attrsOf str; };
|
||||
hex = mkOption { type = themeType; };
|
||||
};
|
||||
}; in
|
||||
{
|
||||
let themeType =
|
||||
let named = submodule {
|
||||
options = {
|
||||
normal = mkOption { type = str; };
|
||||
bright = mkOption { type = str; };
|
||||
pastel = mkOption { type = str; };
|
||||
};
|
||||
};
|
||||
special = submodule {
|
||||
options = {
|
||||
primary = mkOption { type = str; };
|
||||
normal = mkOption { type = str; };
|
||||
slight = mkOption { type = str; };
|
||||
};
|
||||
};
|
||||
in submodule {
|
||||
options = {
|
||||
foreground = mkOption { type = special; };
|
||||
background = mkOption { type = special; };
|
||||
grayscales = mkOption { type = listOf str; };
|
||||
red = mkOption { type = named; };
|
||||
green = mkOption { type = named; };
|
||||
blue = mkOption { type = named; };
|
||||
yellow = mkOption { type = named; };
|
||||
purple = mkOption { type = named; };
|
||||
cyan = mkOption { type = named; };
|
||||
pink = mkOption { type = named; };
|
||||
orange = mkOption { type = named; };
|
||||
misc = mkOption { type = attrsOf str; };
|
||||
hex = mkOption { type = themeType; };
|
||||
};
|
||||
};
|
||||
|
||||
options.riley = with lib; {
|
||||
in {
|
||||
|
||||
ide = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Enable IDE-like plugins such as language servers for Rust, Haskell and
|
||||
Nix in the editor, and configure accordingly. If disabled, the editor
|
||||
will lack some features such as semantic highlighting.
|
||||
'';
|
||||
default = true;
|
||||
};
|
||||
|
||||
gui = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Enable the display server and related graphical programs.
|
||||
'';
|
||||
default = true;
|
||||
};
|
||||
options.riley = with lib; {
|
||||
|
||||
theme = mkOption {
|
||||
type = themeType;
|
||||
description = ''
|
||||
The theme used across the installation. Not used if gui is disabled.
|
||||
'';
|
||||
};
|
||||
theme = mkOption {
|
||||
type = themeType;
|
||||
description = ''
|
||||
The theme used across the installation. Not used if gui is disabled.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
options.devices = mkOption {
|
||||
type = with types; submodule {
|
||||
options = {
|
||||
|
||||
audio = mkOption {
|
||||
type = nullOr (submodule {
|
||||
options = {
|
||||
speakers = mkOption { type = str; };
|
||||
external = mkOption { type = str; };
|
||||
headset = mkOption { type = nullOr str; };
|
||||
main-mic = mkOption { type = nullOr str; };
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
Known audio devices: outputs & microphones.
|
||||
Each string should be a pulseaudio sink or source.
|
||||
'';
|
||||
};
|
||||
options.devices = mkOption {
|
||||
type = with types; submodule {
|
||||
options = {
|
||||
|
||||
video = mkOption {
|
||||
type = submodule {
|
||||
options = {
|
||||
displays = let output = submodule {
|
||||
options = {
|
||||
primary = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
position = mkOption {
|
||||
type = nullOr (listOf int);
|
||||
default = null;
|
||||
};
|
||||
rotate = mkOption {
|
||||
type = enum [ "normal" "left" "right" "inverted" ];
|
||||
default = "normal";
|
||||
};
|
||||
};
|
||||
}; in mkOption {
|
||||
type = attrsOf output;
|
||||
description = ''
|
||||
A list of outputs with information on how to place them.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Define the video devices (just the displays, for now).
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
audio = mkOption {
|
||||
type = nullOr (submodule {
|
||||
options = {
|
||||
speakers = mkOption { type = str; };
|
||||
external = mkOption { type = str; };
|
||||
headset = mkOption { type = nullOr str; };
|
||||
main-mic = mkOption { type = nullOr str; };
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
Known audio devices: outputs & microphones.
|
||||
Each string should be a pulseaudio sink or source.
|
||||
'';
|
||||
};
|
||||
|
||||
video = mkOption {
|
||||
type = submodule {
|
||||
options = {
|
||||
displays = let output = submodule {
|
||||
options = {
|
||||
primary = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
position = mkOption {
|
||||
type = nullOr (listOf int);
|
||||
default = null;
|
||||
};
|
||||
rotate = mkOption {
|
||||
type = enum [ "normal" "left" "right" "inverted" ];
|
||||
default = "normal";
|
||||
};
|
||||
};
|
||||
}; in mkOption {
|
||||
type = attrsOf output;
|
||||
description = ''
|
||||
A list of outputs with information on how to place them.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Define the video devices (just the displays, for now).
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
imports = [
|
||||
imports = [
|
||||
|
||||
<home-manager/nixos>
|
||||
home-manager.nixosModule
|
||||
|
||||
./ide
|
||||
./gui
|
||||
|
||||
./fonts.nix
|
||||
./git.nix
|
||||
./ssh.nix
|
||||
|
||||
];
|
||||
./kak
|
||||
./gui
|
||||
|
||||
./fonts.nix
|
||||
./git.nix
|
||||
./ssh.nix
|
||||
|
||||
];
|
||||
|
||||
config = {
|
||||
|
||||
riley.theme = (import ../colors.nix)."dark";
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
time.timeZone = "Europe/Amsterdam";
|
||||
|
||||
# Web utils
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
|
||||
wget
|
||||
curl
|
||||
git
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
||||
# Coreutils
|
||||
# Web utils
|
||||
|
||||
ripgrep
|
||||
bottom
|
||||
skim
|
||||
exa
|
||||
bat
|
||||
lf
|
||||
fd
|
||||
|
||||
];
|
||||
wget
|
||||
curl
|
||||
git
|
||||
|
||||
boot = {
|
||||
loader.systemd-boot = {
|
||||
enable = true;
|
||||
editor = false;
|
||||
configurationLimit = 10;
|
||||
};
|
||||
];
|
||||
|
||||
loader.efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
|
||||
cleanTmpDir = true;
|
||||
};
|
||||
environment.shellAliases = {
|
||||
|
||||
networking = {
|
||||
firewall.enable = false;
|
||||
useDHCP = false;
|
||||
};
|
||||
# Born to VIM
|
||||
":q" = "exit";
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
security.rtkit.enable = true;
|
||||
# Sike I use kakoune
|
||||
":e" = "kak";
|
||||
|
||||
# Launch [T]erminal
|
||||
"t" = "alacritty";
|
||||
|
||||
# [D]isown
|
||||
"d" = "disown";
|
||||
|
||||
};
|
||||
|
||||
programs.bash.interactiveShellInit = ''
|
||||
|
||||
# [G]o to the directory. Create the directory if it does not exist
|
||||
# yet, and if the directory contains a shell.nix file, source it.
|
||||
g () {
|
||||
[ -d "$1" ] || mkdir -p "$1";
|
||||
cd "$1";
|
||||
[ -e "shell.nix" ] && nix-shell;
|
||||
}
|
||||
|
||||
# [M]ake a directory and immediately enter it.
|
||||
m () { mkdir -p "$1" && cd "$1"; }
|
||||
|
||||
# [R]eplace the current process with the given one.
|
||||
r () { $1 & disown; exit; }
|
||||
|
||||
# [J]ump to the directory by means of fuzzy search. If the fuzzy finder
|
||||
# is aborted, the jump is also aborted.
|
||||
j () { t=`sk` && cd $t; }
|
||||
|
||||
# Enter a temporary [d]irectory.
|
||||
d () { cd "$(mktemp -d)"; }
|
||||
|
||||
'';
|
||||
|
||||
networking = {
|
||||
firewall.enable = false;
|
||||
useDHCP = false;
|
||||
};
|
||||
|
||||
security.rtkit.enable = true;
|
||||
|
||||
users.users."riley" = {
|
||||
isNormalUser = true;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
enable = true;
|
||||
defaultFonts = {
|
||||
monospace = [
|
||||
"Fira Mono"
|
||||
"Fira Code"
|
||||
"Source Code Pro"
|
||||
"Noto Color Emoji"
|
||||
];
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
|
||||
(lib.mkIf (config.riley.gui) {
|
||||
home-manager.users."riley" = {
|
||||
programs.alacritty = {
|
||||
enable = true;
|
||||
settings = {
|
||||
|
||||
window.padding = { x = 8; y = 8; };
|
||||
|
||||
font = {
|
||||
normal = { family = "Fira Code"; style = "Regular"; };
|
||||
bold = { family = "Fira Code"; style = "Medium"; };
|
||||
};
|
||||
|
||||
colors = with config.riley.theme.hex; {
|
||||
|
||||
primary = {
|
||||
background = background.primary;
|
||||
foreground = foreground.primary;
|
||||
};
|
||||
|
||||
normal = {
|
||||
red = red.normal;
|
||||
green = green.normal;
|
||||
blue = blue.normal;
|
||||
magenta = purple.normal;
|
||||
yellow = yellow.normal;
|
||||
cyan = cyan.normal;
|
||||
};
|
||||
|
||||
bright = {
|
||||
red = red.bright;
|
||||
green = green.bright;
|
||||
blue = blue.bright;
|
||||
magenta = purple.bright;
|
||||
yellow = yellow.bright;
|
||||
cyan = cyan.bright;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
})
|
|
@ -1,24 +1,20 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
# This is a simple module that does not define its own options.
|
||||
# Rather, it just looks at the `custom.gui.enable` option to
|
||||
# determine if it needs to add anything.
|
||||
|
||||
(lib.mkIf (config.riley.gui) {
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
let gui = config.custom.gui;
|
||||
|
||||
scripts = (import ../../scripts/clip.nix {
|
||||
inherit pkgs;
|
||||
});
|
||||
|
||||
in lib.mkIf (gui.enable) {
|
||||
|
||||
# Add some shell scripts that abstract away the
|
||||
# horrible reality that the clipboard is managed by
|
||||
# the display server.
|
||||
users.users."riley".packages = with pkgs; [
|
||||
|
||||
(writeShellApplication {
|
||||
name = "copy";
|
||||
runtimeInputs = [ xclip ];
|
||||
text = "xclip -sel clip -i";
|
||||
})
|
||||
|
||||
(writeShellApplication {
|
||||
name = "paste";
|
||||
runtimeInputs = [ xclip ];
|
||||
text = "xclip -sel clip -o";
|
||||
})
|
||||
|
||||
];
|
||||
users.users."riley".packages = with scripts; [ c p ];
|
||||
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,20 +1,48 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
({
|
||||
let gui = config.custom.gui;
|
||||
|
||||
# Clipboard wrapper scripts
|
||||
clip = (import ../../scripts/clip.nix {
|
||||
inherit pkgs;
|
||||
});
|
||||
|
||||
in
|
||||
|
||||
with lib; {
|
||||
|
||||
imports = [
|
||||
./window-manager.nix
|
||||
./pulseaudio.nix
|
||||
./clipboard.nix
|
||||
./alacritty.nix
|
||||
];
|
||||
|
||||
}) // (lib.mkIf (config.riley.gui) {
|
||||
|
||||
# Graphical applications
|
||||
users.users."riley".packages = with pkgs; [
|
||||
google-chrome
|
||||
tdesktop
|
||||
./wm
|
||||
|
||||
./pulseaudio.nix
|
||||
./statusbar.nix
|
||||
./terminal.nix
|
||||
|
||||
./theme.nix
|
||||
|
||||
];
|
||||
|
||||
options.custom.gui = {
|
||||
|
||||
# Use a nested enable option, to allow extension of this option
|
||||
# namespace later on.
|
||||
enable = mkEnableOption "gui applications and window manager";
|
||||
|
||||
};
|
||||
|
||||
})
|
||||
config = mkIf (gui.enable) {
|
||||
|
||||
# Import some applications I use on all my graphical systems
|
||||
users.users."riley".packages = (with pkgs; [
|
||||
|
||||
# My browser
|
||||
google-chrome
|
||||
|
||||
# Telegram client
|
||||
tdesktop
|
||||
|
||||
]) ++ (with clip; [ c p ]); # Add clipboard scripts
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
(lib.mkIf (config.riley.gui) {
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio.enable = true;
|
||||
let gui = config.custom.gui; in
|
||||
|
||||
users.users."riley".packages = with pkgs; [
|
||||
pavucontrol
|
||||
];
|
||||
})
|
||||
with lib; {
|
||||
|
||||
# Define pulseaudio toggle under the `audio` option set.
|
||||
options.custom.gui.audio.pulseaudio = mkEnableOption "PulseAudio sound server";
|
||||
|
||||
config = mkIf (gui.audio.pulseaudio) {
|
||||
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio.enable = true;
|
||||
|
||||
users.users."riley".packages = with pkgs; [
|
||||
pavucontrol
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
11
modules/gui/statusbar.nix
Normal file
11
modules/gui/statusbar.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
|
||||
(lib.mkIf (config.custom.gui.enable && false) {
|
||||
home-manager.users."riley" = {
|
||||
services.polybar = {
|
||||
enable = true;
|
||||
script = "polybar bar &";
|
||||
config = {}; # TODO
|
||||
};
|
||||
};
|
||||
})
|
48
modules/gui/terminal.nix
Normal file
48
modules/gui/terminal.nix
Normal file
|
@ -0,0 +1,48 @@
|
|||
# Module that adds my terminal emulator of choice to my environment.
|
||||
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
let gui = config.custom.gui; in
|
||||
|
||||
with lib; mkIf (gui.enable) {
|
||||
|
||||
home-manager.users."riley".programs.kitty = {
|
||||
|
||||
# Use kitty because it supports cool ligatures and
|
||||
# has nice scripting capabilities.
|
||||
enable = true;
|
||||
|
||||
font = {
|
||||
name = "Fira Code";
|
||||
size = 11;
|
||||
};
|
||||
|
||||
settings = with gui.theme.hex; {
|
||||
|
||||
bold_font = "Fira Code Medium";
|
||||
|
||||
background = background.primary;
|
||||
foreground = foreground.primary;
|
||||
|
||||
color1 = red.normal;
|
||||
color9 = red.bright;
|
||||
|
||||
color2 = green.normal;
|
||||
color10 = green.bright;
|
||||
|
||||
color3 = yellow.normal;
|
||||
color11 = yellow.bright;
|
||||
|
||||
color4 = blue.normal;
|
||||
color12 = blue.bright;
|
||||
|
||||
color5 = purple.normal;
|
||||
color13 = purple.bright;
|
||||
|
||||
color6 = cyan.normal;
|
||||
color14 = cyan.bright;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
58
modules/gui/theme.nix
Normal file
58
modules/gui/theme.nix
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Defines the global color theme option.
|
||||
|
||||
{ lib, ... }:
|
||||
|
||||
with lib; with types;
|
||||
|
||||
# Define the type in a let binding to prevent too much rightward
|
||||
# drift in the option configuration.
|
||||
let themeType =
|
||||
|
||||
let # Named colors are colors like "red" or "black".
|
||||
named = submodule {
|
||||
options = {
|
||||
normal = mkOption { type = str; };
|
||||
bright = mkOption { type = str; };
|
||||
pastel = mkOption { type = str; };
|
||||
};
|
||||
};
|
||||
|
||||
# Special colors are more abstract, for example
|
||||
# "foreground".
|
||||
special = submodule {
|
||||
options = {
|
||||
primary = mkOption { type = str; };
|
||||
normal = mkOption { type = str; };
|
||||
slight = mkOption { type = str; };
|
||||
};
|
||||
};
|
||||
|
||||
in submodule {
|
||||
options = {
|
||||
foreground = mkOption { type = special; };
|
||||
background = mkOption { type = special; };
|
||||
grayscales = mkOption { type = listOf str; };
|
||||
red = mkOption { type = named; };
|
||||
green = mkOption { type = named; };
|
||||
blue = mkOption { type = named; };
|
||||
yellow = mkOption { type = named; };
|
||||
purple = mkOption { type = named; };
|
||||
cyan = mkOption { type = named; };
|
||||
pink = mkOption { type = named; };
|
||||
orange = mkOption { type = named; };
|
||||
misc = mkOption { type = attrsOf str; };
|
||||
hex = mkOption { type = themeType; };
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
|
||||
options.custom.gui.theme = mkOption {
|
||||
type = themeType;
|
||||
description = ''
|
||||
Color theme used across the installation for various
|
||||
GUI elements and terminal colors.
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let theme = config.riley.theme.hex;
|
||||
let scripts = (import ./scripts.nix { inherit pkgs; });
|
||||
theme = config.riley.theme.hex;
|
||||
modifier = "Mod4";
|
||||
terminal = "${pkgs.kitty}/bin/kitty";
|
||||
keybindings = (import ./keybinds.nix {
|
||||
|
||||
inherit modifier lib pkgs config;
|
||||
inherit modifier lib pkgs config scripts;
|
||||
|
||||
directional = {
|
||||
left = "H";
|
||||
|
@ -14,20 +16,24 @@ let theme = config.riley.theme.hex;
|
|||
};
|
||||
|
||||
workspace = {
|
||||
numbered = 5;
|
||||
numbered = 6;
|
||||
named = {
|
||||
"web" = "equal";
|
||||
"doc" = "minus";
|
||||
"dev" = "0";
|
||||
"chat" = "q";
|
||||
"code" = "w";
|
||||
"browser" = "e";
|
||||
};
|
||||
};
|
||||
|
||||
launchers = {
|
||||
browser = "google-chrome-stable";
|
||||
inherit terminal;
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
in (lib.mkIf (config.riley.gui) {
|
||||
in
|
||||
|
||||
with lib; (mkIf config.custom.gui.enable {
|
||||
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
windowManager.i3.enable = true;
|
||||
|
@ -39,14 +45,12 @@ in (lib.mkIf (config.riley.gui) {
|
|||
|
||||
config = with lib; (rec {
|
||||
|
||||
inherit modifier keybindings;
|
||||
|
||||
terminal = "${pkgs.alacritty}/bin/alacritty";
|
||||
inherit modifier keybindings terminal;
|
||||
|
||||
colors = {
|
||||
focused = rec {
|
||||
background = theme.background.normal;
|
||||
text = theme."red".bright;
|
||||
text = theme."green".bright;
|
||||
border = background;
|
||||
childBorder = border;
|
||||
indicator = border;
|
|
@ -1,4 +1,13 @@
|
|||
{ lib, config, pkgs, modifier ? "Mod4", directional, workspace, launchers }:
|
||||
{
|
||||
modifier ? "Mod4",
|
||||
directional,
|
||||
workspace,
|
||||
launchers,
|
||||
scripts,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
}:
|
||||
|
||||
with lib; let mod = modifier;
|
||||
|
||||
|
@ -51,9 +60,9 @@ with lib; let mod = modifier;
|
|||
);
|
||||
|
||||
# Application launchers
|
||||
genLaunchers = ({ browser }: {
|
||||
genLaunchers = ({ browser, terminal }: {
|
||||
"${mod}+Tab" = "exec ${browser}";
|
||||
"${mod}+Return" = "exec alacritty";
|
||||
"${mod}+Return" = "exec ${terminal}";
|
||||
});
|
||||
|
||||
# Layout manipulation
|
||||
|
@ -62,6 +71,9 @@ with lib; let mod = modifier;
|
|||
"${mod}+A" = "split v";
|
||||
"${mod}+S" = "split h";
|
||||
|
||||
"${mod}+Mod1+A" = "layout toggle stacked splitv";
|
||||
"${mod}+Mod1+S" = "layout toggle tabbed splith";
|
||||
|
||||
"${mod}+F" = "fullscreen toggle";
|
||||
|
||||
"${mod}+BackSpace" = "kill";
|
||||
|
@ -96,10 +108,20 @@ with lib; let mod = modifier;
|
|||
|
||||
})))
|
||||
);
|
||||
|
||||
# Utility scripts, for example for making screenshots.
|
||||
utils = ({ lock ? null, sc ? null }:
|
||||
(optionalAttrs (lock != null) {
|
||||
"${mod}+Escape" = "exec ${lock}/bin/lock";
|
||||
}) // (optionalAttrs (sc != null) {
|
||||
"${mod}+d --release" = "exec ${sc}/bin/sc";
|
||||
})
|
||||
);
|
||||
|
||||
in (mkMerge [
|
||||
|
||||
(media { inherit (pkgs) mpc_cli pulseaudio; })
|
||||
(utils scripts)
|
||||
|
||||
(genDirectional directional)
|
||||
(genWorkspaces workspace)
|
21
modules/gui/wm/scripts.nix
Normal file
21
modules/gui/wm/scripts.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Utility scripts for use with a window manager.
|
||||
|
||||
{ pkgs, ... }: with pkgs; {
|
||||
|
||||
lock = writeShellApplication {
|
||||
name = "lock";
|
||||
runtimeInputs = [ i3lock ];
|
||||
text = "i3lock";
|
||||
};
|
||||
|
||||
sc = (writeShellApplication {
|
||||
name = "sc";
|
||||
runtimeInputs = [ xclip scrot ];
|
||||
text = ''
|
||||
env > /tmp/env_sc.txt
|
||||
scrot -D :0 -ozs /tmp/sc.png 2>/tmp/aaa.txt
|
||||
xclip -t "image/png" -sel clip -i < /tmp/sc.png 2>/tmp/bbb.txt
|
||||
'';
|
||||
});
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
# Haskell text faces and other stuff related to syntax highlighting
|
||||
# for Haskell in Kakoune, because I prefer different color arrangements
|
||||
# per language.
|
||||
|
||||
{ theme, pkgs, ... }: pkgs.writeTextFile (rec {
|
||||
name = "common.kak";
|
||||
destination = "/share/kak/colors/${name}";
|
||||
text = with theme; ''
|
||||
face global value rgb:${yellow.bright}
|
||||
face global string rgb:${green.normal}
|
||||
face global variable +a
|
||||
face global module rgb:${green.normal}
|
||||
face global operator rgb:${cyan.bright}
|
||||
face global type rgb:${yellow.normal}
|
||||
face global function rgb:${cyan.bright}
|
||||
face global keyword rgb:${blue.normal}+b
|
||||
face global builtin +b
|
||||
'';
|
||||
})
|
|
@ -1,8 +0,0 @@
|
|||
# Import syntax themes
|
||||
|
||||
{ lib, theme, pkgs, ... }: [
|
||||
(import ./haskell.nix { inherit lib theme pkgs; })
|
||||
(import ./rust.nix { inherit lib theme pkgs; })
|
||||
(import ./nix.nix { inherit lib theme pkgs; })
|
||||
(import ./common.nix { inherit lib theme pkgs; })
|
||||
]
|
|
@ -1,21 +0,0 @@
|
|||
# Haskell text faces and other stuff related to syntax highlighting
|
||||
# for Haskell in Kakoune, because I prefer different color arrangements
|
||||
# per language.
|
||||
|
||||
{ theme, pkgs, ... }: pkgs.writeTextFile (rec {
|
||||
name = "haskell.kak";
|
||||
destination = "/share/kak/colors/${name}";
|
||||
text = with theme; ''
|
||||
face global value rgb:${green.bright}
|
||||
face global string rgb:${green.bright}
|
||||
face global variable +b
|
||||
face global module rgb:${green.normal}
|
||||
face global meta rgb:${misc.lime}
|
||||
face global operator rgb:${cyan.bright}
|
||||
face global type rgb:${yellow.normal}
|
||||
face global function rgb:${cyan.bright}
|
||||
face global attribute rgb:${blue.normal}
|
||||
face global keyword rgb:${blue.normal}
|
||||
face global builtin +b
|
||||
'';
|
||||
})
|
|
@ -1,19 +0,0 @@
|
|||
# Haskell text faces and other stuff related to syntax highlighting
|
||||
# for Haskell in Kakoune, because I prefer different color arrangements
|
||||
# per language.
|
||||
|
||||
{ theme, pkgs, ... }: pkgs.writeTextFile (rec {
|
||||
name = "nix.kak";
|
||||
destination = "/share/kak/colors/${name}";
|
||||
text = with theme; ''
|
||||
|
||||
add-highlighter buffer/ regex '\b\s*(=)' 1:operator
|
||||
|
||||
face global string rgb:${green.normal}
|
||||
face global operator rgb:${yellow.bright}+b
|
||||
face global keyword rgb:${blue.normal}+b
|
||||
face global meta rgb:${purple.bright}
|
||||
face global builtin rgb:${blue.bright}+b
|
||||
|
||||
'';
|
||||
})
|
|
@ -1,44 +0,0 @@
|
|||
# Haskell text faces and other stuff related to syntax highlighting
|
||||
# for Haskell in Kakoune, because I prefer different color arrangements
|
||||
# per language.
|
||||
|
||||
{ theme, pkgs, ... }: pkgs.writeTextFile (rec {
|
||||
name = "rust.kak";
|
||||
destination = "/share/kak/colors/${name}";
|
||||
text = with theme; ''
|
||||
|
||||
# Types
|
||||
face global variant rgb:${green.bright}+b
|
||||
face global enum rgb:${green.bright}+b
|
||||
face global struct rgb:${red.pastel}+b
|
||||
face global alias rgb:${orange.normal}+b
|
||||
face global primitive rgb:${misc.teal}+b
|
||||
face global trait rgb:${purple.bright}+b
|
||||
face global union rgb:${misc.lime}+b
|
||||
|
||||
# Other Rust-specific syntax elements
|
||||
face global lifetime rgb:${cyan.bright}
|
||||
face global format rgb:${orange.bright}+b
|
||||
face global macro rgb:fc4cbf+b
|
||||
|
||||
# Keywords
|
||||
face global keyword rgb:${blue.normal}
|
||||
|
||||
# Literals
|
||||
face global literal rgb:${yellow.bright}
|
||||
face global string rgb:${yellow.bright}
|
||||
|
||||
# Items
|
||||
face global function rgb:${green.normal}
|
||||
face global method function
|
||||
face global module rgb:${misc.blueGrey}
|
||||
|
||||
# Other stuff
|
||||
face global attribute comment
|
||||
face global variable rgb:${foreground.normal}
|
||||
face global property rgb:${misc.lime}
|
||||
face global operator rgb:${yellow.normal}
|
||||
face global punctuation rgb:${foreground.normal}
|
||||
|
||||
'';
|
||||
})
|
|
@ -1,213 +0,0 @@
|
|||
{ lib, pkgs, config, ... }:
|
||||
|
||||
let kakrc = pkgs.writeTextFile (rec {
|
||||
name = "kakrc.kak";
|
||||
destination = "/share/kak/autoload/${name}";
|
||||
text = with config.riley.theme; ''
|
||||
|
||||
# Line numbering
|
||||
add-highlighter global/ number-lines -separator ' │ ' -hlcursor
|
||||
|
||||
# Setting the tabstop to 4 (even though I have an ultrawide monitor)
|
||||
set-option global tabstop 4
|
||||
|
||||
set global ui_options ncurses_assistant=cat
|
||||
|
||||
# Use Alt-Tab to switch between open buffers
|
||||
map global insert <a-tab> <esc>:buffer-next<ret>
|
||||
map global normal <a-tab> :buffer-next<ret>
|
||||
|
||||
colorscheme common
|
||||
|
||||
face global LineNumbers rgb:${background.slight}
|
||||
face global BufferPadding rgb:${background.slight}
|
||||
face global LineNumberCursor rgb:${foreground.primary}
|
||||
face global crosshairs_line "default,rgb:${background.normal}"
|
||||
face global MenuForeground "default,blue"
|
||||
face global MenuBackground "default,rgb:313131"
|
||||
face global InlayHint rgb:828282
|
||||
|
||||
face global comment rgb:${foreground.slight}
|
||||
|
||||
'' + (lib.optionalString (config.riley.ide) ''
|
||||
|
||||
eval %sh{ kak-lsp --kakoune -s $kak_session }
|
||||
|
||||
hook global -group yeet ModuleLoaded rust %{
|
||||
|
||||
# Override the Rust highlighting with semantic
|
||||
# tokens supplied by the LSP client
|
||||
remove-hooks global rust-highlight
|
||||
remove-highlighter shared/rust
|
||||
|
||||
# Request tokens
|
||||
lsp-semantic-tokens
|
||||
|
||||
# Self-destruct this hook (it should only run once)
|
||||
remove-hooks global yeet
|
||||
|
||||
}
|
||||
|
||||
# Load language-specific color schemes
|
||||
hook global WinSetOption filetype=(haskell) %{
|
||||
|
||||
colorscheme haskell
|
||||
lsp-enable-window
|
||||
|
||||
lsp-inlay-diagnostics-enable global
|
||||
|
||||
map global <tab> ': lsp-code-actions<ret>'
|
||||
map global <ret> ': lsp-hover<ret>'
|
||||
|
||||
}
|
||||
|
||||
hook global WinSetOption filetype=(rust) %{
|
||||
|
||||
lsp-enable-window
|
||||
lsp-inlay-diagnostics-enable window
|
||||
|
||||
colorscheme rust
|
||||
|
||||
hook window -group semtok BufReload .* lsp-semantic-tokens
|
||||
hook window -group semtok NormalIdle .* lsp-semantic-tokens
|
||||
hook window -group semtok InsertIdle .* lsp-semantic-tokens
|
||||
|
||||
hook -once -always window WinSetOption filetype=.* %{
|
||||
remove-hooks window semtok
|
||||
}
|
||||
|
||||
hook window ModeChange .*:.*:insert %{
|
||||
remove-highlighter window/lsp_diagnostics
|
||||
}
|
||||
|
||||
hook window ModeChange .*:insert:normal %{
|
||||
lsp-inlay-diagnostics-enable window
|
||||
}
|
||||
|
||||
set global lsp_inlay_diagnostic_sign '>'
|
||||
|
||||
map global normal <tab> ': lsp-code-actions<ret>'
|
||||
map global normal <ret> ': lsp-hover<ret>'
|
||||
|
||||
}
|
||||
|
||||
hook global WinSetOption filetype=(nix) %{
|
||||
colorscheme nix
|
||||
lsp-enable-window
|
||||
}
|
||||
|
||||
face global InlayDiagnosticWarning rgb:a39e31+f
|
||||
face global InlayDiagnosticError rgb:ad494f+f
|
||||
face global InlayDiagnosticHint rgb:4d965a+f
|
||||
|
||||
'');
|
||||
});
|
||||
|
||||
# Syntax colors
|
||||
colors = (import ./colors {
|
||||
theme = config.riley.theme;
|
||||
inherit lib pkgs;
|
||||
});
|
||||
|
||||
# Config for kak-lsp
|
||||
kak-lsp-config = pkgs.writeTextFile (rec {
|
||||
name = "kak-lsp.toml";
|
||||
destination = "/share/kak-lsp/${name}";
|
||||
text = let semTok = (name: value: ''
|
||||
[[semantic_tokens]]
|
||||
token = "${name}"
|
||||
face = "${value}"
|
||||
''); in ''
|
||||
|
||||
[language.rust]
|
||||
filetypes = [ "rust" ]
|
||||
roots = [ "Cargo.toml" ]
|
||||
command = "rust-analyzer"
|
||||
[language.rust.settings.rust-analyzer]
|
||||
semanticTokens = true
|
||||
diagnostics.enabled = [ "unresolved-proc-macro" ]
|
||||
cargo.loadOutDirsFromCheck = true
|
||||
procMacro.enable = false
|
||||
|
||||
[language.haskell]
|
||||
filetypes = [ "haskell" ]
|
||||
roots = [ "Setup.hs", "stack.yaml", "*.cabal" ]
|
||||
command = "haskell-language-server-wrapper"
|
||||
args = [ "--lsp" ]
|
||||
|
||||
[language.nix]
|
||||
filetypes = [ "nix" ]
|
||||
roots = [ "flake.nix", "shell.nix", ".git", ".hg" ]
|
||||
command = "rnix-lsp"
|
||||
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList semTok {
|
||||
"enumMember" = "variant";
|
||||
"enum" = "enum";
|
||||
"union" = "union";
|
||||
"struct" = "struct";
|
||||
"typeAlias" = "alias";
|
||||
"builtinType" = "primitive";
|
||||
"trait" = "trait";
|
||||
"interface" = "trait";
|
||||
"method" = "method";
|
||||
"function" = "function";
|
||||
"namespace" = "module";
|
||||
"boolean" = "literal";
|
||||
"character" = "literal";
|
||||
"number" = "literal";
|
||||
"string" = "string";
|
||||
"keyword" = "keyword";
|
||||
"documentation" = "comment";
|
||||
"comment" = "comment";
|
||||
"escapeSequence" = "format";
|
||||
"formatSpecifier" = "format";
|
||||
"operator" = "operator";
|
||||
"arithmetic" = "operator";
|
||||
"bitwise" = "operator";
|
||||
"comparison" = "operator";
|
||||
"logical" = "operator";
|
||||
"macro" = "macro";
|
||||
"lifetime" = "lifetime";
|
||||
"variable" = "variable";
|
||||
"attribute" = "attribute";
|
||||
"punctuation" = "punctuation";
|
||||
}) }
|
||||
'';
|
||||
});
|
||||
|
||||
in {
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
||||
(pkgs.kakoune.override {
|
||||
plugins = with kakounePlugins; [
|
||||
|
||||
# Custom config
|
||||
kakrc
|
||||
|
||||
# Kakoune language server support
|
||||
(symlinkJoin {
|
||||
paths = [
|
||||
|
||||
# The language server client
|
||||
kak-lsp
|
||||
|
||||
# Include default language servers
|
||||
rnix-lsp
|
||||
haskell-language-server
|
||||
|
||||
# Overwrite kak-lsp.toml
|
||||
kak-lsp-config
|
||||
|
||||
];
|
||||
name = "kak-lsp-${kak-lsp.version}";
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/kak-lsp --add-flags "--config $out/share/kak-lsp/kak-lsp.toml"
|
||||
'';
|
||||
})
|
||||
|
||||
] ++ colors;
|
||||
})
|
||||
|
||||
];
|
||||
}
|
38
modules/kak/colors.nix
Normal file
38
modules/kak/colors.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ theme, lib, pkgs }:
|
||||
|
||||
pkgs.writeTextFile (rec {
|
||||
name = "colors.kak";
|
||||
destination = "/share/kak/colors/${name}";
|
||||
text = with theme; ''
|
||||
|
||||
face global comment rgb:828282
|
||||
|
||||
face global value rgb:${green.normal}
|
||||
face global string rgb:${green.normal}
|
||||
face global keyword rgb:${misc.blueGrey}
|
||||
face global operator rgb:${cyan.normal}
|
||||
face global function rgb:${cyan.normal}
|
||||
face global builtin rgb:${orange.normal}
|
||||
face global module rgb:${yellow.normal}
|
||||
face global meta rgb:${green.bright}
|
||||
face global type rgb:${blue.bright}
|
||||
face global trait rgb:${purple.bright}
|
||||
face global macro +b@meta
|
||||
face global method function
|
||||
face global variant rgb:${blue.normal}
|
||||
|
||||
face global LineNumbers rgb:${background.slight}
|
||||
face global BufferPadding rgb:${background.slight}
|
||||
face global LineNumberCursor rgb:${foreground.primary}
|
||||
face global crosshairs_line default,rgb:212121
|
||||
face global MenuForeground default,rgb:${blue.normal}
|
||||
face global MenuBackground default,rgb:313131
|
||||
|
||||
face global DiagnosticWarning default,default,yellow+c
|
||||
face global DiagnosticError default,default,red+c
|
||||
face global DiagnosticHint default,default,green+c
|
||||
|
||||
face global Reference default,rgb:323232,default
|
||||
|
||||
'';
|
||||
})
|
52
modules/kak/default.nix
Normal file
52
modules/kak/default.nix
Normal file
|
@ -0,0 +1,52 @@
|
|||
{ lib, pkgs, config, ... }:
|
||||
|
||||
with pkgs.kakouneUtils;
|
||||
|
||||
let cfg = config.custom.kak;
|
||||
theme = config.custom.gui.theme;
|
||||
kak-crosshairs = buildKakounePlugin (rec {
|
||||
name = "kak-crosshairs";
|
||||
src = (pkgs.fetchFromGitHub {
|
||||
owner = "insipx";
|
||||
repo = name;
|
||||
rev = "7edba13c535ce1bc67356b1c9461f5d261949d29";
|
||||
sha256 = "sha256-VOn9GGHludJasEwcCv6t1Q3/63w9139MCEkdRDnTw6E";
|
||||
});
|
||||
});
|
||||
in
|
||||
|
||||
with lib; {
|
||||
|
||||
options.custom.kak = {
|
||||
|
||||
enable = (mkEnableOption "kakoune editor") // { default = true; };
|
||||
|
||||
rust = mkEnableOption "Rust support in Kakoune";
|
||||
ts = mkEnableOption "TypeScript support in Kakoune";
|
||||
haskell = mkEnableOption "Haskell support in Kakoune";
|
||||
python = mkEnableOption "Python 3.9 support in Kakoune";
|
||||
nix = (mkEnableOption "Nix support in Kakoune") // { default = true; };
|
||||
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable) {
|
||||
|
||||
environment.systemPackages = [
|
||||
(import ./kakoune.nix {
|
||||
|
||||
typescript = cfg.ts;
|
||||
haskell = cfg.haskell;
|
||||
python = cfg.python;
|
||||
rust = cfg.rust;
|
||||
nix = cfg.nix;
|
||||
|
||||
inherit kak-crosshairs;
|
||||
|
||||
inherit pkgs lib theme;
|
||||
|
||||
})
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
}
|
132
modules/kak/kak-lsp.nix
Normal file
132
modules/kak/kak-lsp.nix
Normal file
|
@ -0,0 +1,132 @@
|
|||
{
|
||||
# Feature flags
|
||||
typescript ? false,
|
||||
haskell ? false,
|
||||
clojure ? false,
|
||||
python ? false,
|
||||
rust ? false,
|
||||
nix ? true,
|
||||
|
||||
# Build context
|
||||
pkgs,
|
||||
lib
|
||||
}:
|
||||
|
||||
with lib;
|
||||
with pkgs;
|
||||
|
||||
let semantic-tokens =
|
||||
let mk = (name: value: ''
|
||||
[[semantic_tokens]]
|
||||
token = "${name}"
|
||||
face = "${value}"
|
||||
''); in concatStringsSep "\n" (mapAttrsToList mk {
|
||||
"enumMember" = "variant";
|
||||
"enum" = "enum";
|
||||
"union" = "union";
|
||||
"struct" = "struct";
|
||||
"typeAlias" = "alias";
|
||||
"builtinType" = "primitive";
|
||||
"trait" = "trait";
|
||||
"interface" = "trait";
|
||||
"method" = "method";
|
||||
"function" = "function";
|
||||
"namespace" = "module";
|
||||
"boolean" = "literal";
|
||||
"character" = "literal";
|
||||
"number" = "literal";
|
||||
"string" = "string";
|
||||
"keyword" = "keyword";
|
||||
"documentation" = "comment";
|
||||
"comment" = "comment";
|
||||
"escapeSequence" = "format";
|
||||
"formatSpecifier" = "format";
|
||||
"operator" = "operator";
|
||||
"arithmetic" = "operator";
|
||||
"bitwise" = "operator";
|
||||
"comparison" = "operator";
|
||||
"logical" = "operator";
|
||||
"macro" = "macro";
|
||||
"macroBang" = "macro";
|
||||
"lifetime" = "lifetime";
|
||||
"variable" = "variable";
|
||||
"attribute" = "attribute";
|
||||
"punctuation" = "punctuation";
|
||||
});
|
||||
|
||||
kak-lsp-config-text = concatStringsSep "\n" (
|
||||
(optional (rust || haskell || clojure) semantic-tokens)
|
||||
++ (optional rust ''
|
||||
[language.rust]
|
||||
filetypes = [ "rust" ]
|
||||
roots = [ "Cargo.toml" ]
|
||||
command = "rust-analyzer"
|
||||
[language.rust.settings.rust-analyzer]
|
||||
semanticTokens = true
|
||||
diagnostics.enabled = [ "unresolved-proc-macro" ]
|
||||
cargo.loadOutDirsFromCheck = true
|
||||
procMacro.enable = false
|
||||
'')
|
||||
++ (optional nix ''
|
||||
[language.nix]
|
||||
filetypes = [ "nix" ]
|
||||
roots = [ "flake.nix", "shell.nix", ".git", ".hg" ]
|
||||
command = "rnix-lsp"
|
||||
'')
|
||||
++ (optional haskell ''
|
||||
[language.haskell]
|
||||
filetypes = [ "haskell" ]
|
||||
roots = [ "Setup.hs", "stack.yaml", "*.cabal" ]
|
||||
command = "haskell-language-server-wrapper"
|
||||
args = [ "--lsp" ]
|
||||
'')
|
||||
++ (optional clojure ''
|
||||
[language.clojure]
|
||||
filetypes = ["clojure"]
|
||||
roots = ["project.clj", "deps.edn", ".lsp/config.edn", ".git/"]
|
||||
command = "clojure-lsp"
|
||||
'')
|
||||
++ (optional python ''
|
||||
[language.python]
|
||||
filetypes = [ "python" ]
|
||||
roots = [ "setup.py", ".git", ".hg" ]
|
||||
command = "pylsp"
|
||||
'')
|
||||
++ (optional typescript ''
|
||||
[language.typescript]
|
||||
filetypes = ["typescript", "javascript"]
|
||||
roots = ["package.json"]
|
||||
command = "rslint-lsp"
|
||||
''));
|
||||
|
||||
kak-lsp-config = (pkgs.writeTextFile (rec {
|
||||
name = "kak-lsp.toml";
|
||||
destination = "/share/kak-lsp/${name}";
|
||||
text = kak-lsp-config-text;
|
||||
}));
|
||||
|
||||
in (symlinkJoin {
|
||||
|
||||
name = "kak-lsp-${kak-lsp.version}";
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
|
||||
paths = with kakounePlugins; [
|
||||
|
||||
# The language server client
|
||||
kak-lsp
|
||||
|
||||
# Overwrite kak-lsp.toml
|
||||
kak-lsp-config
|
||||
|
||||
] ++ (optional nix rnix-lsp)
|
||||
++ (optional typescript rslint)
|
||||
++ (optional haskell haskell-language-server)
|
||||
++ (optional clojure clojure-lsp)
|
||||
++ (optional python python39Packages.python-lsp-server)
|
||||
++ (optional rust rust-analyzer);
|
||||
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/kak-lsp --add-flags "--config $out/share/kak-lsp/kak-lsp.toml"
|
||||
'';
|
||||
|
||||
})
|
70
modules/kak/kakoune.nix
Normal file
70
modules/kak/kakoune.nix
Normal file
|
@ -0,0 +1,70 @@
|
|||
# Preconfigured kakoune editor.
|
||||
|
||||
{
|
||||
# Feature flags
|
||||
clipboard ? false,
|
||||
typescript ? false,
|
||||
haskell ? false,
|
||||
clojure ? false,
|
||||
python ? false,
|
||||
rust ? false,
|
||||
nix ? true,
|
||||
|
||||
# Allow extra plugins to be defined
|
||||
# outside of the package
|
||||
extraPlugins ? [],
|
||||
|
||||
# Plugins
|
||||
kak-crosshairs,
|
||||
|
||||
# Color theme
|
||||
theme,
|
||||
|
||||
# Build context
|
||||
pkgs,
|
||||
lib
|
||||
}:
|
||||
|
||||
let kakrc = (import ./kakrc.nix {
|
||||
inherit clipboard
|
||||
typescript
|
||||
haskell
|
||||
clojure
|
||||
python
|
||||
rust
|
||||
nix
|
||||
theme
|
||||
pkgs
|
||||
lib;
|
||||
});
|
||||
|
||||
colors = (import ./colors.nix {
|
||||
inherit theme
|
||||
pkgs
|
||||
lib;
|
||||
});
|
||||
|
||||
kak-lsp = (import ./kak-lsp.nix {
|
||||
inherit typescript
|
||||
haskell
|
||||
clojure
|
||||
python
|
||||
rust
|
||||
nix
|
||||
pkgs
|
||||
lib;
|
||||
});
|
||||
|
||||
in (pkgs.kakoune.override {
|
||||
plugins = [
|
||||
|
||||
# Configuration
|
||||
kak-lsp
|
||||
colors
|
||||
kakrc
|
||||
|
||||
# Plugins
|
||||
kak-crosshairs
|
||||
|
||||
] ++ extraPlugins;
|
||||
})
|
223
modules/kak/kakrc.nix
Normal file
223
modules/kak/kakrc.nix
Normal file
|
@ -0,0 +1,223 @@
|
|||
# Defines the kakrc.
|
||||
|
||||
{
|
||||
# Feature flags
|
||||
clipboard ? false,
|
||||
typescript ? false,
|
||||
haskell ? false,
|
||||
clojure ? false,
|
||||
python ? false,
|
||||
rust ? false,
|
||||
nix ? true,
|
||||
|
||||
# Color theme
|
||||
theme,
|
||||
|
||||
# Build tools
|
||||
pkgs,
|
||||
lib,
|
||||
}:
|
||||
|
||||
|
||||
let keybinds = ''
|
||||
map global insert <a-tab> <esc>:buffer-next<ret>
|
||||
map global normal <a-tab> :buffer-next<ret>
|
||||
'' + (lib.optionalString clipboard ''
|
||||
map global user y <a-|>c<ret>
|
||||
map global user p !p<ret>
|
||||
'');
|
||||
|
||||
# Initialization code for IDE mode needed for every supported
|
||||
# language, and inlay diagnostics.
|
||||
ide-init = ''
|
||||
lsp-enable-window
|
||||
|
||||
hook window ModeChange .*:.*:insert %{
|
||||
lsp-inlay-diagnostics-disable window
|
||||
remove-highlighter window/lsp_diagnostics
|
||||
}
|
||||
hook window ModeChange .*:insert:normal %{
|
||||
lsp-inlay-diagnostics-enable window
|
||||
}
|
||||
'';
|
||||
|
||||
# Implies `ide-init`. Adds code actions and hover.
|
||||
ide-core = ''
|
||||
|
||||
${ide-init}
|
||||
|
||||
map buffer normal <tab> ': lsp-code-actions<ret>'
|
||||
map buffer normal <ret> ': lsp-hover<ret>'
|
||||
|
||||
'';
|
||||
|
||||
# Implies `ide-core`, which implies `ide-init`.
|
||||
ide-full = ''
|
||||
|
||||
${ide-core}
|
||||
|
||||
hook window -group semtok BufReload .* lsp-semantic-tokens
|
||||
hook window -group semtok NormalIdle .* lsp-semantic-tokens
|
||||
hook window -group semtok InsertIdle .* lsp-semantic-tokens
|
||||
|
||||
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window semtok }
|
||||
|
||||
map global normal <up> ': lsp-previous-symbol<ret>'
|
||||
map global normal <down> ': lsp-next-symbol<ret>'
|
||||
map global normal <a-down> ': lsp-hover-next-symbol<ret>'
|
||||
map global normal <a-up> ': lsp-hover-previous-symbol<ret>'
|
||||
|
||||
map global normal <a-left> ': lsp-previous-location *goto*<ret>'
|
||||
map global normal <a-right> ': lsp-next-location *goto*<ret>'
|
||||
|
||||
''; in
|
||||
|
||||
|
||||
# Nix hacking-related configuration. Nix has a very weak language
|
||||
# server, and it basically only supports `ide-init` (for completions).
|
||||
let nix-config = (lib.optionalString nix ''
|
||||
hook global WinSetOption filetype=nix %{
|
||||
${ide-init}
|
||||
face global keyword rgb:${theme.cyan.normal}
|
||||
}
|
||||
'');
|
||||
|
||||
# Sometimes work requires me to touch the frontend. Ew. `ide-core`
|
||||
# suffices here.
|
||||
typescript-config = (lib.optionalString typescript ''
|
||||
hook global WinSetOption filetype=(javascript|typescript) %{
|
||||
${ide-core}
|
||||
}
|
||||
'');
|
||||
|
||||
# Python-related config. Python does not support more features than
|
||||
# those in `ide-core`.
|
||||
python-config = (lib.optionalString python ''
|
||||
hook global WinSetOption filetype=python %{
|
||||
|
||||
${ide-core}
|
||||
|
||||
face window keyword rgb:${theme.green.bright}
|
||||
face window meta keyword
|
||||
|
||||
}
|
||||
'');
|
||||
|
||||
# Clojure-lsp has all the IDE features I use.
|
||||
clojure-config = (lib.optionalString clojure ''
|
||||
hook global WinSetOption filetype=clojure %{
|
||||
${ide-full}
|
||||
}
|
||||
'');
|
||||
|
||||
# Haskell development. Haskell has a language server with
|
||||
# the features in `ide-full`.
|
||||
haskell-config = (lib.optionalString haskell ''
|
||||
hook global WinSetOption filetype=haskell %{
|
||||
|
||||
${ide-full}
|
||||
|
||||
set-option buffer tabstop 2
|
||||
|
||||
face global variable rgb:${theme.purple.normal}
|
||||
face global attribute keyword
|
||||
face global operator keyword
|
||||
face global keyword rgb:${theme.blue.bright}
|
||||
face global value string
|
||||
face global meta rgb:${theme.pink.normal}
|
||||
|
||||
}
|
||||
'');
|
||||
|
||||
# Rust development. Rust's language servers all support the
|
||||
# `ide-full` features.
|
||||
rust-config = (lib.optionalString rust ''
|
||||
hook global WinSetOption filetype=rust %{
|
||||
|
||||
${ide-full}
|
||||
|
||||
hook global -group yeet ModuleLoaded rust %{
|
||||
|
||||
# Override the Rust highlighting with semantic
|
||||
# tokens supplied by the LSP client
|
||||
remove-hooks global rust-highlight
|
||||
remove-highlighter shared/rust
|
||||
|
||||
# Request tokens
|
||||
lsp-semantic-tokens
|
||||
|
||||
# Self-destruct this hook (it should only run once)
|
||||
remove-hooks global yeet
|
||||
|
||||
}
|
||||
|
||||
hook global NormalIdle .* %{ lsp-highlight-references }
|
||||
hook global InsertMove .* %{ lsp-highlight-references }
|
||||
|
||||
face global type rgb:${theme.blue.normal}
|
||||
face global trait rgb:${theme.purple.normal}
|
||||
face global macro rgb:${theme.green.bright}
|
||||
face global format rgb:${theme.orange.bright}
|
||||
face global attribute rgb:${theme.orange.bright}
|
||||
face global operator rgb:${theme.yellow.normal}
|
||||
face global function rgb:${theme.green.bright}
|
||||
face global keyword rgb:${theme.misc.blueGrey}
|
||||
|
||||
face global variable white
|
||||
face global value white
|
||||
face global meta white
|
||||
|
||||
face global alias rgb:${theme.orange.normal}
|
||||
face global enum type
|
||||
face global struct type
|
||||
face global union type
|
||||
|
||||
face global lifetime rgb:${theme.pink.pastel}
|
||||
|
||||
face global module rgb:ffffff
|
||||
|
||||
}
|
||||
'');
|
||||
|
||||
in pkgs.writeTextFile (rec {
|
||||
name = "kakrc.kak";
|
||||
destination = "/share/kak/autoload/${name}";
|
||||
text = ''
|
||||
set global tabstop 4
|
||||
set global indentwidth 4
|
||||
|
||||
eval %sh{ kak-lsp --kakoune -s $kak_session }
|
||||
|
||||
add-highlighter global/ number-lines -separator ' │ ' -hlcursor
|
||||
|
||||
face global InlayHint rgb:828282
|
||||
face global InlayDiagnosticWarning rgb:a39e31+f
|
||||
face global InlayDiagnosticError rgb:ad494f+f
|
||||
face global InlayDiagnosticHint rgb:4d965a+f
|
||||
face global InlayDiagnosticInfo rgb:4d965a+f
|
||||
|
||||
hook global WinSetOption filetype=markdown %{
|
||||
hook window -group spellck BufReload .* spell
|
||||
hook window -group spellck NormalIdle .* spell
|
||||
hook window -group spellck InsertIdle .* spell
|
||||
|
||||
hook -once -always window WinSetOption filetype=.* %{
|
||||
remove-hooks window spellck
|
||||
}
|
||||
}
|
||||
|
||||
${keybinds}
|
||||
|
||||
${typescript-config}
|
||||
${haskell-config}
|
||||
${clojure-config}
|
||||
${python-config}
|
||||
${rust-config}
|
||||
${nix-config}
|
||||
|
||||
hook global KakBegin .* %{
|
||||
cursorline
|
||||
colorscheme colors
|
||||
}
|
||||
'';
|
||||
})
|
27
modules/mpd.nix
Normal file
27
modules/mpd.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let cfg = config.riley.mpd; in
|
||||
|
||||
with lib; {
|
||||
|
||||
options.riley.mpd = {
|
||||
enable = mkEnableOption "music player daemon";
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable) {
|
||||
|
||||
# Enable the service
|
||||
home-manager.users."riley" = {
|
||||
services.mpd = {
|
||||
enable = true;
|
||||
musicDirectory = "$HOME/media/music";
|
||||
};
|
||||
};
|
||||
|
||||
users.users."riley".packages = with pkgs; [
|
||||
mpc_cli
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -15,4 +15,10 @@
|
|||
packages = with pkgs; [ openssh ];
|
||||
|
||||
};
|
||||
|
||||
users.users."root" = {
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGk/nBXhr3xWtbXBBkCuwqE6OixpRXCfscfxibgcCsTR me@riley.lgbt"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
11
overlays/default.nix
Normal file
11
overlays/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
self: super: {
|
||||
minecraft =
|
||||
let version = "2.2.2012";
|
||||
in super.minecraft.overrideAttrs (old: {
|
||||
inherit version;
|
||||
src = self.fetchurl {
|
||||
url = "https://launcher.mojang.com/download/linux/x86_64/minecraft-launcher_${version}.tar.gz";
|
||||
sha256 = "sha256-er+g/0pqsS5mDcZ5ID9kATuF3RwDQThue1mc/XRVms8=";
|
||||
};
|
||||
});
|
||||
}
|
9
scripts/README.md
Normal file
9
scripts/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Scripts
|
||||
|
||||
This directory contains nix derivations for shell scripts I want to use across
|
||||
devices.
|
||||
|
||||
| Filename | Scripts | Description |
|
||||
| ---------- | -------- | ------------------------------------------ |
|
||||
| `clip.nix` | `c`, `p` | Copy and paste abstractions |
|
||||
| `sc.nix` | `sc` | Area screenshot tool with clip integration |
|
12
scripts/bitwarden.nix
Normal file
12
scripts/bitwarden.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ pkgs, ... }: with pkgs; {
|
||||
|
||||
# Get a password entry from the list
|
||||
pw = (writeShellApplication {
|
||||
name = "pw";
|
||||
runtimeInputs = [ rbw skim ];
|
||||
text = ''
|
||||
x=$(rbw list | sk) && rbw "$@" "$x"
|
||||
'';
|
||||
});
|
||||
|
||||
}
|
17
scripts/clip.nix
Normal file
17
scripts/clip.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{ pkgs, ... }: with pkgs; {
|
||||
|
||||
# Copy something to the clipboard
|
||||
c = (writeShellApplication {
|
||||
name = "c";
|
||||
runtimeInputs = [ xclip ];
|
||||
text = "xclip -sel clip -i";
|
||||
});
|
||||
|
||||
# Paste something from the clipboard
|
||||
p = (writeShellApplication {
|
||||
name = "p";
|
||||
runtimeInputs = [ xclip ];
|
||||
text = "xclip -sel clip -o";
|
||||
});
|
||||
|
||||
}
|
12
scripts/sc.nix
Normal file
12
scripts/sc.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ pkgs, ... }: with pkgs; {
|
||||
|
||||
# Take a screenshot of a selected area and put it in the clipboard.
|
||||
sc = (writeShellApplication {
|
||||
name = "sc";
|
||||
runtimeInputs = [ xclip scrot ];
|
||||
text = ''
|
||||
scrot -z -s - | tee /tmp/sc.png | xclip -i -sel clip -t image/png
|
||||
'';
|
||||
});
|
||||
|
||||
}
|
8
secrets/secrets.nix
Normal file
8
secrets/secrets.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
let sif = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIXreYQgV6lS0rJ1NlAbgq3Iv5FJ8o1MOr08NhLTGFG";
|
||||
thor = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILniE+LdfdV9V9+Zj5gJXqKEv1CzQaEySy1u5OdbKa8d";
|
||||
in {
|
||||
"website.age".publicKeys = [
|
||||
thor
|
||||
sif
|
||||
];
|
||||
}
|
10
secrets/website.age
Normal file
10
secrets/website.age
Normal file
|
@ -0,0 +1,10 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 qlXMTg b+IgpHsZOeqs3rHFs6BE2kXFKh0ya5Qr8WKqgNO5rDA
|
||||
a/LM3SIob+udnVsqIqUkR7xdE7fa1TyQhOZbjQRsnV0
|
||||
-> ssh-ed25519 ZEUNCQ PErAc4AM7H1zYFv4OlFkZVGJlze6nTvmmEt1y+x4tDY
|
||||
2HwpQ+2B/zXatOCKUPSabRu2ZWcTTODzheDkxngcQi4
|
||||
-> j]Pn\)-grease uQI:D GZvyy
|
||||
9/Z0dk6R1bUhJbN32W3id9q959Nn0+jVL2dzDxLDHjacDeldJ4WuxrEzl0xdMUNE
|
||||
YaFJepKcRKR9
|
||||
--- X8YEMtOmM0Mr71UzVA8gKozDYk5S53XSmBxjpSP6PbQ
|
||||
‡Ì/‡Å&!.¼l1d)õ©›:í=T<>öÖÿÉ<C3BF>ï P^º/Çf‘V†F0$ç_Ƀ
|
Loading…
Reference in a new issue