Move config for kalle-pc into new repo layout

main
kalle 2024-12-11 00:55:41 +01:00
parent 0de189372b
commit 04ad416f64
40 changed files with 2047 additions and 557 deletions

View File

@ -30,11 +30,12 @@
};
outputs =
{ self
, nixpkgs
, home-manager
, ...
} @ inputs:
{
self,
nixpkgs,
home-manager,
...
}@inputs:
let
inherit (self) outputs;
in
@ -43,23 +44,24 @@
nixosConfigurations = {
"kalle-pc" = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs outputs; };
modules = [ ./nixos/kalle-pc/configuration.nix ];
specialArgs = {
inherit inputs outputs;
};
modules = [ ./hosts/kalle-pc ];
};
"kalle-laptop" = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs outputs; };
specialArgs = {
inherit inputs outputs;
};
modules = [ ./nixos/kalle-laptop/configuration.nix ];
};
};
homeConfigurations = {
"kalle@kalle-pc" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
extraSpecialArgs = { inherit inputs outputs; };
modules = [ ./home-manager/kalle-pc/kalle.nix ];
};
"kalle@kalle-laptop" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
extraSpecialArgs = { inherit inputs outputs; };
extraSpecialArgs = {
inherit inputs outputs;
};
modules = [ ./home-manager/kalle-laptop/kalle.nix ];
};
};

View File

@ -8,269 +8,5 @@
}:
{
home = {
username = "kalle";
homeDirectory = "/home/kalle";
};
imports = [
../../nvim
../../tmux
../../eww
../../hyprland
../../hyprland/hyprpaper.nix
../../ags
];
hyprland =
let
mod = "SUPER";
in
{
mod = mod;
primaryMonitor = "DP-2";
monitors = [
{
name = "DP-2";
width = 1920;
height = 1080;
refreshRate = 144;
x = 0;
y = 1080;
vrr = 1;
}
{
name = "HDMI-A-1";
width = 1920;
height = 1080;
x = 1500;
y = 0;
}
{
name = "HDMI-A-2";
width = 1920;
height = 1080;
x = 1920;
y = 1080;
transform = 3;
}
];
autoStart = [
# Bar
"${pkgs.ags}/bin/ags"
"${pkgs.firefox}/bin/firefox"
"${pkgs.discord}/bin/discord"
"${pkgs.kitty}/bin/kitty"
];
environment = {
XCURSOR_SIZE = "24";
};
sensitivity = 0.1;
layout = "dwindle";
layerRules = {
"gtk-layer-shell" = [
"blur"
"ignorezero"
];
"notifications2" = [
"noanim"
"blur"
"ignorezero"
];
};
windowRules = {
# Auto workspace
firefox = [ "workspace 1 silent" ];
discord = [ "workspace name:HDMI-A-2" ];
};
windowRulesV2 = {
# ULauncher
"class:^(ulauncher)$" = [
"dimaround"
];
};
# Media keys
# bind = ,XF86AudioPlay, exec, playerctl --player plasma-browser-integration play-pause
# bind = ,XF86AudioPrev, exec, playerctl previous
# bind = ,XF86AudioNext, exec, playerctl next
# bind = ,XF86AudioLowerVolume, exec, playerctl --player plasma-browser-integration volume 0.01-
# bind = ,XF86AudioRaiseVolume, exec, playerctl --player plasma-browser-integration volume 0.01+
# This is a dumb work around for hyprland not passing ALT half the time with the pass dispatcher.
# bind = ALT, M, exec, xdotool key 'ALT+m'
# bind = ALT, B, exec, xdotool key 'ALT+b'
binds = {
"${mod}, return" = "exec, ${pkgs.kitty}/bin/kitty";
"${mod}, E" = "exec, ${pkgs.ulauncher}/bin/ulauncher-toggle #wofi --show drun";
"${mod}, Print" = "exec, ${pkgs.bash}/bin/bash -c \"grim -g \\\"$(slurp)\\\" - | wl-copy\"";
# Clipboard history
# bind = $mainMod, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy
};
mouseBinds = { };
};
hyprpaper = {
wallpaperFolder = "/home/kalle/Pictures/Wallpapers";
};
nixpkgs = {
overlays = with outputs.overlays; [ nvim-plugins ];
config = {
allowUnfree = true;
allowUnfreePredicate = _: true;
permittedInsecurePackages = [
"electron-25.9.0"
"electron-29.4.6"
];
};
};
# The home.packages option allows you to install Nix packages into your
# environment.
home.packages = with pkgs; [
discord
discord-canary
vesktop
chromium
httpie
kate
dolphin
ark
rustup
gcc
prismlauncher
pavucontrol
difftastic
sops
(obsidian.override { electron = electron_29-bin; })
unzip
vlc
feishin
cachix
];
programs.home-manager.enable = true;
programs.firefox = {
enable = true;
nativeMessagingHosts = [ pkgs.plasma-browser-integration ];
};
gtk = {
enable = true;
theme = {
name = "Adwaita-dark";
package = pkgs.gnome-themes-extra;
};
iconTheme = {
name = "breeze-dark";
package = pkgs.kdePackages.breeze-icons;
};
cursorTheme = {
name = "breeze_cursors";
package = pkgs.libsForQt5.breeze-qt5;
};
};
qt = {
enable = true;
style.name = "breeze";
};
dconf = {
enable = true;
settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
};
};
programs.bash = {
enable = true;
shellAliases = {
# Git aliases
gg = "git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an (%ae)%C(reset)' --all";
gca = "git add -A; git commit -a --amend --no-edit";
gs = "git status";
# Replace some commands with better versions
ssh = "kitty +kitten ssh";
diff = "${pkgs.difftastic}/bin/difft";
};
initExtra = ''
function open() {
xdg-open $@ &> /dev/null &
}
'';
};
programs.kitty = {
enable = true;
themeFile = "Catppuccin-Mocha";
settings = {
background_opacity = "0.8";
allow_remote_control = true;
enable_audio_bell = false;
};
};
programs.starship = {
enable = true;
settings = {
add_newline = true;
# Remove text from nix shell component
nix_shell.format = "via [$symbol]($style) ";
git_status.disabled = true;
package.disabled = true;
};
};
programs.direnv = {
enable = true;
enableBashIntegration = true;
nix-direnv.enable = true;
};
programs.git = {
enable = true;
userName = "Kalle Struik";
userEmail = "kalle@kallestruik.nl";
difftastic.enable = true;
extraConfig = {
init.defaultBranch = "main";
};
};
home.sessionVariables = {
EDITOR = "nvim";
};
# This value determines the Home Manager release that your configuration is
# compatible with. This helps avoid breakage when a new Home Manager release
# introduces backwards incompatible changes.
#
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
home.stateVersion = "23.05"; # Please read the comment before changing.
do.not.rebuild = migration in progress;
}

136
hosts/_base/default.nix Normal file
View File

@ -0,0 +1,136 @@
{
inputs,
pkgs,
...
}:
{
imports = [
inputs.home-manager.nixosModules.home-manager
];
nix.settings = {
# Enable flakes and new 'nix' command
experimental-features = "nix-command flakes";
# Deduplicate and optimize nix store
auto-optimise-store = true;
# Allow me to use cachix
trusted-users = [
"root"
"kalle"
];
};
nixpkgs.config.allowUnfree = true;
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
useXkbConfig = true; # use xkbOptions in tty.
};
# Enable CUPS to print documents.
services.printing.enable = true;
# Enable sound.
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
environment.systemPackages = with pkgs; [
xdg-user-dirs
];
fonts = {
enableDefaultPackages = true;
packages = with pkgs; [
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
fira-code
fira-code-symbols
(nerdfonts.override { fonts = [ "NerdFontsSymbolsOnly" ]; })
];
fontconfig = {
defaultFonts = {
serif = [
"Noto Serif"
"Symbols Nerd Font"
];
sansSerif = [
"Noto Sans"
"Symbols Nerd Font"
];
monospace = [
"Fira Code"
"Symbols Nerd Font Mono"
];
};
};
};
users.users.kalle = {
isNormalUser = true;
group = "kalle";
extraGroups = [
"wheel"
];
};
users.groups.kalle.gid = 1000;
home-manager.users.kalle = {
home = {
username = "kalle";
homeDirectory = "/home/kalle";
sessionVariables = {
EDITOR = "nvim";
};
};
programs.home-manager.enable = true;
# TODO: Make this be based on the system wide style
gtk = {
enable = true;
theme = {
name = "Adwaita-dark";
package = pkgs.gnome-themes-extra;
};
iconTheme = {
name = "breeze-dark";
package = pkgs.kdePackages.breeze-icons;
};
cursorTheme = {
name = "breeze_cursors";
package = pkgs.libsForQt5.breeze-qt5;
};
};
qt = {
enable = true;
style.name = "breeze";
};
dconf = {
enable = true;
settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
};
};
};
services.openssh.enable = true;
}

167
hosts/kalle-pc/default.nix Normal file
View File

@ -0,0 +1,167 @@
{
inputs,
config,
pkgs,
...
}:
{
imports = [
../_base
./hardware-configuration.nix
./hardware-configuration.override.nix
../../modules/sddm.nix
../../modules/hyprland.nix
../../modules/hyprpaper.nix
../../modules/bash.nix
../../modules/kitty.nix
../../modules/git.nix
../../modules/direnv.nix
../../modules/firefox.nix
../../modules/steam.nix
../../modules/nvim
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
services.btrfs.autoScrub.enable = true;
networking.hostName = "kalle-pc";
networking.networkmanager.enable = true;
time.timeZone = "Europe/Amsterdam";
services.xserver = {
enable = true;
xkb.layout = "us";
};
services.gvfs.enable = true;
# Allow flashing ZSA keyboards
hardware.keyboard.zsa.enable = true;
# No need for firewall, since this machine is always at home
networking.firewall.enable = false;
hyprland =
let
mod = "SUPER";
uwsm = "${pkgs.uwsm}/bin/uwsm";
mkUwsmApp = pkg: name: "${uwsm} app -- ${pkg}/share/applications/${name}.desktop";
in
{
mod = mod;
primaryMonitor = "DP-2";
monitors = [
{
name = "DP-2";
width = 1920;
height = 1080;
refreshRate = 144;
x = 0;
y = 1080;
vrr = 1;
}
{
name = "HDMI-A-1";
width = 1920;
height = 1080;
x = 1500;
y = 0;
}
{
name = "HDMI-A-2";
width = 1920;
height = 1080;
x = 1920;
y = 1080;
transform = 3;
}
];
autoStart = [
"${pkgs.ags}/bin/ags"
(mkUwsmApp pkgs.firefox "firefox")
(mkUwsmApp pkgs.discord "discord")
];
binds = {
"${mod}, return" = "exec, ${mkUwsmApp pkgs.kitty "kitty"}";
"${mod}, E" = "exec, ${pkgs.ulauncher}/bin/ulauncher-toggle #wofi --show drun";
"${mod}, Print" = "exec, ${pkgs.bash}/bin/bash -c \"grim -g \\\"$(slurp)\\\" - | wl-copy\"";
# Clipboard history
# bind = $mainMod, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy
};
sensitivity = 0.1;
layerRules = {
"gtk-layer-shell" = [
"blur"
"ignorezero"
];
"notifications2" = [
"noanim"
"blur"
"ignorezero"
];
};
windowRules = {
# Auto workspace
firefox = [ "workspace 1 silent" ];
discord = [ "workspace name:HDMI-A-2" ];
};
windowRulesV2 = {
# ULauncher
"class:^(ulauncher)$" = [
"dimaround"
];
};
};
hyprpaper.wallpaperFolder = "/home/kalle/Pictures/Wallpapers";
home-manager.users.kalle = {
home.packages = with pkgs; [
discord
discord-canary
vesktop
chromium
httpie
kate
dolphin
ark
rustup
gcc
prismlauncher
pavucontrol
difftastic
sops
unzip
vlc
feishin
cachix
];
};
# 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 = "23.05"; # Did you read the comment?
# This value determines the Home Manager release that your configuration is
# compatible with. This helps avoid breakage when a new Home Manager release
# introduces backwards incompatible changes.
#
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
home-manager.users.kalle.home.stateVersion = "23.05"; # Please read the comment before changing.
}

View File

@ -0,0 +1,68 @@
# 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 = [
"xhci_pci"
"ahci"
"usb_storage"
"usbhid"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=root" ];
};
fileSystems."/home" = {
device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=home" ];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=nix" ];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/23F6-1045";
fsType = "vfat";
};
fileSystems."/swap" = {
device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=swap" ];
};
swapDevices = [ ];
# 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.enp35s0.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,32 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
fileSystems = {
# Extra filesystem configs to enable compression.
"/".options = [ "compress=zstd" ];
"/home".options = [ "compress=zstd" ];
"/nix".options = [
"compress=zstd"
"noatime"
];
"/swap".options = [ "noatime" ];
# Mount other drives
"/mnt/games" = {
device = "/dev/disk/by-uuid/0ac05c3f-df12-458e-b145-e912febe1205";
fsType = "ext4";
};
"/mnt/external" = {
device = "/dev/disk/by-uuid/13e2dfc3-7b4d-44ac-9417-51b933a36917";
fsType = "ext4";
};
};
}

View File

@ -1,8 +1,9 @@
{ inputs
, lib
, config
, pkgs
, ...
{
inputs,
lib,
config,
pkgs,
...
}:
{
@ -23,27 +24,25 @@
cfg = config.hyprpaper;
hyprlandCfg = config.hyprland;
changeWallpaperScript =
pkgs.writeShellScriptBin
"change-wallpaper"
(lib.concatStringsSep
"\n"
(lib.flatten
(map
(m:
let
output = m.name;
wallpaper = "\"$(${pkgs.findutils}/bin/find -L \"${cfg.wallpaperFolder}\" -type f | ${pkgs.coreutils}/bin/shuf -n 1)\"";
in
[
"wallpaper=${wallpaper}"
"${pkgs.hyprland}/bin/hyprctl hyprpaper preload $wallpaper"
"${pkgs.hyprland}/bin/hyprctl hyprpaper wallpaper ${output},$wallpaper"
]
)
hyprlandCfg.monitors)
++ [ "${pkgs.hyprland}/bin/hyprctl hyprpaper unload all" ])
);
changeWallpaperScript = pkgs.writeShellScriptBin "change-wallpaper" (
lib.concatStringsSep "\n" (
lib.flatten (
map (
m:
let
output = m.name;
wallpaper = "\"$(${pkgs.findutils}/bin/find -L \"${cfg.wallpaperFolder}\" -type f | ${pkgs.coreutils}/bin/shuf -n 1)\"";
in
[
"wallpaper=${wallpaper}"
"${pkgs.hyprland}/bin/hyprctl hyprpaper preload $wallpaper"
"${pkgs.hyprland}/bin/hyprctl hyprpaper wallpaper ${output},$wallpaper"
]
) hyprlandCfg.monitors
)
++ [ "${pkgs.hyprland}/bin/hyprctl hyprpaper unload all" ]
)
);
in
{
hyprland.autoStart = [

View File

@ -0,0 +1,46 @@
import { GTK_ALIGN_CENTER, GTK_ALIGN_END, GTK_ALIGN_START } from "../constants.js"
import { Clock } from "./Clock.js"
import { SysTray } from "./Systray.js"
function BarStart() {
return Widget.Box({
halign: GTK_ALIGN_START,
children: [
Widget.Label({ label: "Start" }),
Widget.Button({ label: "Button", onClicked: () => App.ToggleWindow("media2") }),
],
})
}
function BarCenter() {
return Widget.Box({
halign: GTK_ALIGN_CENTER,
children: [
Clock(),
],
})
}
function BarEnd() {
return Widget.Box({
halign: GTK_ALIGN_END,
children: [
SysTray(),
],
})
}
export function Bar(monitor = 0) {
return Widget.Window({
monitor,
exclusivity: "exclusive",
className: "bar",
margins: [5, 5, 0, 5],
name: `bar${monitor}`,
anchor: ["left", "top", "right"],
child: Widget.CenterBox({
vertical: false,
startWidget: BarStart(),
centerWidget: BarCenter(),
endWidget: BarEnd(),
})
})
}

View File

@ -0,0 +1,24 @@
const time = Variable("", {
poll: [1000, 'date "+%H:%M"'],
})
const date = Variable("", {
poll: [1000, 'date "+%Y-%m-%d"'],
})
export function Clock() {
return Widget.Box({
className: "clock",
vertical: true,
children: [
Widget.Label({
className: "time",
label: time.bind(),
}),
Widget.Label({
className: "date",
label: date.bind(),
}),
],
})
}

View File

@ -0,0 +1,16 @@
const systemtray = await Service.import("systemtray")
export function SysTray() {
const items = systemtray.bind("items")
.as(items => items.map(item => Widget.Button({
child: Widget.Icon({ icon: item.bind("icon") }),
on_primary_click: (_, event) => item.activate(event),
on_secondary_click: (_, event) => item.openMenu(event),
tooltip_markup: item.bind("tooltip_markup"),
})))
return Widget.Box({
className: "systray",
children: items,
})
}

View File

@ -0,0 +1,35 @@
@define-color ctp-rosewater #f5e0dc;
@define-color ctp-flamingo #f2cdcd;
@define-color ctp-pink #f5c2e7;
@define-color ctp-mauve #cba6f7;
@define-color ctp-red #f38ba8;
@define-color ctp-maroon #eba0ac;
@define-color ctp-peach #fab387;
@define-color ctp-yellow #f9e2af;
@define-color ctp-green #a6e3a1;
@define-color ctp-teal #94e2d5;
@define-color ctp-sky #89dceb;
@define-color ctp-sapphire #74c7ec;
@define-color ctp-blue #89b4fa;
@define-color ctp-lavender #b4befe;
@define-color ctp-text #cdd6f4;
@define-color ctp-subtext1 #bac2de;
@define-color ctp-subtext0 #a6adc8;
@define-color ctp-overlay2 #9399b2;
@define-color ctp-overlay1 #7f849c;
@define-color ctp-overlay0 #6c7086;
@define-color ctp-surface2 #585b70;
@define-color ctp-surface1 #45475a;
@define-color ctp-surface0 #313244;
@define-color ctp-base #1e1e2e;
@define-color ctp-mantle #181825;
@define-color ctp-crust #11111b;
button {
background: @ctp-surface0;
border: none;
}
button:active, button:hover, button:focus {
background: @ctp-surface1;
}

View File

@ -0,0 +1,14 @@
import { Media } from "./media/Media.js";
import { Bar } from "./bar/Bar.js";
import { Notifications } from "./notifications/Notifications.js";
App.config({
style: "./style.css",
windows: [
Bar(2),
Media(2),
Notifications(2),
]
})

View File

@ -0,0 +1,5 @@
export const GTK_ALIGN_FILL = 0;
export const GTK_ALIGN_START = 1;
export const GTK_ALIGN_END = 2;
export const GTK_ALIGN_CENTER = 3;
export const GTK_ALIGN_BASELINE = 4;

View File

@ -0,0 +1,160 @@
import { GTK_ALIGN_CENTER, GTK_ALIGN_FILL } from '../constants.js'
const mpris = await Service.import("mpris")
const players = mpris.bind("players")
const FALLBACK_ICON = "audio-x-generic-symbolic"
const PLAY_ICON = "media-playback-start-symbolic"
const PAUSE_ICON = "media-playback-pause-symbolic"
const PREV_ICON = "media-skip-backward-symbolic"
const NEXT_ICON = "media-skip-forward-symbolic"
/** @param {number} length */
function lengthStr(length) {
const min = Math.floor(length / 60)
const sec = Math.floor(length % 60)
const sec0 = sec < 10 ? "0" : ""
return `${min}:${sec0}${sec}`
}
/** @param {import('types/service/mpris').MprisPlayer} player */
function Player(player) {
const artists = player.bind("track_artists").transform(a => a.join(", "))
const playPause = Widget.Button({
className: "play-pause",
onClicked: () => player.playPause(),
visible: player.bind("can_play"),
child: Widget.Icon({
icon: player.bind("play_back_status").transform(s => {
switch (s) {
case "Playing": return PAUSE_ICON
case "Paused":
case "Stopped": return PLAY_ICON
}
}),
}),
})
const prev = Widget.Button({
onClicked: () => player.previous(),
visible: player.bind("can_go_prev"),
child: Widget.Icon(PREV_ICON),
})
const next = Widget.Button({
onClicked: () => player.next(),
visible: player.bind("can_go_next"),
child: Widget.Icon(NEXT_ICON),
})
const positionSlider = Widget.Slider({
className: "position",
drawValue: false,
onChange: ({ value }) => player.position = value * player.length,
visible: player.bind("length").as(l => l > 0),
setup: self => {
function update() {
const value = player.position / player.length
self.value = value > 0 ? value : 0
}
self.hook(player, update)
self.hook(player, update, "position")
self.poll(1000, update)
},
})
const positionLabel = Widget.Label({
className: "position",
hpack: "start",
setup: self => {
const update = (_, time) => {
self.label = lengthStr(time || player.position)
self.visible = player.length > 0
}
self.hook(player, update, "position")
self.poll(1000, update)
},
})
const lengthLabel = Widget.Label({
className: "length",
hpack: "end",
visible: player.bind("length").transform(l => l > 0),
label: player.bind("length").transform(lengthStr),
})
return Widget.Overlay({
className: "player",
child: Widget.Box({
className: "bg-img",
vpack: "start",
css: player.bind("cover_path").transform(p => `background-image: url('${p}');`),
}),
overlays: [
Widget.Box({
className: "bg-cover"
}),
Widget.Box({
className: "overlay",
vertical: true,
halign: GTK_ALIGN_CENTER,
children: [
Widget.Box({
className: "info",
vertical: true,
children: [
Widget.Label({ className: "title", label: player.bind("track_title") }),
Widget.Label({ className: "album", label: player.bind("track_album") }),
Widget.Label({ className: "artist", label: artists }),
],
}),
Widget.Box({
vexpand: true,
}),
Widget.CenterBox({
className: "controls",
startWidget: positionLabel,
centerWidget: Widget.Box({
halign: GTK_ALIGN_CENTER,
spacing: 20,
children: [
prev,
playPause,
next,
],
}),
endWidget: lengthLabel,
}),
positionSlider,
],
})
],
})
}
function MediaContent() {
const currentIdx = Variable(0);
const currentPlayer = Utils.merge([currentIdx.bind(), players], (currentIdx, players) => {
const idx = Math.min(currentIdx, players.length - 1);
return players[idx];
})
return Widget.Box({
children: currentPlayer.as(p => [Player(p)]),
})
}
export function Media(monitor = 0) {
return Widget.Window({
monitor,
visible: false,
exclusivity: "normal",
className: "media",
margins: [10, 10, 0, 10],
name: `media${monitor}`,
anchor: ["left", "top"],
child: MediaContent(),
})
}

View File

@ -0,0 +1,59 @@
.media > box {
border-radius: 5px;
background-color: transparent;
color: @ctp-text;
}
.media .player .bg-img {
border-radius: 5px;
min-width: 400px;
min-height: 200px;
background-size: cover;
}
.media .player .bg-cover {
background: linear-gradient(alpha(@ctp-base, 0.5), @ctp-base);
}
.media .player .overlay {
border-radius: 5px;
min-width: 400px;
}
.media .player .info {
padding: 10px;
}
.media .player .controls {
padding: 10px;
}
.media .player .info .title {
font-size: 1.2em;
font-weight: bold;
}
.media .player scale.position {
padding: 0;
border-radius: 0;
border: none;
}
.media .player scale.position trough {
min-height: 4px;
border-radius: 0;
border: none;
background-color: @ctp-overlay0;
}
.media .player scale.position highlight {
border-radius: 0;
border: none;
background-color: @ctp-lavender;
}
.media .player scale.position slider {
all: unset;
}

View File

@ -0,0 +1,129 @@
const notifications = await Service.import("notifications")
/** @param {import('resource:///com/github/Aylur/ags/service/notifications.js').Notification} n */
function NotificationIcon({ app_entry, app_icon, image }) {
if (image) {
return Widget.Box({
css: `background-image: url("${image}");`
+ "background-size: contain;"
+ "background-repeat: no-repeat;"
+ "background-position: center;",
})
}
let icon = "dialog-information-symbolic"
if (Utils.lookUpIcon(app_icon))
icon = app_icon
if (app_entry && Utils.lookUpIcon(app_entry))
icon = app_entry
return Widget.Box({
child: Widget.Icon(icon),
})
}
/** @param {import('resource:///com/github/Aylur/ags/service/notifications.js').Notification} n */
function Notification(n) {
const icon = Widget.Box({
vpack: "start",
class_name: "icon",
child: NotificationIcon(n),
})
const title = Widget.Label({
class_name: "title",
xalign: 0,
justification: "left",
hexpand: true,
max_width_chars: 24,
label: n.summary,
use_markup: true,
})
const body = Widget.Label({
class_name: "body",
hexpand: true,
use_markup: true,
xalign: 0,
justification: "left",
label: n.body,
wrap: true,
})
const content = Widget.Box({
className: "content",
children: [
icon,
Widget.Box({
vertical: true,
children: [
title,
body,
]
}),
],
})
const actions = Widget.Box({
className: "actions",
children: n.actions.map(({ id, label }) => Widget.Button({
className: "action",
on_clicked: () => {
n.invoke(id)
n.dismiss()
},
hexpand: true,
child: Widget.Label(label),
})),
})
return Widget.EventBox({
attribute: { id: n.id },
onPrimaryClick: n.dismiss,
child: Widget.Box({
classNames: ["notification", n.urgency],
vertical: true,
children: [
content,
actions,
],
}),
})
}
function NotificationList() {
const list = Widget.Box({
css: "min-width: 2px; min-height: 2px;",
vertical: true,
spacing: 10,
children: notifications.popups.map(Notification),
})
function onNotified(_, /** @type {number} */ id) {
const n = notifications.getNotification(id)
if (n)
list.children = [Notification(n), ...list.children]
}
function onDismissed(_, /** @type {number} */ id) {
list.children.find(n => n.attribute.id === id)?.destroy()
}
list.hook(notifications, onNotified, "notified")
.hook(notifications, onDismissed, "dismissed")
return list
}
export function Notifications(monitor = 0) {
return Widget.Window({
monitor,
exclusivity: "normal",
className: "notifications",
margins: [10, 10, 10, 10],
name: `notifications${monitor}`,
anchor: ["left", "top"],
child: NotificationList(),
})
}

View File

@ -0,0 +1,59 @@
.notification {
min-width: 300px;
padding: 10px;
background-color: alpha(@ctp-base, 0.7);
border-radius: 5px;
border: 1px solid;
border-left: 5px solid;
border-color: @ctp-overlay1;
}
.notification.low {
border-color: @ctp-base;
}
.notification.critical {
border-color: @ctp-red;
}
.notification .icon {
min-width: 68px;
min-height: 68px;
margin-right: 1em;
}
.notification .icon image {
font-size: 58px;
/* to center the icon */
margin: 5px;
color: @ctp-text;
}
.notification .icon box {
min-width: 68px;
min-height: 68px;
border-radius: 7px;
}
.notification .actions .action {
margin: 0 .4em;
margin-top: .8em;
}
.notification .actions .action:first-child {
margin-left: 0;
}
.notification .actions .action:last-child {
margin-right: 0;
}
.notification .title {
color: @ctp-text;
font-size: 1.4em;
}
.notification .body {
color: @ctp-subtext0;
}

View File

@ -0,0 +1,22 @@
@import url("colors.css");
@import url("notifications/style.css");
@import url("media/style.css");
.bar > box {
padding: 10px;
border-radius: 5px;
background-color: alpha(@ctp-base, 0.95);
color: @ctp-text;
}
.clock .time {
font-weight: bold;
font-size: 1em;
}
.clock .date {
font-size: 0.8em;
}

View File

@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": [
"ES2022"
],
"allowJs": true,
"checkJs": true,
"strict": true,
"noImplicitAny": false,
"baseUrl": ".",
"typeRoots": [
"./types"
],
"skipLibCheck": true
}
}

1
modules/ags/config/types Symbolic link
View File

@ -0,0 +1 @@
/home/kalle/.local/share/com.github.Aylur.ags/types

15
modules/ags/default.nix Normal file
View File

@ -0,0 +1,15 @@
{
inputs,
...
}:
{
home-manager.users.kalle = {
imports = [ inputs.ags.homeManagerModules.default ];
programs.ags = {
enable = true;
configDir = ./config;
};
};
}

38
modules/bash.nix Normal file
View File

@ -0,0 +1,38 @@
{
pkgs,
...
}:
{
home-manager.users.kalle = {
programs.bash = {
enable = true;
shellAliases = {
# Git aliases
gg = "git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an (%ae)%C(reset)' --all";
gca = "git add -A; git commit -a --amend --no-edit";
gs = "git status";
# Replace some commands with better versions
diff = "${pkgs.difftastic}/bin/difft";
};
initExtra = ''
function open() {
xdg-open $@ &> /dev/null &
}
'';
};
programs.starship = {
enable = true;
settings = {
add_newline = true;
# Remove text from nix shell component
nix_shell.format = "via [$symbol]($style) ";
git_status.disabled = true;
package.disabled = true;
};
};
};
}

10
modules/direnv.nix Normal file
View File

@ -0,0 +1,10 @@
{
...
}:
{
home-manager.users.kalle.programs.direnv = {
enable = true;
enableBashIntegration = true;
nix-direnv.enable = true;
};
}

11
modules/firefox.nix Normal file
View File

@ -0,0 +1,11 @@
{
pkgs,
...
}:
{
home-manager.users.kalle.programs.firefox = {
enable = true;
nativeMessagingHosts = [ pkgs.plasma-browser-integration ];
};
}

15
modules/git.nix Normal file
View File

@ -0,0 +1,15 @@
{
...
}:
{
home-manager.users.kalle.programs.git = {
enable = true;
userName = "Kalle Struik";
userEmail = "kalle@kallestruik.nl";
difftastic.enable = true;
extraConfig = {
init.defaultBranch = "main";
};
};
}

293
modules/hyprland.nix Normal file
View File

@ -0,0 +1,293 @@
{
inputs,
pkgs,
lib,
config,
...
}:
{
options =
let
inherit (lib) mkOption types;
in
{
hyprland = {
mod = mkOption {
type = types.str;
default = "SUPER";
};
primaryMonitor = mkOption {
type = types.str;
};
monitors = mkOption {
type = types.listOf (
types.submodule {
options = {
name = mkOption {
type = types.str;
};
width = mkOption {
type = types.int;
};
height = mkOption {
type = types.int;
};
refreshRate = mkOption {
type = types.int;
default = 60;
};
x = mkOption {
type = types.int;
default = 0;
};
y = mkOption {
type = types.int;
default = 0;
};
transform = mkOption {
type = types.int;
default = 0;
};
vrr = mkOption {
type = types.int;
default = 0;
};
enabled = mkOption {
type = types.bool;
default = true;
};
};
}
);
default = [ ];
};
autoStart = mkOption {
type = types.listOf types.str;
default = [ ];
};
sensitivity = mkOption {
type = types.float;
default = 0.0;
};
layerRules = mkOption {
type = types.attrsOf (types.listOf types.str);
default = { };
};
windowRules = mkOption {
type = types.attrsOf (types.listOf types.str);
default = { };
};
windowRulesV2 = mkOption {
type = types.attrsOf (types.listOf types.str);
default = { };
};
binds = mkOption {
type = types.attrsOf types.str;
default = { };
};
};
};
config =
let
cfg = config.hyprland;
in
{
nix.settings = {
substituters = [
"https://hyprland.cachix.org"
];
trusted-public-keys = [
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
];
};
programs.hyprland = {
enable = true;
withUWSM = true;
package = inputs.hyprland.packages.x86_64-linux.hyprland;
};
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
environment.systemPackages = with pkgs; [
grim # For xdg-desktop-portal-hyprland which does not declare this dependency
slurp # Some for this one
];
home-manager.users.kalle = {
home.packages = with pkgs; [
wl-clipboard
cliphist
ulauncher
];
wayland.windowManager.hyprland = {
enable = true;
# Disable systemd integration since we are using UWSM
systemd.enable = false;
settings = {
monitor =
map (
m:
let
resolution = "${toString m.width}x${toString m.height}@${toString m.refreshRate}";
position = "${toString m.x}x${toString m.y}";
vrr = if m.vrr != 0 then "vrr,${toString m.vrr}" else "";
transform = if m.transform != 0 then "transform,${toString m.transform}" else "";
in
"${m.name},${if m.enabled then "${resolution},${position},1,${vrr}${transform}" else "disable"}"
) (cfg.monitors)
# Automatically detect newly connected monitors
++ [ ",preferred,auto,auto" ];
# TODO: Make these start via UWSM
exec-once = [
"${pkgs.wl-clipboard}/bin/wl-paste --watch ${pkgs.cliphist}/bin/cliphist store"
"${pkgs.ulauncher}/bin/ulauncher --no-window-shadow --hide-window"
# TODO: Replace this with hyprland's polkit agent
"${pkgs.libsForQt5.polkit-kde-agent}/libexec/polkit-kde-authentication-agent-1"
] ++ cfg.autoStart;
env = [
"XCURSOR_SIZE,24"
];
input = {
kb_layout = "us";
kb_variant = "";
kb_options = "";
follow_mouse = 1;
touchpad = {
natural_scroll = "yes";
};
sensitivity = cfg.sensitivity;
accel_profile = "flat";
};
general = {
gaps_in = 5;
gaps_out = 10;
border_size = 1;
# TODO: Make this use system color scheme
"col.active_border" = "rgba(33ccffee) rgba(00ff99ee) 45deg";
"col.inactive_border" = "rgba(595959aa)";
layout = "dwindle";
};
misc.force_default_wallpaper = 1;
decoration = {
rounding = 5;
blur = {
enabled = "yes";
size = 3;
passes = 1;
new_optimizations = "on";
};
};
animations = {
enabled = "yes";
bezier = [
"myBezier, 0.05, 0.9, 0.1, 1.05"
];
animation = [
"windows, 1, 3, myBezier"
"windowsOut, 1, 3, default, popin 80%"
"border, 1, 5, default"
"borderangle, 1, 4, default"
"fade, 1, 3, default"
"workspaces, 1, 2, default"
];
};
layerrule =
let
y = ident: value: "${value},${ident}";
x = ident: values: map (y ident) values;
in
lib.flatten (lib.mapAttrsToList x cfg.layerRules);
workspace =
let
# Create one work space for each non primary monitor
perMonitorWorkspaces = map (m: "name:${m.name}, monitor:${m.name}") (
lib.filter (m: m.name != cfg.primaryMonitor) cfg.monitors
);
# Create 10 work spaces on the primary monitor
primaryMonitorWorkspaces = map (i: "${toString i}, monitor:${cfg.primaryMonitor}") (lib.range 1 10);
in
primaryMonitorWorkspaces ++ perMonitorWorkspaces;
bind =
let
# Create binds to switch workspaces and move windows between them
workspaceBinds = lib.flatten (
map (
i:
let
k = if i == 10 then 0 else i;
in
[
"${cfg.mod}, ${toString k}, workspace, ${toString i}"
"${cfg.mod} SHIFT, ${toString k}, movetoworkspace, ${toString i}"
]
) (lib.range 1 10)
);
# Create binds to manage windows
windowManagementBinds = [
"${cfg.mod} SHIFT, Q, killactive"
"${cfg.mod}, F, togglefloating"
"${cfg.mod} SHIFT, F, fullscreen"
];
configBinds = lib.mapAttrsToList (k: v: "${k}, ${v}") cfg.binds;
in
configBinds ++ workspaceBinds ++ windowManagementBinds;
bindm = [
"${cfg.mod}, mouse:272, movewindow"
"${cfg.mod}, mouse:273, resizewindow"
];
windowrule =
let
y = ident: value: "${value},${ident}";
x = ident: values: map (y ident) values;
in
lib.flatten (lib.mapAttrsToList x cfg.windowRules);
windowrulev2 =
let
y = ident: value: "${value},${ident}";
x = ident: values: map (y ident) values;
in
lib.flatten (lib.mapAttrsToList x cfg.windowRulesV2);
};
};
};
};
}

58
modules/hyprpaper.nix Normal file
View File

@ -0,0 +1,58 @@
{
lib,
config,
pkgs,
...
}:
{
options =
let
inherit (lib) mkOption types;
in
{
hyprpaper = {
wallpaperFolder = mkOption {
type = types.str;
};
};
};
config =
let
cfg = config.hyprpaper;
hyprlandCfg = config.hyprland;
changeWallpaperScript = pkgs.writeShellScriptBin "change-wallpaper" (
lib.concatStringsSep "\n" (
lib.flatten (
map (
m:
let
output = m.name;
wallpaper = "\"$(${pkgs.findutils}/bin/find -L \"${cfg.wallpaperFolder}\" -type f | ${pkgs.coreutils}/bin/shuf -n 1)\"";
in
[
"wallpaper=${wallpaper}"
"${pkgs.hyprland}/bin/hyprctl hyprpaper preload $wallpaper"
"${pkgs.hyprland}/bin/hyprctl hyprpaper wallpaper ${output},$wallpaper"
]
) hyprlandCfg.monitors
)
++ [ "${pkgs.hyprland}/bin/hyprctl hyprpaper unload all" ]
)
);
in
{
hyprland.autoStart = [
"${pkgs.hyprpaper}/bin/hyprpaper"
"sleep 2; ${changeWallpaperScript}/bin/change-wallpaper"
];
home-manager.users.kalle.home.packages = with pkgs; [
hyprpaper
changeWallpaperScript
];
};
}

14
modules/kitty.nix Normal file
View File

@ -0,0 +1,14 @@
{
...
}:
{
home-manager.users.kalle.programs.kitty = {
enable = true;
themeFile = "Catppuccin-Mocha";
settings = {
background_opacity = "0.8";
allow_remote_control = true;
enable_audio_bell = false;
};
};
}

138
modules/nvim/default.nix Normal file
View File

@ -0,0 +1,138 @@
{
pkgs,
outputs,
...
}:
{
nixpkgs = {
overlays = with outputs.overlays; [ nvim-plugins ];
};
home-manager.users.kalle.programs.neovim =
let
toLua = str: "lua << EOF\n${str}\nEOF\n";
toLuaFile = file: "lua << EOF\n${builtins.readFile file}\nEOF\n";
in
{
enable = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
extraPackages = with pkgs; [
nodejs_22 # Required for copilot-vim
ripgrep # Required for telescope
wl-clipboard # Required for clipboard sync
# Language servers
clang-tools
lua-language-server
nodePackages.typescript-language-server
nodePackages."@astrojs/language-server"
typescript
tailwindcss-language-server
gopls
vhdl-ls
nixd
nixfmt-rfc-style
];
plugins = with pkgs.vimPlugins; [
yuck-vim
{
plugin = which-key-nvim;
config = toLua "require('which-key').setup()";
}
neodev-nvim
plenary-nvim
{
plugin = telescope-nvim;
config = toLuaFile ./plugin/telescope.lua;
}
telescope-ui-select-nvim
FTerm-nvim
vim-fugitive
harpoon1
{
plugin = undotree-nvim;
config = toLua "require('undotree').setup()";
}
{
plugin = comment-nvim;
config = toLua "require('Comment').setup()";
}
{
plugin = todo-comments-nvim;
config = toLua "require('todo-comments').setup()";
}
{
plugin = neoconf-nvim;
config = toLua "require('neoconf').setup()";
}
{
plugin = catppuccin-nvim;
config = "colorscheme catppuccin-mocha";
}
cmp-nvim-lsp
cmp-nvim-lsp-signature-help
cmp-buffer
cmp-path
cmp-cmdline
cmp-git
cmp-calc
cmp_luasnip
copilot-cmp
luasnip
friendly-snippets
{
plugin = nvim-cmp;
config = toLuaFile ./plugin/cmp.lua;
}
{
plugin = nvim-lspconfig;
config = toLuaFile ./plugin/lsp.lua;
}
rust-tools-nvim
{
plugin = fidget-nvim;
config = toLua "require('fidget').setup({})";
}
rainbow-delimiters-nvim
{
plugin = (nvim-treesitter.withAllGrammars);
config = toLuaFile ./plugin/treesitter.lua;
}
{
plugin = copilot-lua;
config = toLua ''
require("copilot").setup({
suggestion = { enabled = false },
panel = { enabled = false },
})
'';
}
];
extraLuaConfig = ''
${builtins.readFile ./options.lua}
${builtins.readFile ./keymaps.lua}
'';
};
}

44
modules/nvim/keymaps.lua Normal file
View File

@ -0,0 +1,44 @@
---@diagnostic disable: redefined-local
local function map(mode, keys, func, desc, silent)
local silent = silent == nil and true or silent
vim.keymap.set(mode, keys, func, { desc = desc, silent = silent })
end
-- Movement between windows
map('n', '<leader>h', function() vim.cmd.wincmd('h') end, "Window Left")
map('n', '<leader>j', function() vim.cmd.wincmd('j') end, "Window Down")
map('n', '<leader>k', function() vim.cmd.wincmd('k') end, "Window Up")
map('n', '<leader>l', function() vim.cmd.wincmd('l') end, "Window Right")
-- Harpoon keybinds
map('n', '<leader>mm', require('harpoon.mark').add_file, "[M]ark file in harpoon")
map('n', '<leader>mh', require('harpoon.ui').toggle_quick_menu, "[M]enu [H]arpoon")
map('n', '<leader>1', function() require('harpoon.ui').nav_file(1) end, "Harpoon [1]")
map('n', '<leader>2', function() require('harpoon.ui').nav_file(2) end, "Harpoon [2]")
map('n', '<leader>3', function() require('harpoon.ui').nav_file(3) end, "Harpoon [3]")
map('n', '<leader>4', function() require('harpoon.ui').nav_file(4) end, "Harpoon [4]")
map('n', '<leader>5', function() require('harpoon.ui').nav_file(5) end, "Harpoon [5]")
map('n', '<leader>6', function() require('harpoon.ui').nav_file(6) end, "Harpoon [6]")
map('n', '<leader>7', function() require('harpoon.ui').nav_file(7) end, "Harpoon [7]")
map('n', '<leader>8', function() require('harpoon.ui').nav_file(8) end, "Harpoon [8]")
map('n', '<leader>9', function() require('harpoon.ui').nav_file(9) end, "Harpoon [9]")
map('n', '<leader>tg', vim.cmd.Neogit, '[T]oggle [G]it view')
map('n', '<leader>tu', require('undotree').toggle, '[T]oggle [U]ndo tree')
map('n', '[d', vim.diagnostic.goto_prev, 'Goto Previous Diagnostic')
map('n', ']d', vim.diagnostic.goto_next, 'Goto Next Diagnostic')
map('n', '<leader>e', vim.diagnostic.open_float, 'Show [E]rrors')
map('n', '<leader>q', vim.diagnostic.setloclist, 'Errors to [Q]uickfix')
map('n', '<leader>?', require('telescope.builtin').oldfiles, '[?] Find recently opened files')
map('n', '<leader><space>', require('telescope.builtin').find_files, '[ ]Search Files')
map('n', '<leader>sb', require('telescope.builtin').buffers, '[S]earch [B]uffers')
map('n', '<leader>sh', require('telescope.builtin').help_tags, '[S]earch [H]elp')
map('n', '<leader>sw', require('telescope.builtin').grep_string, '[S]earch current [W]ord')
map('n', '<leader>sg', require('telescope.builtin').live_grep, '[S]earch by [G]rep')
map('n', '<leader>sd', require('telescope.builtin').diagnostics, '[S]earch [D]iagnostics')
map({ 'n', 't' }, '<A-t>', require("FTerm").toggle, 'Toggle Terminal')

41
modules/nvim/options.lua Normal file
View File

@ -0,0 +1,41 @@
vim.opt.termguicolors = true
vim.opt.clipboard = 'unnamed,unnamedplus'
vim.opt.timeoutlen = 300
vim.opt.mouse = 'a'
vim.opt.listchars = 'tab:▸ ,extends:,precedes:'
vim.opt.swapfile = false
vim.opt.backup = false
vim.opt.undodir = vim.fn.expand('~/.cache/vim/undo')
vim.opt.undofile = true
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.list = true
vim.opt.wrap = false
vim.opt.scrolloff = 8
vim.opt.autoindent = true
vim.opt.expandtab = true
vim.opt.softtabstop = 4
vim.opt.shiftwidth = 4
vim.opt.tabstop = 4
vim.opt.smartindent = true
vim.opt.modeline = true
vim.opt.spell = true
vim.g.mapleader = ' '
vim.opt.hlsearch = false
vim.opt.incsearch = true
vim.opt.signcolumn = 'yes'
vim.opt.updatetime = 50
vim.opt.completeopt = { 'menuone', 'noselect', 'noinsert' }
vim.opt.shortmess = vim.opt.shortmess + { c = true }
-- Autoformat on save
vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]]

102
modules/nvim/plugin/cmp.lua Normal file
View File

@ -0,0 +1,102 @@
local cmp = require 'cmp'
local luasnip = require 'luasnip'
require("copilot_cmp").setup()
local has_words_before = function()
if vim.api.nvim_buf_get_option(0, "buftype") == "prompt" then return false end
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_text(0, line - 1, 0, line - 1, col, {})[1]:match("^%s*$") == nil
end
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-n>'] = cmp.mapping.select_next_item(),
-- Add tab support
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 's' }),
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() and has_words_before() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { 'i', 's' }),
['<C-f>'] = cmp.mapping.scroll_docs(-4),
['<C-d>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<C-e>'] = cmp.mapping.close(),
['<CR>'] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Insert,
select = true,
})
}),
sources = cmp.config.sources({
{ name = "copilot", group_index = 2 },
{ name = 'path' }, -- file paths
{ name = 'nvim_lsp' }, -- from language server
{ name = 'nvim_lsp_signature_help' }, -- display function signatures with current parameter emphasized
{ name = 'luasnip' },
{ name = 'nvim_lua' }, -- complete neovim's Lua runtime API such vim.lsp.*
{ name = 'buffer' }, -- source current buffer
{ name = 'calc' }, -- source for math calculation
}),
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
formatting = {
fields = { 'menu', 'abbr', 'kind' },
format = function(entry, item)
local menu_icon = {
nvim_lsp = 'λ',
vsnip = '',
buffer = 'Ω',
path = '🖫',
}
item.menu = menu_icon[entry.source.name]
return item
end,
},
})
cmp.setup.filetype('gitcommit', {
sources = cmp.config.sources({
{ name = 'cmp_git' }, -- You can specify the `cmp_git` source if you were installed it.
}, {
{ name = 'buffer' },
})
})
-- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline('/', {
mapping = cmp.mapping.preset.cmdline(),
sources = {
{ name = 'buffer' }
}
})
-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(':', {
mapping = cmp.mapping.preset.cmdline(),
sources = cmp.config.sources({
{ name = 'path' }
}, {
{ name = 'cmdline' }
})
})

172
modules/nvim/plugin/lsp.lua Normal file
View File

@ -0,0 +1,172 @@
local on_attach = function(_, bufnr)
local nmap = function(keys, func, desc)
if desc then
desc = 'LSP: ' .. desc
end
vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc })
end
nmap('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
nmap('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
nmap('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
nmap('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
nmap('<leader>D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition')
nmap('<leader>ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols')
nmap('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
-- See `:help K` for why this keymap
nmap('K', vim.lsp.buf.hover, 'Hover Documentation')
nmap('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
-- Lesser used LSP functionality
nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
nmap('<leader>wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder')
nmap('<leader>wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder')
nmap('<leader>wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, '[W]orkspace [L]ist Folders')
-- Create a command `:Format` local to the LSP buffer
vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
if vim.lsp.buf.format then
vim.lsp.buf.format()
elseif vim.lsp.buf.formatting then
vim.lsp.buf.formatting()
end
end, { desc = 'Format current buffer with LSP' })
end
-- LSP Diagnostics Options Setup
local sign = function(opts)
vim.fn.sign_define(opts.name, {
texthl = opts.name,
text = opts.text,
numhl = ''
})
end
sign({ name = 'DiagnosticSignError', text = '' })
sign({ name = 'DiagnosticSignWarn', text = '' })
sign({ name = 'DiagnosticSignHint', text = '' })
sign({ name = 'DiagnosticSignInfo', text = '' })
vim.diagnostic.config({
virtual_text = false,
signs = true,
update_in_insert = true,
underline = true,
severity_sort = false,
float = {
border = 'rounded',
source = 'always',
header = '',
prefix = '',
},
})
vim.cmd([[
autocmd CursorHold * lua vim.diagnostic.open_float(nil, { focusable = false })
]])
-- LSP Configuration
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
require('neodev').setup({
override = function(root_dir, library)
if root_dir:find("/home/kalle/.dots", 1, true) == 1 then
library.enabled = true
library.plugins = true
end
end,
})
require('lspconfig').lua_ls.setup {
on_attach = on_attach,
capabilities = capabilities,
root_dir = function()
return vim.loop.cwd()
end,
cmd = { "lua-language-server" },
settings = {
Lua = {
workspace = { checkThirdParty = false },
telemetry = { enable = false },
},
}
}
require('lspconfig').nixd.setup {
on_attach = on_attach,
capabilities = capabilities,
settings = {
nixd = {
formatting = {
command = { "nixfmt" },
},
},
},
}
require('lspconfig').tsserver.setup {
on_attach = on_attach,
capabilities = capabilities,
init_options = {
tsserver = {
fallbackPath = string.gsub(vim.fn.system("dirname `which tsserver`"), '^%s*(.-)%s*$', '%1') .. "/../lib/node_modules/typescript/lib",
},
},
}
require('lspconfig').tailwindcss.setup {
on_attach = on_attach,
capabilities = capabilities,
}
require('lspconfig').clangd.setup {
on_attach = on_attach,
capabilities = capabilities,
}
require('lspconfig').gopls.setup {
on_attach = on_attach,
capabilities = capabilities,
}
require('lspconfig').vhdl_ls.setup {
on_attach = on_attach,
capabilities = capabilities,
}
require('lspconfig').astro.setup {
on_attach = on_attach,
capabilities = capabilities,
}
require('rust-tools').setup({
server = {
on_attach = on_attach,
settings = {
["rust-analyzer"] = {
checkOnSave = {
command = "clippy"
},
},
}
},
})
-- Workaround for https://github.com/neovim/neovim/issues/30985
for _, method in ipairs({ 'textDocument/diagnostic', 'workspace/diagnostic' }) do
local default_diagnostic_handler = vim.lsp.handlers[method]
vim.lsp.handlers[method] = function(err, result, context, config)
if err ~= nil and err.code == -32802 then
return
end
return default_diagnostic_handler(err, result, context, config)
end
end

View File

@ -0,0 +1,13 @@
require('telescope').setup {
defaults = {
mappings = {
i = {
['<C-u>'] = false,
['<C-d>'] = false,
},
},
},
}
require("telescope").load_extension("ui-select")
pcall(require('telescope').load_extension, 'fzf')

View File

@ -0,0 +1,9 @@
require('nvim-treesitter.configs').setup {
ensure_installed = {},
auto_install = false,
highlight = { enable = true },
indent = { enable = true },
}

6
modules/sddm.nix Normal file
View File

@ -0,0 +1,6 @@
{
...
}:
{
services.displayManager.sddm.enable = true;
}

34
modules/steam.nix Normal file
View File

@ -0,0 +1,34 @@
{
pkgs,
...
}:
{
programs.steam = {
enable = true;
package = pkgs.steam.override {
extraPkgs =
pkgs: with pkgs; [
xorg.libXcursor
xorg.libXi
xorg.libXinerama
xorg.libXScrnSaver
libpng
libpulseaudio
libvorbis
stdenv.cc.cc.lib
libkrb5
keyutils
];
extraLibraries =
pkgs: with pkgs; [
gperftools # Needed for tf2 to work
];
};
};
environment.systemPackages = with pkgs; [
gamescope
pkgsi686Linux.gperftools # Needed for tf2
];
}

View File

@ -6,178 +6,6 @@
}:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
./hardware-configuration.override.nix
# inputs.nixos-cosmic.nixosModules.default
];
nix.settings = {
# Enable flakes and new 'nix' command
experimental-features = "nix-command flakes";
# Deduplicate and optimize nix store
auto-optimise-store = true;
# Allow me to use cachix
trusted-users = [
"root"
"kalle"
];
substituters = [
"https://hyprland.cachix.org"
"https://cosmic.cachix.org/"
];
trusted-public-keys = [
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
"cosmic.cachix.org-1:Dya9IyXD4xdBehWjrkPv6rtxpmMdRel02smYzA85dPE="
];
};
services.btrfs.autoScrub.enable = true;
nixpkgs.config.allowUnfree = true;
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "kalle-pc";
networking.networkmanager.enable = true;
# Set your time zone.
time.timeZone = "Europe/Amsterdam";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
useXkbConfig = true; # use xkbOptions in tty.
};
# Enable the X11 windowing system.
services.displayManager.sddm.enable = true;
services.xserver = {
enable = true;
xkb.layout = "us";
};
# services.desktopManager.cosmic.enable = true;
# services.displayManager.cosmic-greeter.enable = true;
# Allow flashing ZSA keyboards
hardware.keyboard.zsa.enable = true;
programs.hyprland = {
enable = true;
package = inputs.hyprland.packages.x86_64-linux.hyprland;
};
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
# Enable CUPS to print documents.
services.printing.enable = true;
# Enable sound.
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
users.users.kalle = {
isNormalUser = true;
group = "kalle";
extraGroups = [
"wheel"
"dialout"
]; # Enable sudo for the user.
};
users.groups.kalle.gid = 1000;
environment.systemPackages = with pkgs; [
xdg-user-dirs
grim # For xdg-desktop-portal-hyprland which does not declare this dependency
slurp # Some for this one
gamescope
pkgsi686Linux.gperftools # Needed for tf2
];
fonts = {
enableDefaultPackages = true;
packages = with pkgs; [
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
fira-code
fira-code-symbols
(nerdfonts.override { fonts = [ "NerdFontsSymbolsOnly" ]; })
];
fontconfig = {
defaultFonts = {
serif = [
"Noto Serif"
"Symbols Nerd Font"
];
sansSerif = [
"Noto Sans"
"Symbols Nerd Font"
];
monospace = [
"Fira Code"
"Symbols Nerd Font Mono"
];
};
};
};
# Steam needs to be installed on system level, because reasons
programs.steam = {
enable = true;
package = pkgs.steam.override {
extraPkgs =
pkgs: with pkgs; [
xorg.libXcursor
xorg.libXi
xorg.libXinerama
xorg.libXScrnSaver
libpng
libpulseaudio
libvorbis
stdenv.cc.cc.lib
libkrb5
keyutils
];
extraLibraries =
pkgs: with pkgs; [
gperftools # Needed for tf2 to work
];
};
};
services.gvfs.enable = true;
# Enable the OpenSSH daemon.
services.openssh.enable = true;
# Disable firewall.
networking.firewall.enable = false;
# 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 = "23.05"; # Did you read the comment?
still.migrating = do not rebuild this;
}

View File

@ -1,56 +0,0 @@
# 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 = [ "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=root" ];
};
fileSystems."/home" =
{ device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=home" ];
};
fileSystems."/nix" =
{ device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=nix" ];
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/23F6-1045";
fsType = "vfat";
};
fileSystems."/swap" =
{ device = "/dev/disk/by-uuid/d453acaf-12a4-4f7a-b33e-90d87a086995";
fsType = "btrfs";
options = [ "subvol=swap" ];
};
swapDevices = [ ];
# 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.enp35s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@ -1,23 +0,0 @@
{ config, lib, pkgs, modulesPath, ...}:
{
fileSystems = {
# Extra filesystem configs to enable compression.
"/".options = [ "compress=zstd" ];
"/home".options = [ "compress=zstd" ];
"/nix".options = [ "compress=zstd" "noatime" ];
"/swap".options = [ "noatime" ];
# Mount other drives
"/mnt/games" = {
device = "/dev/disk/by-uuid/0ac05c3f-df12-458e-b145-e912febe1205";
fsType = "ext4";
};
"/mnt/external" = {
device = "/dev/disk/by-uuid/13e2dfc3-7b4d-44ac-9417-51b933a36917";
fsType = "ext4";
};
};
}