diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..483c00c --- /dev/null +++ b/flake.lock @@ -0,0 +1,533 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "neovim-nightly-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "neovim-nightly-overlay", + "hercules-ci-effects", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "id": "flake-parts", + "type": "indirect" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat_2", + "gitignore": "gitignore", + "nixpkgs": [ + "neovim-nightly-overlay", + "nixpkgs" + ], + "nixpkgs-stable": [ + "neovim-nightly-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1717664902, + "narHash": "sha256-7XfBuLULizXjXfBYy/VV+SpYMHreNRHk9nKMsm1bgb4=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "neovim-nightly-overlay", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "neovim-nightly-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1713898448, + "narHash": "sha256-6q6ojsp/Z9P2goqnxyfCSzFOD92T3Uobmj8oVAicUOs=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "c0302ec12d569532a6b6bd218f698bc402e93adc", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1717527182, + "narHash": "sha256-vWSkg6AMok1UUQiSYVdGMOXKD2cDFnajITiSi0Zjd1A=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "845a5c4c073f74105022533907703441e0464bc3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-24.05", + "repo": "home-manager", + "type": "github" + } + }, + "hyprcursor": { + "inputs": { + "hyprlang": [ + "hyprland", + "hyprlang" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1717181720, + "narHash": "sha256-yv+QZWsusu/NWjydkxixHC2g+tIJ9v+xkE2EiVpJj6g=", + "owner": "hyprwm", + "repo": "hyprcursor", + "rev": "9e27a2c2ceb1e0b85bd55b0afefad196056fe87c", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprcursor", + "type": "github" + } + }, + "hyprland": { + "inputs": { + "hyprcursor": "hyprcursor", + "hyprlang": "hyprlang", + "hyprwayland-scanner": "hyprwayland-scanner", + "nixpkgs": "nixpkgs", + "systems": "systems", + "xdph": "xdph" + }, + "locked": { + "lastModified": 1718051463, + "narHash": "sha256-ZB7Ov9pbyOUl6Up8o3Kvb/4bghhcbBk0JILLS/L7LUM=", + "ref": "refs/heads/main", + "rev": "811429bfd4a46f33c7788580f72038b0c3c1c2b1", + "revCount": 4795, + "submodules": true, + "type": "git", + "url": "https://github.com/hyprwm/Hyprland" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://github.com/hyprwm/Hyprland" + } + }, + "hyprland-contrib": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1716228712, + "narHash": "sha256-y+LOXuSRMfkR2Vfwl5K2NVrszi1h5MJpML+msLnVS8U=", + "owner": "hyprwm", + "repo": "contrib", + "rev": "33b38358559054d316eb605ccb733980dfa7dc63", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "contrib", + "type": "github" + } + }, + "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "hyprland", + "xdph", + "nixpkgs" + ], + "systems": [ + "hyprland", + "xdph", + "systems" + ] + }, + "locked": { + "lastModified": 1691753796, + "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprlang": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1716473782, + "narHash": "sha256-+qLn4lsHU6iL3+HTo1gTQ1tWzet8K9h+IfVemzEQZj8=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "87d5d984109c839482b88b4795db073eb9ed446f", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprwayland-scanner": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1717784906, + "narHash": "sha256-YxmfxHfWed1fosaa7fC1u7XoKp1anEZU+7Lh/ojRKoM=", + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "rev": "0f30f9eca6e404130988554accbb64d1c9ec877d", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "type": "github" + } + }, + "neovim-nightly-overlay": { + "inputs": { + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", + "git-hooks": "git-hooks", + "hercules-ci-effects": "hercules-ci-effects", + "neovim-src": "neovim-src", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1717998128, + "narHash": "sha256-yHRdkBgDXUuW5RRY0HuoHhnyUgI7RY7E2ceaGEyoOxg=", + "owner": "nix-community", + "repo": "neovim-nightly-overlay", + "rev": "8a60d0af103bfc26f6a4e9c023c3f202a5cda549", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "neovim-nightly-overlay", + "type": "github" + } + }, + "neovim-src": { + "flake": false, + "locked": { + "lastModified": 1717973250, + "narHash": "sha256-3SETpW06kTp3K9Up2DIhXdr2kH3Zl9lqzrMv4Qpi6dM=", + "owner": "neovim", + "repo": "neovim", + "rev": "40329f32d809302196ffd3f47b4d01a1d67f5a9b", + "type": "github" + }, + "original": { + "owner": "neovim", + "repo": "neovim", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1717602782, + "narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1717880976, + "narHash": "sha256-BRvSCsKtDUr83NEtbGfHLUOdDK0Cgbezj2PtcHnz+sQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4913a7c3d8b8d00cb9476a6bd730ff57777f740c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1717786204, + "narHash": "sha256-4q0s6m0GUcN7q+Y2DqD27iLvbcd1G50T2lv08kKxkSI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "051f920625ab5aabe37c920346e3e69d7d34400e", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1717868076, + "narHash": "sha256-c83Y9t815Wa34khrux81j8K8ET94ESmCuwORSKm2bQY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cd18e2ae9ab8e2a0a8d715b60c91b54c0ac35ff9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1717952948, + "narHash": "sha256-mJi4/gjiwQlSaxjA6AusXBN/6rQRaPCycR7bd8fydnQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2819fffa7fa42156680f0d282c60d81e8fb185b7", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-24.05", + "type": "indirect" + } + }, + "nur": { + "locked": { + "lastModified": 1718078179, + "narHash": "sha256-DjPinJD5qfICyAQ1F/kiDPDYXIZn0m9ZGh01QxYN6ug=", + "owner": "nix-community", + "repo": "NUR", + "rev": "17ca35f1d12452f5135d0b96a67a78eb72d203ae", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "hyprland": "hyprland", + "hyprland-contrib": "hyprland-contrib", + "neovim-nightly-overlay": "neovim-nightly-overlay", + "nixpkgs": "nixpkgs_3", + "nixpkgs-unstable": "nixpkgs-unstable", + "nur": "nur", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1718058322, + "narHash": "sha256-d5jLlAwVi4NzT9yc5UrPiOpDxTRhu8GGh0IIfeFcdrM=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "d071c74a7de1e26d211b69b6fbae37ae2e31a87f", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "xdph": { + "inputs": { + "hyprland-protocols": "hyprland-protocols", + "hyprlang": [ + "hyprland", + "hyprlang" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1716290197, + "narHash": "sha256-1u9Exrc7yx9qtES2brDh7/DDZ8w8ap1nboIOAtCgeuM=", + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "rev": "91e48d6acd8a5a611d26f925e51559ab743bc438", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..0207f10 --- /dev/null +++ b/flake.nix @@ -0,0 +1,114 @@ +{ + description = "Tigor's Nixos Configuration"; + + nixConfig = { + extra-substituters = [ + "https://nix-community.cachix.org" + "https://hyprland.cachix.org" + "https://nixpkgs-wayland.cachix.org" + ]; + extra-trusted-public-keys = [ + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=" + "nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA=" + ]; + }; + inputs = { + nur.url = "github:nix-community/NUR"; + neovim-nightly-overlay = { + url = "github:nix-community/neovim-nightly-overlay"; + }; + hyprland-contrib = { + url = "github:hyprwm/contrib"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nixpkgs.url = "nixpkgs/nixos-24.05"; + nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; + hyprland.url = "git+https://github.com/hyprwm/Hyprland?submodules=1"; + home-manager = { + url = "github:nix-community/home-manager/release-24.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + outputs = inputs @ { self, nur, nixpkgs, home-manager, sops-nix, neovim-nightly-overlay, ... }: + let + commonModules = [ + nur.nixosModules.nur + home-manager.nixosModules.home-manager + { + nixpkgs.overlays = [ + neovim-nightly-overlay.overlays.default + nur.overlay + ]; + } + { + nix.settings = { + substituters = [ + "https://cache.nixos.org/" + "https://nix-community.cachix.org" + ]; + trusted-public-keys = [ + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + } + sops-nix.nixosModules.sops + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.sharedModules = [ + inputs.sops-nix.homeManagerModules.sops + ]; + } + ]; + unstable = import inputs.nixpkgs-unstable { + system = "x86_64-linux"; + config.allowUnfree = true; + }; + in + { + nixosConfigurations = + { + castle = + let + profile-path = ./profiles/castle.nix; + hardware-configuration = ./hardware-configuration/castle.nix; + specialArgs = { inherit inputs unstable profile-path hardware-configuration; }; + in + nixpkgs.lib.nixosSystem + { + system = "x86_64-linux"; + modules = + [ + ./system + { + home-manager.extraSpecialArgs = specialArgs; + home-manager.users.tigor = import ./home/tigor; + } + ] ++ commonModules; + specialArgs = specialArgs; + }; + fort = + let + profile-path = ./profiles/fort.nix; + hardware-configuration = ./hardware-configuration/fort.nix; + specialArgs = { inherit inputs unstable profile-path hardware-configuration; }; + in + nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ./system + { + home-manager.extraSpecialArgs = specialArgs; + home-manager.users.tigor = import ./home/tigor; + } + ] ++ commonModules; + specialArgs = specialArgs; + }; + }; + }; +} diff --git a/hardware-configuration/castle.nix b/hardware-configuration/castle.nix new file mode 100644 index 0000000..96468c7 --- /dev/null +++ b/hardware-configuration/castle.nix @@ -0,0 +1,75 @@ +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + sops.secrets."smb/secrets" = { + owner = config.users.users.tigor.name; + }; + + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ "dm-snapshot" ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + system.fsPackages = [ pkgs.bindfs ]; + fileSystems."/nas" = + { + device = "//192.168.100.5/wd_red_1"; + fsType = "cifs"; + options = [ + "_netdev" + "x-systemd.automount" + "noauto" + "x-systemd.idle-timeout=60" + "x-systemd.device-timeout=5s" + "x-systemd.mount-timeout=5s" + "uid=1000" + "gid=100" + "credentials=${config.sops.secrets."smb/secrets".path}" + ]; + }; + + fileSystems."/" = + { + device = "/dev/disk/by-uuid/6a987bc7-1f00-4494-bcef-b0f8afc62b7b"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { + device = "/dev/disk/by-uuid/812C-A3A9"; + fsType = "vfat"; + }; + + fileSystems."/home" = + { + device = "/dev/disk/by-uuid/0add1f95-4cd5-4d44-876e-c1b381b7d133"; + fsType = "ext4"; + }; + + fileSystems."/workstation" = + { + device = "/dev/disk/by-uuid/7a3a7a8a-91d5-43fb-a80b-376bacdb54ec"; + fsType = "ext4"; + }; + + swapDevices = + [ + { device = "/dev/disk/by-uuid/15139a5f-a695-47a1-bd59-7e530989860c"; } + ]; + + # 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..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp6s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp7s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hardware-configuration/fort.nix b/hardware-configuration/fort.nix new file mode 100644 index 0000000..5c2012f --- /dev/null +++ b/hardware-configuration/fort.nix @@ -0,0 +1,32 @@ +{ config, lib, modulesPath, ... }: + +{ + imports = + [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { + device = "/dev/disk/by-label/NIXROOT"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { + device = "/dev/disk/by-label/NIXBOOT"; + fsType = "vfat"; + }; + + swapDevices = + [{ device = "/dev/disk/by-label/NIXSWAP"; }]; + + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/home/modules/default.nix b/home/modules/default.nix new file mode 100644 index 0000000..063d7d5 --- /dev/null +++ b/home/modules/default.nix @@ -0,0 +1,11 @@ +{ ... }: +{ + imports = [ + ./gnome + ./sway + ./hyprland + ./syncthing.nix + ./obs.nix + ./firefox.nix + ]; +} diff --git a/home/modules/firefox.nix b/home/modules/firefox.nix new file mode 100644 index 0000000..1ab404f --- /dev/null +++ b/home/modules/firefox.nix @@ -0,0 +1,49 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.firefox; +in +{ + config = lib.mkIf cfg.enable { + programs.firefox = { + enable = true; + policies = { + DisableTelemetry = true; + DisableFirefoxStudies = true; + EnableTrackingProtection = { + Value = true; + Locked = true; + Cryptomining = true; + Fingerprinting = true; + }; + DisablePocket = true; + DisableFirefoxAccounts = true; + DisableAccounts = true; + OverrideFirstRunPage = ""; + OverridePostUpdatePage = ""; + DontCheckDefaultBrowser = true; + DisplayBookmarksToolbar = "never"; # alternatives: "always" or "newtab" + DisplayMenuBar = "default-off"; # alternatives: "always", "never" or "default-on" + SearchBar = "unified"; # alternative: "separate" + }; + profiles = { + tigor = { + id = 0; + name = "Tigor"; + isDefault = true; + extensions = with pkgs.nur.repos.rycee.firefox-addons; [ + ublock-origin + bitwarden + cookie-autodelete + old-reddit-redirect + reddit-enhancement-suite + vimium-c + violentmonkey + ]; + settings = { + "extensions.autoDisableScopes" = 0; + }; + }; + }; + }; + }; +} diff --git a/home/modules/gnome/default.nix b/home/modules/gnome/default.nix new file mode 100644 index 0000000..1fc2f97 --- /dev/null +++ b/home/modules/gnome/default.nix @@ -0,0 +1,104 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.gnome; +in +{ + config = lib.mkIf cfg.enable { + dconf = { + enable = true; + settings = { + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + enable-hot-corners = false; + }; + # "org/gnome/desktop/wm/preferences".resize-with-right-button = true; + "org/gnome/desktop/wm/preferences" = { + resize-with-right-button = true; + button-layout = "appmenu:minimize,maximize,close"; + num-workspaces = 10; + }; + "org/gnome/desktop/wm/keybindings" = { + switch-to-workspace-1 = [ "1" ]; + switch-to-workspace-2 = [ "2" ]; + switch-to-workspace-3 = [ "3" ]; + switch-to-workspace-4 = [ "4" ]; + switch-to-workspace-5 = [ "5" ]; + switch-to-workspace-6 = [ "6" ]; + switch-to-workspace-7 = [ "7" ]; + switch-to-workspace-8 = [ "8" ]; + switch-to-workspace-9 = [ "9" ]; + switch-to-workspace-10 = [ "0" ]; + + move-to-workspace-1 = [ "1" ]; + move-to-workspace-2 = [ "2" ]; + move-to-workspace-3 = [ "3" ]; + move-to-workspace-4 = [ "4" ]; + move-to-workspace-5 = [ "5" ]; + move-to-workspace-6 = [ "6" ]; + move-to-workspace-7 = [ "7" ]; + move-to-workspace-8 = [ "8" ]; + move-to-workspace-9 = [ "9" ]; + move-to-workspace-10 = [ "0" ]; + + toggle-maximized = [ "space" ]; + }; + + "org/gnome/shell/keybindings" = { + switch-to-application-1 = [ ]; + switch-to-application-2 = [ ]; + switch-to-application-3 = [ ]; + switch-to-application-4 = [ ]; + switch-to-application-5 = [ ]; + switch-to-application-6 = [ ]; + switch-to-application-7 = [ ]; + switch-to-application-8 = [ ]; + switch-to-application-9 = [ ]; + }; + + "org/gnome/shell" = { + disable-user-extensions = false; + + enabled-extensions = [ + "user-theme@gnome-shell-extensions.gcampax.github.com" + "trayIconsReloaded@selfmade.pl" + "gsconnect@andyholmes.github.io" + "dashbar@fthx" + "pano@elhan.io" + "appindicatorsupport@rgcjonas.gmail.com" + "drive-menu@gnome-shell-extensions.gcampax.github.com" # built-in to gnome DE + "runcat@kolesnikov.se" + "docker@stickman_0x00.com" + "Vitals@CoreCoding.com" + ]; + }; + + "org/gnome/settings-daemon/plugins/media-keys".screensaver = [ "F12" ]; + + "org/gnome/deskto/input-sources".xkb-options = [ + "terminate:ctrl_alt_bksp" + "caps:ctrl_modifier" + "shift:both_capslock_cancel" + ]; + }; + }; + + home.packages = with pkgs; [ + gnomeExtensions.user-themes + gnomeExtensions.tray-icons-reloaded + gnomeExtensions.pano + gnomeExtensions.dashbar + gnomeExtensions.gsconnect + gnomeExtensions.appindicator + gnomeExtensions.runcat + gnomeExtensions.docker + gnomeExtensions.vitals + gnomeExtensions.espresso + gnomeExtensions.forge + + gnome.dconf-editor + gnome.gnome-tweaks + libappindicator-gtk2 + ]; + }; + +} diff --git a/home/modules/hyprland/alacritty.nix b/home/modules/hyprland/alacritty.nix new file mode 100644 index 0000000..297cc38 --- /dev/null +++ b/home/modules/hyprland/alacritty.nix @@ -0,0 +1,36 @@ +{ lib, config, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + programs.alacritty = { + enable = true; + settings = { + import = [ + "${config.home.homeDirectory}/.cache/wallust/alacritty.toml" + ]; + live_config_reload = true; + font = { + normal = { + family = "JetBrainsMono Nerd Font"; + style = "Regular"; + }; + italic = { + family = "JetBrainsMono Nerd Font"; + style = "Italic"; + }; + bold = { + family = "JetBrainsMono Nerd Font"; + style = "Bold"; + }; + bold_italic = { + family = "JetBrainsMono Nerd Font"; + style = "Bold Italic"; + }; + size = 11.0; + }; + }; + }; + }; +} diff --git a/home/modules/hyprland/default.nix b/home/modules/hyprland/default.nix new file mode 100644 index 0000000..6c5571a --- /dev/null +++ b/home/modules/hyprland/default.nix @@ -0,0 +1,46 @@ +{ pkgs, lib, config, unstable, ... }: +let + cfg = config.profile.hyprland; +in +{ + imports = [ + ./dunst.nix + ./hypridle.nix + ./hyprland.nix + ./hyprlock.nix + # hyprpaper seems to be broken with out of memory and failure to swap wallpapers correctly. + # Use swww for now until the application is stable. + # ./hyprpaper.nix + ./pyprland.nix + ./rofi.nix + ./wallust.nix + ./waybar.nix + ./wlogout.nix + ./swappy.nix + ./alacritty.nix + ]; + config = lib.mkIf cfg.enable { + home.packages = with pkgs; [ + unstable.cosmic-term + cliphist + qalculate-gtk + pavucontrol + pasystray + + graphicsmagick + unstable.swayosd + image-roll # image viewer + ]; + + home.pointerCursor = { + name = "Adwaita"; + package = pkgs.gnome.adwaita-icon-theme; + size = 24; + x11 = { + enable = true; + defaultCursor = "Adwaita"; + }; + }; + + }; +} diff --git a/home/modules/hyprland/dunst.nix b/home/modules/hyprland/dunst.nix new file mode 100644 index 0000000..25a16f1 --- /dev/null +++ b/home/modules/hyprland/dunst.nix @@ -0,0 +1,350 @@ +{ config, lib, unstable, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ + unstable.dunst + ]; + home.file.".config/dunst/dunstrc".text = '' + [global] + ### Display ### + + # Which monitor should the notifications be displayed on. + monitor = ${cfg.dunst.monitor} + + # Display notification on focused monitor. Possible modes are: + # mouse: follow mouse pointer + # keyboard: follow window with keyboard focus + # none: don't follow anything + # + # "keyboard" needs a window manager that exports the + # _NET_ACTIVE_WINDOW property. + # This should be the case for almost all modern window managers. + # + # If this option is set to mouse or keyboard, the monitor option + # will be ignored. + follow = none + + ### Geometry ### + + # dynamic width from 0 to 300 + # width = (0, 300) + # constant width of 300 + width = 300 + + # The maximum height of a single notification, excluding the frame. + height = (0,300) + + # Position the notification in the top right corner + origin = top-center + + # Offset from the origin + offset = 0x30 + + # Scale factor. It is auto-detected if value is 0. + scale = 0 + + # Maximum number of notification (0 means no limit) + notification_limit = 20 + + ### Progress bar ### + + # Turn on the progess bar. It appears when a progress hint is passed with + # for example dunstify -h int:value:12 + progress_bar = true + + # Set the progress bar height. This includes the frame, so make sure + # it's at least twice as big as the frame width. + progress_bar_height = 10 + + # Set the frame width of the progress bar + progress_bar_frame_width = 1 + + # Set the minimum width for the progress bar + progress_bar_min_width = 150 + + # Set the maximum width for the progress bar + progress_bar_max_width = 300 + + # Corner radius for the progress bar. 0 disables rounded corners. + progress_bar_corner_radius = 10 + + # Corner radius for the icon image. + icon_corner_radius = 0 + + # Show how many messages are currently hidden (because of + # notification_limit). + indicate_hidden = yes + + # The transparency of the window. Range: [0; 100]. + # This option will only work if a compositing window manager is + # present (e.g. xcompmgr, compiz, etc.). (X11 only) + transparency = 30 + + # Draw a line of "separator_height" pixel height between two + # notifications. + # Set to 0 to disable. + # If gap_size is greater than 0, this setting will be ignored. + separator_height = 2 + + # Padding between text and separator. + padding = 8 + + # Horizontal padding. + horizontal_padding = 8 + + # Padding between text and icon. + text_icon_padding = 0 + + # Defines width in pixels of frame around the notification window. + # Set to 0 to disable. + frame_width = 1 + + # Defines color of the frame around the notification window. + frame_color = "#ffffff" + + # Size of gap to display between notifications - requires a compositor. + # If value is greater than 0, separator_height will be ignored and a border + # of size frame_width will be drawn around each notification instead. + # Click events on gaps do not currently propagate to applications below. + gap_size = 0 + + # Define a color for the separator. + # possible values are: + # * auto: dunst tries to find a color fitting to the background; + # * foreground: use the same color as the foreground; + # * frame: use the same color as the frame; + # * anything else will be interpreted as a X color. + separator_color = frame + + # Sort messages by urgency. + sort = yes + + # Don't remove messages, if the user is idle (no mouse or keyboard input) + # for longer than idle_threshold seconds. + # Set to 0 to disable. + # A client can set the 'transient' hint to bypass this. See the rules + # section for how to disable this if necessary + # idle_threshold = 120 + + ### Text ### + + font = "Fira Sans Semibold" 9 + + # The spacing between lines. If the height is smaller than the + # font height, it will get raised to the font height. + line_height = 1 + + # Possible values are: + # full: Allow a small subset of html markup in notifications: + # bold + # italic + # strikethrough + # underline + # + # For a complete reference see + # . + # + # strip: This setting is provided for compatibility with some broken + # clients that send markup even though it's not enabled on the + # server. Dunst will try to strip the markup but the parsing is + # simplistic so using this option outside of matching rules for + # specific applications *IS GREATLY DISCOURAGED*. + # + # no: Disable markup parsing, incoming notifications will be treated as + # plain text. Dunst will not advertise that it has the body-markup + # capability if this is set as a global setting. + # + # It's important to note that markup inside the format option will be parsed + # regardless of what this is set to. + markup = full + + # The format of the message. Possible variables are: + # %a appname + # %s summary + # %b body + # %i iconname (including its path) + # %I iconname (without its path) + # %p progress value if set ([ 0%] to [100%]) or nothing + # %n progress value if set without any extra characters + # %% Literal % + # Markup is allowed + format = "%s\n%b" + + # Alignment of message text. + # Possible values are "left", "center" and "right". + alignment = left + + # Vertical alignment of message text and icon. + # Possible values are "top", "center" and "bottom". + vertical_alignment = center + + # Show age of message if message is older than show_age_threshold + # seconds. + # Set to -1 to disable. + show_age_threshold = 60 + + # Specify where to make an ellipsis in long lines. + # Possible values are "start", "middle" and "end". + ellipsize = middle + + # Ignore newlines '\n' in notifications. + ignore_newline = no + + # Stack together notifications with the same content + stack_duplicates = true + + # Hide the count of stacked notifications with the same content + hide_duplicate_count = false + + # Display indicators for URLs (U) and actions (A). + show_indicators = yes + + ### Icons ### + + # Recursive icon lookup. You can set a single theme, instead of having to + # define all lookup paths. + enable_recursive_icon_lookup = true + + # Set icon theme (only used for recursive icon lookup) + icon_theme = "Papirus-Dark,Adwaita" + # You can also set multiple icon themes, with the leftmost one being used first. + # icon_theme = "Adwaita, breeze" + + # Align icons left/right/top/off + icon_position = left + + # Scale small icons up to this size, set to 0 to disable. Helpful + # for e.g. small files or high-dpi screens. In case of conflict, + # max_icon_size takes precedence over this. + min_icon_size = 32 + + # Scale larger icons down to this size, set to 0 to disable + max_icon_size = 128 + + # Paths to default icons (only neccesary when not using recursive icon lookup) + icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ + + ### History ### + + # Should a notification popped up from history be sticky or timeout + # as if it would normally do. + sticky_history = yes + + # Maximum amount of notifications kept in history + history_length = 20 + + ### Misc/Advanced ### + + # dmenu path. + dmenu = /usr/bin/dmenu -p dunst: + + # Browser for opening urls in context menu. + browser = /usr/bin/xdg-open + + # Always run rule-defined scripts, even if the notification is suppressed + always_run_script = true + + # Define the title of the windows spawned by dunst + title = Dunst + + # Define the class of the windows spawned by dunst + class = Dunst + + # Define the corner radius of the notification window + # in pixel size. If the radius is 0, you have no rounded + # corners. + # The radius will be automatically lowered if it exceeds half of the + # notification height to avoid clipping text and/or icons. + corner_radius = 10 + + # Ignore the dbus closeNotification message. + # Useful to enforce the timeout set by dunst configuration. Without this + # parameter, an application may close the notification sent before the + # user defined timeout. + ignore_dbusclose = false + + ### Wayland ### + # These settings are Wayland-specific. They have no effect when using X11 + + # Uncomment this if you want to let notications appear under fullscreen + # applications (default: overlay) + # layer = top + + # Set this to true to use X11 output on Wayland. + force_xwayland = false + + ### Legacy + + # Use the Xinerama extension instead of RandR for multi-monitor support. + # This setting is provided for compatibility with older nVidia drivers that + # do not support RandR and using it on systems that support RandR is highly + # discouraged. + # + # By enabling this setting dunst will not be able to detect when a monitor + # is connected or disconnected which might break follow mode if the screen + # layout changes. + force_xinerama = false + + ### mouse + + # Defines list of actions for each mouse event + # Possible values are: + # * none: Don't do anything. + # * do_action: Invoke the action determined by the action_name rule. If there is no + # such action, open the context menu. + # * open_url: If the notification has exactly one url, open it. If there are multiple + # ones, open the context menu. + # * close_current: Close current notification. + # * close_all: Close all notifications. + # * context: Open context menu for the notification. + # * context_all: Open context menu for all notifications. + # These values can be strung together for each mouse event, and + # will be executed in sequence. + mouse_left_click = close_current + mouse_middle_click = do_action, close_current + mouse_right_click = close_all + + # Experimental features that may or may not work correctly. Do not expect them + # to have a consistent behaviour across releases. + [experimental] + # Calculate the dpi to use on a per-monitor basis. + # If this setting is enabled the Xft.dpi value will be ignored and instead + # dunst will attempt to calculate an appropriate dpi value for each monitor + # using the resolution and physical size. This might be useful in setups + # where there are multiple screens with very different dpi values. + per_monitor_dpi = false + + + [urgency_low] + # IMPORTANT: colors have to be defined in quotation marks. + # Otherwise the "#" and following would be interpreted as a comment. + background = "#000000CC" + foreground = "#888888" + timeout = 6 + # Icon for notifications with low urgency, uncomment to enable + #default_icon = /path/to/icon + + [urgency_normal] + background = "#000000CC" + foreground = "#ffffff" + timeout = 6 + # Icon for notifications with normal urgency, uncomment to enable + #default_icon = /path/to/icon + + [urgency_critical] + background = "#900000CC" + foreground = "#ffffff" + frame_color = "#ffffff" + timeout = 6 + # Icon for notifications with critical urgency, uncomment to enable + #default_icon = /path/to/icon + + [disable_notification_from_fcitx5_about_gtk_im_module] + appname = "fcitx5" + skip_display = true + ''; + }; +} diff --git a/home/modules/hyprland/hypridle.nix b/home/modules/hyprland/hypridle.nix new file mode 100644 index 0000000..3f56978 --- /dev/null +++ b/home/modules/hyprland/hypridle.nix @@ -0,0 +1,33 @@ +{ lib, config, unstable, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ unstable.hypridle ]; + + home.file.".config/hypr/hypridle.conf".text = '' + general { + lock_cmd = "pidof hyprlock || hyprlock" + before_sleep_cmd = "hyprlock" + after_sleep_cmd = hyprctl dispatch dpms on + } + + listener { + timeout = 600 + on-timeout = "hyprlock" + } + + listener { + timeout = 660 + on-timeout = hyprctl dispatch dpms off + on-resume = hyprctl dispatch dpms on + } + + listener { + timeout = 1800 + on-timeout = systemctl suspend + } + ''; + }; +} diff --git a/home/modules/hyprland/hyprland.nix b/home/modules/hyprland/hyprland.nix new file mode 100644 index 0000000..976db34 --- /dev/null +++ b/home/modules/hyprland/hyprland.nix @@ -0,0 +1,238 @@ +{ lib, inputs, pkgs, config, ... }: +let + cfg = config.profile.hyprland; + select-window = rec { + filename = "select-window.sh"; + script = pkgs.writeScriptBin filename (builtins.readFile (./scripts/search-window.sh)); + path = "${script}/bin/${filename}"; + }; + init-wallpaper = rec { + filename = "init-wallpaper.sh"; + script = pkgs.writeScriptBin filename (builtins.readFile (./scripts/init-wallpaper.sh)); + path = "${script}/bin/${filename}"; + }; + gnome-keyring = rec { + filename = "gnome-keyring.sh"; + script = pkgs.writeScriptBin filename (builtins.readFile (./scripts/gnome-keyring.sh)); + path = "${script}/bin/${filename}"; + }; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ + inputs.hyprland-contrib.packages.${pkgs.system}.grimblast + ]; + sops.secrets."gnome-keyring/${config.home.username}" = { }; + wayland.windowManager.hyprland = { + enable = true; + systemd.variables = [ "all" ]; + settings = { + # window decors + general = { + gaps_in = 10; + gaps_out = 14; + border_size = 3; + "col.active_border" = "rgba(ffffffff)"; + layout = "dwindle"; + }; + + dwindle = { + pseudotile = true; + preserve_split = true; + force_split = 2; + }; + + master = { + new_is_master = true; + }; + + gestures = { + workspace_swipe = true; + workspace_swipe_create_new = false; + }; + + workspace = cfg.settings.workspaces; + + decoration = { + rounding = 10; + blur = { + enabled = true; + size = 6; + passes = 2; + new_optimizations = "on"; + ignore_opacity = true; + xray = true; + # blurls = waybar + }; + active_opacity = 1.0; + inactive_opacity = 0.9; + fullscreen_opacity = 1.0; + + drop_shadow = true; + shadow_range = 30; + shadow_render_power = 3; + "col.shadow" = "0x66000000"; + }; + + monitor = cfg.settings.monitors; + "$mod" = "SUPER"; + + # https://wiki.hyprland.org/Configuring/Binds + bind = [ + # Programs + "$mod, RETURN, exec, kitty" + "$mod, E, exec, thunar" + "$mod, B, exec, microsoft-edge" + "$mod, D, exec, rofi -show drun -replace -i" + "$mod, BackSpace, exec, wlogout" + "$mod, S, exec, pypr toggle term" + ''$mod, F, exec, ${select-window.path}'' + "$mod, W, exec, pypr wall next" + + # Workspaces + "$mod, 1, workspace, 1" + "$mod, 2, workspace, 2" + "$mod, 3, workspace, 3" + "$mod, 4, workspace, 4" + "$mod, 5, workspace, 5" + "$mod, 6, workspace, 6" + "$mod, 7, workspace, 7" + "$mod, 8, workspace, 8" + "$mod, 9, workspace, 9" + "$mod, 0, workspace, 10" + "$mod SHIFT, 1, movetoworkspace, 1" + "$mod SHIFT, 2, movetoworkspace, 2" + "$mod SHIFT, 3, movetoworkspace, 3" + "$mod SHIFT, 4, movetoworkspace, 4" + "$mod SHIFT, 5, movetoworkspace, 5" + "$mod SHIFT, 6, movetoworkspace, 6" + "$mod SHIFT, 7, movetoworkspace, 7" + "$mod SHIFT, 8, movetoworkspace, 8" + "$mod SHIFT, 9, movetoworkspace, 9" + "$mod SHIFT, 0, movetoworkspace, 10" + "$mod, mouse_down, workspace, e+1" + "$mod, mouse_up, workspace, e-1" + "$mod CTRL, down, workspace, empty" + + # Window Management + "$mod, Q, killactive" + "$mod, Space, fullscreen" + "$mod, H, movefocus, l" + "$mod, J, movefocus, d" + "$mod, k, movefocus, u" + "$mod, l, movefocus, r" + "$mod SHIFT, H, movewindow, l" + "$mod SHIFT, J, movewindow, d" + "$mod SHIFT, k, movewindow, u" + "$mod SHIFT, l, movewindow, r" + + "$mod, PRINT, exec, grimblast --notify copysave output" + ", PRINT, exec, grimblast --notify copysave area" + "SHIFT, PRINT, exec, grimblast --notify save area - | swappy -f -" + ]; + + binde = [ + "$mod CTRL, H, resizeactive, -100 0" + "$mod CTRL, J, resizeactive, 0 100" + "$mod CTRL, K, resizeactive, 0 -100" + "$mod CTRL, L, resizeactive, 100 0" + ]; + + # m -> mouse + bindm = [ + "$mod, mouse:272, movewindow" + "$mod, mouse:273, resizewindow" + ]; + # e -> repeat, will repeat when held. + # l -> even when locked + bindel = [ + # Media + ", XF86AudioRaiseVolume, exec, swayosd-client --output-volume raise --max-volume 150" + ", XF86AudioLowerVolume, exec, swayosd-client --output-volume lower --max-volume 150" + + # Light + ", XF86MonBrightnessUp, exec, swayosd-client --brightness +10" + ", XF86MonBrightnessDown, exec, swayosd-client --brightness -10" + ]; + bindl = [ + ", XF86AudioMute, exec, swayosd-client --output-volume mute-toggle" + ", XF86AudioPlay, exec, playerctl play-pause" + ", XF86AudioPause, exec, playerctl pause" + ", XF86AudioNext, exec, playerctl next" + ", XF86AudioPrev, exec, playerctl previous" + ", XF86AudioMicMute, exec, swayosd-client --input-volume mute-toggle" + ", XF86Calculator, exec, qalculate-gtk" + ]; + + input = { + follow_mouse = 1; + touchpad = { + natural_scroll = false; + }; + mouse_refocus = false; + sensitivity = 0; + kb_options = config.profile.xkb.options; + }; + + misc = { + disable_hyprland_logo = true; + disable_splash_rendering = true; + focus_on_activate = true; + enable_swallow = true; + swallow_regex = "^(Alacritty|kitty|footclient)$"; + }; + + animations = { + enabled = true; + bezier = [ + "wind, 0.05, 0.9, 0.1, 1.05" + "winIn, 0.1, 1.1, 0.1, 1.1" + "winOut, 0.3, -0.3, 0, 1" + "liner, 1, 1, 1, 1" + ]; + animation = [ + "windows, 1, 6, wind, slide" + "windowsIn, 1, 6, winIn, slide" + "windowsOut, 1, 5, winOut, slide" + "windowsMove, 1, 5, wind, slide" + "border, 1, 1, liner" + "borderangle, 1, 30, liner, loop" + "fade, 1, 10, default" + "workspaces, 1, 5, wind" + ]; + }; + + windowrulev2 = [ + config.profile.discord.window_rule + config.profile.slack.window_rule + config.profile.whatsapp.window_rule + ]; + }; + extraConfig = '' + exec-once=dbus-update-activation-enviroment --all + exec-once=${gnome-keyring.path} ${config.sops.secrets."gnome-keyring/${config.home.username}".path} + + exec-once=${init-wallpaper.path} ${./wallpaper.jpeg} + exec-once=wallust run ${config.home.homeDirectory}/.cache/wallpaper/current + exec-once=swayosd-libinput-backend + exec-once=swayosd-server + exec-once=swww-daemon + exec-once=bash -c "sleep 10; hypridle" + exec-once=waybar + exec-once=nm-applet + exec-once=pasystray + exec-once=pypr + exec-once=dunst + exec-once=fcitx5 -d + + source=${config.home.homeDirectory}/.cache/wallust/hyprland.conf + exec-once=sleep 0.2 && swww img ${config.home.homeDirectory}/.cache/wallpaper/current + + exec-once=bash -c "sleep 10; until ping -c 1 web.whatsapp.com; do sleep 1; done; whatsapp-for-linux" + exec-once=bash -c "sleep 10; until ping -c 1 discord.com; do sleep 1; done; discord" + exec-once=bash -c "sleep 10; until ping -c 1 google.com; do sleep 1; done; slack" + exec-once=bash -c "sleep 10; until ping -c 1 nextcloud.tigor.web.id; do sleep 1; done; nextcloud --background" + ''; + }; + }; +} diff --git a/home/modules/hyprland/hyprlock.nix b/home/modules/hyprland/hyprlock.nix new file mode 100644 index 0000000..25e20cf --- /dev/null +++ b/home/modules/hyprland/hyprlock.nix @@ -0,0 +1,93 @@ +{ lib, unstable, config, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ + unstable.hyprlock + ]; + + home.file.".config/hypr/hyprlock.conf".text = + let + blurred_image = "${config.home.homeDirectory}/.cache/wallpaper/blurred.png"; + in + '' + background { + monitor = + path = ${blurred_image} + } + + input-field { + monitor = + size = 200, 50 + outline_thickness = 3 + dots_size = 0.33 # Scale of input-field height, 0.2 - 0.8 + dots_spacing = 0.15 # Scale of dots' absolute size, 0.0 - 1.0 + dots_center = true + dots_rounding = -1 # -1 default circle, -2 follow input-field rounding + outer_color = rgb(151515) + inner_color = rgb(FFFFFF) + font_color = rgb(10, 10, 10) + fade_on_empty = true + fade_timeout = 1000 # Milliseconds before fade_on_empty is triggered. + placeholder_text = Input Password... # Text rendered in the input box when it's empty. + hide_input = false + rounding = -1 # -1 means complete rounding (circle/oval) + check_color = rgb(204, 136, 34) + fail_color = rgb(204, 34, 34) # if authentication failed, changes outer_color and fail message color + fail_text = $FAIL ($ATTEMPTS) # can be set to empty + fail_transition = 300 # transition time in ms between normal outer_color and fail_color + capslock_color = -1 + numlock_color = -1 + bothlock_color = -1 # when both locks are active. -1 means don't change outer color (same for above) + invert_numlock = false # change color if numlock is off + swap_font_color = false # see below + position = 0, -20 + halign = center + valign = center + } + + label { + monitor = + text = cmd[update:1000] echo "$TIME" + color = rgba(200, 200, 200, 1.0) + font_size = 55 + font_family = Fira Semibold + position = -100, -40 + halign = right + valign = bottom + shadow_passes = 5 + shadow_size = 10 + } + + label { + monitor = + text = $USER + color = rgba(200, 200, 200, 1.0) + font_size = 20 + font_family = Fira Semibold + position = -100, 160 + halign = right + valign = bottom + shadow_passes = 5 + shadow_size = 10 + } + + image { + monitor = + path = $HOME/.cache/wallpaper/square_wallpaper.png + size = 280 # lesser side if not 1:1 ratio + rounding = -1 # negative values mean circle + border_size = 4 + border_color = rgb(221, 221, 221) + rotate = 0 # degrees, counter-clockwise + reload_time = -1 # seconds between reloading, 0 to reload with SIGUSR2 + # reload_cmd = # command to get new path. if empty, old path will be used. don't run "follow" commands like tail -F + position = 0, 200 + halign = center + valign = center + } + ''; + }; +} diff --git a/home/modules/hyprland/hyprpaper.nix b/home/modules/hyprland/hyprpaper.nix new file mode 100644 index 0000000..e4d1c74 --- /dev/null +++ b/home/modules/hyprland/hyprpaper.nix @@ -0,0 +1,22 @@ +{ lib, unstable, config, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ + unstable.hyprpaper + ]; + + home.file.".config/hypr/hyprpaper.conf".text = + let + recent_wallpaper = "${config.home.homeDirectory}/.cache/wallpaper/current"; + in + '' + preload = ${recent_wallpaper} + wallpaper = ,${recent_wallpaper} + spash = false + ipc = on + ''; + }; +} diff --git a/home/modules/hyprland/pyprland.nix b/home/modules/hyprland/pyprland.nix new file mode 100644 index 0000000..b1b95be --- /dev/null +++ b/home/modules/hyprland/pyprland.nix @@ -0,0 +1,37 @@ +{ lib, pkgs, unstable, config, ... }: +let + cfg = config.profile.hyprland; + draw-wallpaper = rec { + filename = "select-wallpaper.sh"; + script = pkgs.writeScriptBin filename (builtins.readFile ./scripts/draw-wallpaper.sh); + path = "${script}/bin/${filename}"; + }; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ unstable.pyprland unstable.swww ]; + home.file.".config/hypr/pyprland.toml".source = + let + tomlFormat = pkgs.formats.toml { }; + in + tomlFormat.generate "pyprland.toml" { + # https://github.com/hyprland-community/pyprland/wiki/Getting-started#configuring + pyprland.plugins = [ + "scratchpads" + "fetch_client_menu" + "wallpapers" + ]; + scratchpads.term = { + animation = "fromTop"; + command = "kitty --class kitty-dropterm"; + class = "kitty-dropterm"; + size = "75% 75%"; + }; + wallpapers = { + path = cfg.pyprland.wallpaper-dirs; + unique = false; + command = ''${draw-wallpaper.path} [file]''; + }; + }; + }; +} diff --git a/home/modules/hyprland/rofi.nix b/home/modules/hyprland/rofi.nix new file mode 100644 index 0000000..5fcebdc --- /dev/null +++ b/home/modules/hyprland/rofi.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ + pkgs.rofi-wayland + ]; + + home.file.".config/rofi" = { + source = ./rofi; + recursive = true; + }; + }; +} diff --git a/home/modules/hyprland/rofi/config.rasi b/home/modules/hyprland/rofi/config.rasi new file mode 100644 index 0000000..637e159 --- /dev/null +++ b/home/modules/hyprland/rofi/config.rasi @@ -0,0 +1,223 @@ +@import "~/.cache/wallust/rofi.rasi" + +/* ---- Window ---- */ +window { + width: 900px; + x-offset: 0px; + y-offset: 0px; + spacing: 0px; + padding: 0px; + margin: 0px; + color: #FFFFFF; + border: @border-width; + border-color: #FFFFFF; + cursor: "default"; + transparency: "real"; + location: center; + anchor: center; + fullscreen: false; + enabled: true; + border-radius: 10px; + background-color: transparent; +} + +/* ---- Mainbox ---- */ +mainbox { + enabled: true; + orientation: horizontal; + spacing: 0px; + margin: 0px; + background-color: @background; + background-image: @current-image; + children: ["imagebox","listbox"]; +} + +/* ---- Imagebox ---- */ +imagebox { + padding: 18px; + background-color: transparent; + orientation: vertical; + children: [ "inputbar", "dummy", "mode-switcher" ]; +} + +/* ---- Listbox ---- */ +listbox { + spacing: 20px; + background-color: transparent; + orientation: vertical; + children: [ "message", "listview" ]; +} + +/* ---- Dummy ---- */ +dummy { + background-color: transparent; +} + +/* ---- Inputbar ---- */ +inputbar { + enabled: true; + text-color: @foreground; + spacing: 10px; + padding: 15px; + border-radius: 10px; + border-color: @foreground; + background-color: @background; + children: [ "textbox-prompt-colon", "entry" ]; +} + +textbox-prompt-colon { + enabled: true; + expand: false; + str: ""; + padding: 0px 5px 0px 0px; + background-color: transparent; + text-color: inherit; +} + +entry { + enabled: true; + background-color: transparent; + text-color: inherit; + cursor: text; + placeholder: "Search"; + placeholder-color: inherit; +} + +/* ---- Mode Switcher ---- */ +mode-switcher{ + enabled: true; + spacing: 20px; + background-color: transparent; + text-color: @foreground; +} + +button { + padding: 10px; + border-radius: 10px; + background-color: @background; + text-color: inherit; + cursor: pointer; + border: 0px; +} + +button selected { + background-color: @color11; + text-color: @foreground; +} + +/* ---- Listview ---- */ +listview { + enabled: true; + columns: 1; + lines: 8; + cycle: true; + dynamic: true; + scrollbar: false; + layout: vertical; + reverse: false; + fixed-height: true; + fixed-columns: true; + spacing: 0px; + padding: 10px; + margin: 0px; + background-color: @background; + border:0px; +} + +/* ---- Element ---- */ +element { + enabled: true; + padding: 10px; + margin: 5px; + cursor: pointer; + background-color: @background; + border-radius: 10px; + border: @border-width; +} + +element normal.normal { + background-color: inherit; + text-color: @foreground; +} + +element normal.urgent { + background-color: inherit; + text-color: @foreground; +} + +element normal.active { + background-color: inherit; + text-color: @foreground; +} + +element selected.normal { + background-color: @color11; + text-color: @foreground; +} + +element selected.urgent { + background-color: inherit; + text-color: @foreground; +} + +element selected.active { + background-color: inherit; + text-color: @foreground; +} + +element alternate.normal { + background-color: inherit; + text-color: @foreground; +} + +element alternate.urgent { + background-color: inherit; + text-color: @foreground; +} + +element alternate.active { + background-color: inherit; + text-color: @foreground; +} + +element-icon { + background-color: transparent; + text-color: inherit; + size: 32px; + cursor: inherit; +} + +element-text { + background-color: transparent; + text-color: inherit; + cursor: inherit; + vertical-align: 0.5; + horizontal-align: 0.0; +} + +/*****----- Message -----*****/ +message { + background-color: transparent; + border:0px; + margin:20px 0px 0px 0px; + padding:0px; + spacing:0px; + border-radius: 10px; +} + +textbox { + padding: 15px; + margin: 0px; + border-radius: 0px; + background-color: @background; + text-color: @foreground; + vertical-align: 0.5; + horizontal-align: 0.0; +} + +error-message { + padding: 15px; + border-radius: 20px; + background-color: @background; + text-color: @foreground; +} diff --git a/home/modules/hyprland/scripts/draw-wallpaper.sh b/home/modules/hyprland/scripts/draw-wallpaper.sh new file mode 100644 index 0000000..ad4b65f --- /dev/null +++ b/home/modules/hyprland/scripts/draw-wallpaper.sh @@ -0,0 +1,26 @@ +#/usr/bin/env bash + +# This is a script to draw wallpaper. +# First argument must exist and targets to image path. +# +# Requirements: +# 1. hyprland +# 2. swww +# 3. GraphicsMagick +# 4. wallust + +if [ "$1" == "" ]; then + echo "Image path must be given" + exit 1 +fi + +image_file=$1 +target="$HOME/.cache/wallpaper/current" +blur_target="$HOME/.cache/wallpaper/blurred.png" + +mkdir -p "$HOME/.cache/wallpaper" +echo "$image_file" >"$HOME/.cache/wallpaper/origin.txt" +cp "$image_file" "$target" +swww img "$target" +wallust run "$target" +gm convert -resize 75% -blur 50x30 "$target" "$blur_target" diff --git a/home/modules/hyprland/scripts/gnome-keyring.sh b/home/modules/hyprland/scripts/gnome-keyring.sh new file mode 100644 index 0000000..8f54616 --- /dev/null +++ b/home/modules/hyprland/scripts/gnome-keyring.sh @@ -0,0 +1,6 @@ +#/usr/bin/bash + +secret_file=$1 + +cat "$secret_file" | gnome-keyring-daemon --unlock +gnome-keyring-daemon --start --components=pkcs11,secrets,ssh diff --git a/home/modules/hyprland/scripts/init-wallpaper.sh b/home/modules/hyprland/scripts/init-wallpaper.sh new file mode 100644 index 0000000..635bb5d --- /dev/null +++ b/home/modules/hyprland/scripts/init-wallpaper.sh @@ -0,0 +1,26 @@ +#/usr/bin/env bash + +# This shell script ensures there are wallpaper files in expected locations +# where hyprland ecosystem expected them to find. +# +# Requirements: +# - GraphicsMagick for the 'gm' command. + +if [ "$1" == "" ]; then + echo "Initial image path is required" + exit 1 +fi + +init_wallpaper="$1" +cache_file="$HOME/.cache/wallpaper/current" +blurred="$HOME/.cache/wallpaper/blurred.png" + +mkdir -p $HOME/.cache/wallpaper + +if [ ! -f "$cache_file" ]; then + cp "$init_wallpaper" "$cache_file" +fi + +if [ ! -f "$blurred" ]; then + gm convert -resize 75% -blur 50x30 "$cache_file" "$blurred" +fi diff --git a/home/modules/hyprland/scripts/search-window.sh b/home/modules/hyprland/scripts/search-window.sh new file mode 100644 index 0000000..b445f37 --- /dev/null +++ b/home/modules/hyprland/scripts/search-window.sh @@ -0,0 +1,39 @@ +#/usr/bin/env bash +# rofi -show window for Hyprland, basically +# +# Requires gojq and rofi to be on PATH. + +state="$(hyprctl -j clients)" +active_window="$(hyprctl -j activewindow)" + +current_addr="$(echo "$active_window" | gojq -r '.address')" + +window="$(echo "$state" | + gojq -r '.[] | select(.monitor != -1 ) | "\(.address) \(.workspace.name) \(.title)"' | + grep -v "scratch_term" | + sed "s|$current_addr|focused ->|" | + sort -r | + rofi -dmenu -i -matching fuzzy)" + +addr="$(echo "$window" | awk '{print $1}')" +ws="$(echo "$window" | awk '{print $2}')" + +if [[ "$addr" =~ focused* ]]; then + echo 'already focused, exiting' + exit 0 +fi + +fullscreen_on_same_ws="$(echo "$state" | gojq -r ".[] | select(.fullscreen == true) | select(.workspace.name == \"$ws\") | .address")" + +if [[ "$window" != "" ]]; then + if [[ "$fullscreen_on_same_ws" == "" ]]; then + hyprctl dispatch focuswindow address:${addr} + else + # If we want to focus app_A and app_B is fullscreen on the same workspace, + # app_A will get focus, but app_B will remain on top. + # This monstrosity is to make sure app_A will end up on top instead. + # XXX: doesn't handle fullscreen 0, but I don't care. + notify-send 'Complex switch' "$window" + hyprctl --batch "dispatch focuswindow address:${fullscreen_on_same_ws}; dispatch fullscreen 1; dispatch focuswindow address:${addr}; dispatch fullscreen 1" + fi +fi diff --git a/home/modules/hyprland/swappy.nix b/home/modules/hyprland/swappy.nix new file mode 100644 index 0000000..00f9cf4 --- /dev/null +++ b/home/modules/hyprland/swappy.nix @@ -0,0 +1,22 @@ +{ lib, pkgs, config, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ pkgs.swappy ]; + + home.file.".config/swappy/config".text = '' + [Default] + save_dir=${config.home.homeDirectory}/Pictures/screenshots + save_filename_format=swappy-%Y%m%d-%H%M%S.png + show_panel=true + line_size=5 + text_size=20 + text_font=sans-serif + paint_mode=brush + early_exit=true + fill_shape=false + ''; + }; +} diff --git a/home/modules/hyprland/wallpaper.jpeg b/home/modules/hyprland/wallpaper.jpeg new file mode 100755 index 0000000..cb44928 Binary files /dev/null and b/home/modules/hyprland/wallpaper.jpeg differ diff --git a/home/modules/hyprland/wallust-build.nix b/home/modules/hyprland/wallust-build.nix new file mode 100644 index 0000000..9d1d8c5 --- /dev/null +++ b/home/modules/hyprland/wallust-build.nix @@ -0,0 +1,43 @@ +{ lib +, fetchFromGitea +, rustPlatform +, nix-update-script +, imagemagick +, makeWrapper +, unstable +}: +let + version = "3.0.0-beta"; +in +rustPlatform.buildRustPackage { + pname = "wallust"; + inherit version; + + src = fetchFromGitea { + domain = "codeberg.org"; + owner = "explosion-mental"; + repo = "wallust"; + rev = version; + hash = "sha256-gGyxRdv2I/3TQWrTbUjlJGsaRv4SaNE+4Zo9LMWmxk8="; + }; + + cargoHash = "sha256-dkHS8EOzmn5VLiKP3SMT0ZGAsk2wzvQeioG7NuGGUzA="; + + nativeBuildInputs = [ makeWrapper unstable.rustc ]; + + postFixup = '' + wrapProgram $out/bin/wallust \ + --prefix PATH : "${lib.makeBinPath [ imagemagick ]}" + ''; + + passthru.updateScript = nix-update-script { }; + + meta = { + description = "A better pywal"; + homepage = "https://codeberg.org/explosion-mental/wallust"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ onemoresuza iynaix ]; + downloadPage = "https://codeberg.org/explosion-mental/wallust/releases/tag/${version}"; + mainProgram = "wallust"; + }; +} diff --git a/home/modules/hyprland/wallust-templates/alacritty.toml b/home/modules/hyprland/wallust-templates/alacritty.toml new file mode 100644 index 0000000..74838f5 --- /dev/null +++ b/home/modules/hyprland/wallust-templates/alacritty.toml @@ -0,0 +1,31 @@ +[window] +opacity = {{alpha/100}} + +[colors] +[colors.primary] +background = "{{background}}" +foreground = "{{foreground}}" + +[colors.cursor] +text = "CellForeground" +cursor = "{{cursor}}" + +[colors.bright] +black = "{{color0}}" +red = "{{color1}}" +green = "{{color2}}" +yellow = "{{color3}}" +blue = "{{color4}}" +magenta = "{{color5}}" +cyan = "{{color6}}" +white = "{{color7}}" + +[colors.normal] +black = "{{color8}}" +red = "{{color9}}" +green = "{{color10}}" +yellow = "{{color11}}" +blue = "{{color12}}" +magenta = "{{color13}}" +cyan = "{{color14}}" +white = "{{color15}}" diff --git a/home/modules/hyprland/wallust-templates/base16-nvim.lua b/home/modules/hyprland/wallust-templates/base16-nvim.lua new file mode 100644 index 0000000..c19bf96 --- /dev/null +++ b/home/modules/hyprland/wallust-templates/base16-nvim.lua @@ -0,0 +1,30 @@ +require("mini.base16").setup({ + palette = { + base00 = "{{color0}}", -- Background + base01 = "{{color1 | darken(0.75)}}", -- CursorLine, CMP Background + base02 = "{{color2 | darken(0.50)}}", -- Visual Select + base03 = "{{color3 | blend(color1)}}", -- Comment, MatchParen + base04 = "{{color4}}", -- Keywords, properties, Line Number + base05 = "{{color5}}", -- NormalText, CMP Selection, TSProperty + base06 = "{{color6}}", + base07 = "{{color7}}", + base08 = "{{color8 | complementary}}", -- TSVariable + base09 = "{{color9 | complementary | lighten(0.25)}}", -- TSConstant, @constant (booleans, etc) + base0A = "{{color10 | complementary | lighten(0.25)}}", -- CMP Property (Field), TSType + base0B = "{{color11 | blend(color7) | complementary | lighten(0.25)}}", -- String Texts + base0C = "{{color12}}", -- Types, Regex + base0D = "{{color13}}", -- Functions, String Escape + base0E = "{{color14}}", + base0F = "{{color15}}", + }, + use_cterm = vim.fn.has("termguicolors") == 0, + plugins = { default = true }, +}) + +------- Neovide Configuration ------- + +-- stylua: ignore start +vim.g.neovide_transparency = {{alpha/100}} +-- stylua: ignore end + +vim.g.neovide_background_color = "{{color0}}{{ alpha | alpha_hexa }}" diff --git a/home/modules/hyprland/wallust-templates/hyprland.conf b/home/modules/hyprland/wallust-templates/hyprland.conf new file mode 100644 index 0000000..bff4cd3 --- /dev/null +++ b/home/modules/hyprland/wallust-templates/hyprland.conf @@ -0,0 +1,26 @@ +$background = rgb({{background | strip}}) +$foreground = rgb({{foreground | strip}}) +$color0 = rgb({{color0 | strip}}) +$color1 = rgb({{color1 | strip}}) +$color2 = rgb({{color2 | strip}}) +$color3 = rgb({{color3 | strip}}) +$color4 = rgb({{color4 | strip}}) +$color5 = rgb({{color5 | strip}}) +$color6 = rgb({{color6 | strip}}) +$color7 = rgb({{color7 | strip}}) +$color8 = rgb({{color8 | strip}}) +$color9 = rgb({{color9 | strip}}) +$color10 = rgb({{color10 | strip}}) +$color11 = rgb({{color11 | strip}}) +$color12 = rgb({{color12 | strip}}) +$color13 = rgb({{color13 | strip}}) +$color14 = rgb({{color14 | strip}}) +$color15 = rgb({{color15 | strip}}) + +general { + col.inactive_border = $color11 +} + +decoration { + inactive_opacity = {{alpha / 100}} +} diff --git a/home/modules/hyprland/wallust-templates/kitty.conf b/home/modules/hyprland/wallust-templates/kitty.conf new file mode 100644 index 0000000..5ff7bc2 --- /dev/null +++ b/home/modules/hyprland/wallust-templates/kitty.conf @@ -0,0 +1,30 @@ +foreground {{foreground}} +background {{background}} +background_opacity {{ alpha / 100 }} +cursor {{cursor}} + +active_tab_foreground {{background}} +active_tab_background {{foreground}} +inactive_tab_foreground {{foreground}} +inactive_tab_background {{background}} + +active_border_color {{foreground}} +inactive_border_color {{background}} +bell_border_color {{color1}} + +color0 {{color0}} +color1 {{color1}} +color2 {{color2}} +color3 {{color3}} +color4 {{color4}} +color5 {{color5}} +color6 {{color6}} +color7 {{color7}} +color8 {{color8}} +color9 {{color9}} +color10 {{color10}} +color11 {{color11}} +color12 {{color12}} +color13 {{color13}} +color14 {{color14}} +color15 {{color15}} diff --git a/home/modules/hyprland/wallust-templates/rofi.rasi b/home/modules/hyprland/wallust-templates/rofi.rasi new file mode 100644 index 0000000..4f4960c --- /dev/null +++ b/home/modules/hyprland/wallust-templates/rofi.rasi @@ -0,0 +1,22 @@ +* { + background: rgba(0,0,1,0.5); + foreground: #FFFFFF; + color0: {{color0}}; + color1: {{color1}}; + color2: {{color2}}; + color3: {{color3}}; + color4: {{color4}}; + color5: {{color5}}; + color6: {{color6}}; + color7: {{color7}}; + color8: {{color8}}; + color9: {{color9}}; + color10: {{color10}}; + color11: {{color11}}; + color12: {{color12}}; + color13: {{color13}}; + color14: {{color14}}; + color15: {{color15}}; + border-width: 3px; + current-image: url("~/.cache/wallpaper/blurred.png", height); +} diff --git a/home/modules/hyprland/wallust-templates/waybar.css b/home/modules/hyprland/wallust-templates/waybar.css new file mode 100644 index 0000000..06a8e0b --- /dev/null +++ b/home/modules/hyprland/wallust-templates/waybar.css @@ -0,0 +1,456 @@ +@define-color foreground {{foreground}}; +@define-color background {{background}}; +@define-color cursor {{cursor}}; + +@define-color color0 {{color0}}; +@define-color color1 {{color1}}; +@define-color color2 {{color2}}; +@define-color color3 {{color3 | lighten(0.5)}}; +@define-color color4 {{color4}}; +@define-color color5 {{color5}}; +@define-color color6 {{color6}}; +@define-color color7 {{color7}}; +@define-color color8 {{color8}}; +@define-color color9 {{color9}}; +@define-color color10 {{color10}}; +@define-color color11 {{color11}}; +@define-color color12 {{color12}}; +@define-color color13 {{color13}}; +@define-color color14 {{color14}}; +@define-color color15 {{color15}}; + +@define-color backgroundlight {{color8}}; +@define-color backgrounddark {{foreground}}; +@define-color workspacesbackground1 {{foreground | darken(0.4)}}; +@define-color workspacesbackground2 {{foreground}}; +@define-color bordercolor {{color8}}; +@define-color textcolor1 {{color8}}; +@define-color textcolor2 {{foreground}}; +@define-color textcolor3 {{foreground}}; +@define-color iconcolor {{foreground}}; + +@define-color group-background-color rgba({{color2 | rgb}}, 0.3); +@define-color group-border-color rgba({{foreground | rgb}}, 0.8); +@define-color tooltip-background-color rgba({{color1 | rgb}}, 0.95); +@define-color text-base {{foreground}}; +@define-color text-alt {{color8}}; + +* { + font-family: "Fira Sans Semibold", FontAwesome, Roboto, Helvetica, Arial, sans-serif; + border: none; + border-radius: 0px; +} + +window#waybar { + background-color: rgba({{background | rgb}}, 0.3); + border: 0px; + color: {{foreground}}; + transition-property: background-color; + transition-duration: 0.5s; +} + +/* ----------------------------------------------------- +* Workspaces +* ----------------------------------------------------- */ + +#workspaces { + background: @group-background-color; + margin: 5px 1px 6px 1px; + padding: 0px 0.75rem; + border-radius: 24px; + border: 2px solid @group-border-color; + font-weight: bold; + font-style: normal; + font-size: 16px; +} + +#workspaces button { + padding: 0px 5px; + margin: 4px 3px; + border-radius: 15px; + border: 0px; + color: @textcolor1; + background-color: @workspacesbackground2; + transition: all 0.3s ease-in-out; +} + +#workspaces button.active { + color: @textcolor1; + background: @workspacesbackground2; + border-radius: 15px; + min-width: 40px; + transition: all 0.3s ease-in-out; + opacity: 1; +} + +#workspaces button:hover { + color: @textcolor1; + background: @workspacesbackground2; + border-radius: 15px; + opacity: 0.7; +} + +/* ----------------------------------------------------- +* Tooltips +* ----------------------------------------------------- */ + +tooltip { + border-radius: 10px; + background-color: @tooltip-background-color; + padding: 20px; + margin: 0px; + border: 1px solid @textcolor2; +} + +tooltip label { + color: @textcolor2; +} + +/* ----------------------------------------------------- +* Window +* ----------------------------------------------------- */ + +#window { + background: @group-background-color; + border: 2px solid @group-border-color; + margin: 8px 15px 8px 0px; + padding: 2px 10px 0px 10px; + border-radius: 12px; + color: @textcolor2; + font-size: 16px; + font-weight: normal; +} + +window#waybar.empty #window { + background-color: transparent; + border: 0px; +} + +/* ----------------------------------------------------- + * Taskbar + * ----------------------------------------------------- */ + +#taskbar { + background: @backgroundlight; + margin: 6px 15px 6px 0px; + padding: 0px; + border-radius: 15px; + font-weight: normal; + font-style: normal; + opacity: 0.8; + border: 3px solid @backgroundlight; +} + +#taskbar button { + margin: 0; + border-radius: 15px; + padding: 0px 5px 0px 5px; +} + +/* ----------------------------------------------------- + * Modules + * ----------------------------------------------------- */ + +.modules-left { + padding-left: 1rem; +} + +.modules-left > widget:first-child > #workspaces { + margin-left: 0; +} + +.modules-right > widget:last-child > #workspaces { + margin-right: 0; +} + +/* ----------------------------------------------------- +* Custom Quicklinks +* ----------------------------------------------------- */ + +#custom-brave, +#custom-browser, +#custom-keybindings, +#custom-outlook, +#custom-filemanager, +#custom-teams, +#custom-chatgpt, +#custom-calculator, +#custom-windowsvm, +#custom-cliphist, +#custom-wallpaper, +#custom-settings, +#custom-wallpaper, +#custom-system, +#custom-waybarthemes { + margin-right: 23px; + font-size: 20px; + font-weight: bold; + opacity: 0.8; + color: @iconcolor; +} + +#custom-system { + margin-right: 15px; +} + +#custom-wallpaper { + margin-right: 25px; +} + +#custom-waybarthemes, +#custom-settings { + margin-right: 20px; +} + +#custom-ml4w-welcome { + margin-right: 12px; + background-image: url("../assets/ml4w-icon.png"); + background-repeat: no-repeat; + background-position: center; + padding-right: 24px; +} + +#custom-ml4w-hyprland-settings { + margin-right: 12px; + background-image: url("../assets/hyprland-icon.png"); + background-repeat: no-repeat; + background-position: center; + padding-right: 16px; +} + +#custom-chatgpt { + margin-right: 12px; + background-image: url("../assets/ai-icon-20.png"); + background-repeat: no-repeat; + background-position: center; + padding-right: 24px; +} + +/* ----------------------------------------------------- + * Idle Inhibator + * ----------------------------------------------------- */ + +#idle_inhibitor { + margin-right: 17px; + font-size: 20px; + font-weight: bold; + opacity: 0.8; + color: @iconcolor; +} + +#idle_inhibitor.activated { + margin-right: 15px; + font-size: 20px; + font-weight: bold; + opacity: 0.8; + color: #dc2f2f; +} + +/* ----------------------------------------------------- + * Custom Modules + * ----------------------------------------------------- */ + +#custom-appmenu { + background-color: @backgrounddark; + font-size: 16px; + color: @textcolor1; + border-radius: 15px; + padding: 0px 10px 0px 10px; + margin: 8px 14px 8px 14px; + opacity: 0.8; + border: 3px solid @bordercolor; +} + +/* ----------------------------------------------------- + * Custom Exit + * ----------------------------------------------------- */ + +#custom-exit { + margin: 0px 20px 0px 0px; + padding: 0px; + font-size: 20px; + color: @iconcolor; +} + +/* ----------------------------------------------------- + * Custom Updates + * ----------------------------------------------------- */ + +#custom-updates { + background-color: @backgroundlight; + font-size: 16px; + color: @textcolor2; + border-radius: 15px; + padding: 2px 10px 0px 10px; + margin: 8px 15px 8px 0px; + opacity: 0.8; +} + +#custom-updates.green { + background-color: @backgroundlight; +} + +#custom-updates.yellow { + background-color: #ff9a3c; + color: #ffffff; +} + +#custom-updates.red { + background-color: #dc2f2f; + color: #ffffff; +} + +/* ----------------------------------------------------- + * Custom Youtube + * ----------------------------------------------------- */ + +#custom-youtube { + background-color: @backgroundlight; + font-size: 16px; + color: @textcolor2; + border-radius: 15px; + padding: 2px 10px 0px 10px; + margin: 8px 15px 8px 0px; + opacity: 0.8; +} + +/* ----------------------------------------------------- + * Hardware Group + * ----------------------------------------------------- */ + +#disk, +#memory, +#cpu, +#language { + margin: 0px; + padding: 0px; + font-size: 16px; + color: @iconcolor; +} + +#language { + margin-right: 10px; +} + +/* ----------------------------------------------------- + * Clock + * ----------------------------------------------------- */ + +#clock { + background-color: @group-background-color; + font-size: 16px; + color: @text-base; + border-radius: 15px; + padding: 1px 10px 0px 10px; + margin: 8px 15px 8px 0px; + border: 3px solid @group-border-color; +} + +/* ----------------------------------------------------- +* Pulseaudio +* ----------------------------------------------------- */ + +#pulseaudio { + background-color: @group-background-color; + font-size: 16px; + border: 2px solid @group-border-color; + color: @textcolor2; + border-radius: 15px; + padding: 2px 10px 0px 10px; + margin: 8px 15px 8px 0px; +} + +#pulseaudio.muted { + color: @color3; + border-color: @color3; +} + +/* ----------------------------------------------------- +* Network +* ----------------------------------------------------- */ + +#network { + background-color: @group-background-color; + border: 2px solid @group-border-color; + font-size: 16px; + color: @text-base; + border-radius: 15px; + padding: 2px 10px 0px 10px; + margin: 8px 15px 8px 0px; +} + +/* ----------------------------------------------------- + * Bluetooth + * ----------------------------------------------------- */ + +#bluetooth, +#bluetooth.on, +#bluetooth.connected { + background-color: @group-background-color; + border: 2px solid @group-border-color; + font-size: 16px; + color: @text-base; + border-radius: 15px; + padding: 2px 10px 0px 10px; + margin: 8px 15px 8px 0px; +} + +#bluetooth.off { + background-color: transparent; + padding: 0px; + margin: 0px; +} + +/* ----------------------------------------------------- +* Battery +* ----------------------------------------------------- */ + +#battery { + background-color: @group-background-color; + border: 2px solid @group-border-color; + font-size: 16px; + color: @text-base; + border-radius: 15px; + padding: 2px 15px 0px 10px; + margin: 8px 15px 8px 0px; + opacity: 0.8; +} + +#battery.charging, +#battery.plugged { + color: @text-base; +} + +@keyframes blink { + to { + background-color: @backgroundlight; + color: @textcolor2; + } +} + +#battery.critical:not(.charging) { + background-color: #f53c3c; + color: @textcolor3; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +/* ----------------------------------------------------- + * Tray + * ----------------------------------------------------- */ + +#tray { + padding: 0px 15px 0px 0px; + color: @textcolor3; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; +} diff --git a/home/modules/hyprland/wallust-templates/wlogout.css b/home/modules/hyprland/wallust-templates/wlogout.css new file mode 100644 index 0000000..30b98cf --- /dev/null +++ b/home/modules/hyprland/wallust-templates/wlogout.css @@ -0,0 +1,20 @@ +@define-color foreground {{foreground}}; +@define-color background {{background}}; +@define-color cursor {{cursor}}; + +@define-color color0 {{color0}}; +@define-color color1 {{color1}}; +@define-color color2 {{color2}}; +@define-color color3 {{color3}}; +@define-color color4 {{color4}}; +@define-color color5 {{color5}}; +@define-color color6 {{color6}}; +@define-color color7 {{color7}}; +@define-color color8 {{color8}}; +@define-color color9 {{color9}}; +@define-color color10 {{color10}}; +@define-color color11 {{color11}}; +@define-color color12 {{color12}}; +@define-color color13 {{color13}}; +@define-color color14 {{color14}}; +@define-color color15 {{color15}}; diff --git a/home/modules/hyprland/wallust.nix b/home/modules/hyprland/wallust.nix new file mode 100644 index 0000000..400754c --- /dev/null +++ b/home/modules/hyprland/wallust.nix @@ -0,0 +1,101 @@ +{ pkgs, unstable, lib, config, ... }: +let + cfg = config.profile.hyprland; + wallust = cfg.wallust; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ + pkgs.imagemagick + # unstable.wallust + (pkgs.callPackage ./wallust-build.nix { inherit unstable; }) + ]; + + home. file.".config/wallust/templates" = { + source = ./wallust-templates; + recursive = true; + }; + + home.file.".config/wallust/wallust.toml".source = + let + tomlFormat = pkgs.formats.toml { }; + in + tomlFormat.generate + "wallust.toml" + { + # See https://codeberg.org/explosion-mental/wallust/src/branch/master/wallust.toml + # for more information about the configuration options. + + # How the image is parse, in order to get the colors: + # full - resized - wal - thumb - fastresize - kmeans + backend = wallust.backend; + + # What color space to use to produce and select the most prominent colors: + # lab - labmixed - lch - lchmixed + color_space = wallust.colorSpace; + threshold = wallust.threshold; + + # Use the most prominent colors in a way that makes sense, a scheme color palette: + # dark - dark16 - darkcomp - darkcomp16 + # light - light16 - lightcomp - lightcomp16 + # harddark - harddark16 - harddarkcomp - harddarkcomp16 + # softdark - softdark16 - softdarkcomp - softdarkcomp16 + # softlight - softlight16 - softlightcomp - softlightcomp16 + palette = wallust.palette; + + # Ensures a "readable contrast" (OPTIONAL, disabled by default) + # Should only be enabled when you notice an unreadable contrast frequently happening + # with your images. The reference color for the contrast is the background color. + check_contrast = wallust.checkContrast; + + # Color saturation, between [1% and 100%] (OPTIONAL, disabled by default) + # usually something higher than 50 increases the saturation and below + # decreases it (on a scheme with strong and vivid colors) + # saturation = 50; + + # Alpha value for templating, by default 100 (no other use whatsoever) + alpha = wallust.alpha; + + templates = + # Templates requires certain syntax + # + # See: https://codeberg.org/explosion-mental/wallust/wiki/wallust.1-Man-Page + # Note that the documentation is for 3.x and above. + let + out = config.home.homeDirectory + "/.cache/wallust"; + in + { + waybar = { + template = "templates/waybar.css"; + # target = out + "/waybar.css"; + target = "${config.home.homeDirectory}/.config/waybar/style.css"; + }; + wlogout = { + template = "templates/wlogout.css"; + target = out + "/wlogout.css"; + }; + hyprland = { + template = "templates/hyprland.conf"; + target = out + "/hyprland.conf"; + }; + kitty = { + template = "templates/kitty.conf"; + target = "${config.home.homeDirectory}/.config/kitty/kitty.d/99-colors.conf"; + }; + base16-nvim = { + template = "templates/base16-nvim.lua"; + target = out + "/base16-nvim.lua"; + }; + rofi = { + template = "templates/rofi.rasi"; + target = out + "/rofi.rasi"; + }; + alacritty = { + template = "templates/alacritty.toml"; + target = out + "/alacritty.toml"; + }; + }; + }; + }; + +} diff --git a/home/modules/hyprland/waybar-modules.jsonc b/home/modules/hyprland/waybar-modules.jsonc new file mode 100644 index 0000000..5ed9441 --- /dev/null +++ b/home/modules/hyprland/waybar-modules.jsonc @@ -0,0 +1,308 @@ +{ + // Taskbar + "wlr/taskbar": { + "format": "{icon}", + "icon-size": 18, + "tooltip-format": "{title}", + "on-click": "activate", + "on-click-middle": "close", + "ignore-list": ["Alacritty"], + "app_ids-mapping": { + "firefoxdeveloperedition": "firefox-developer-edition" + }, + "rewrite": { + "Firefox Web Browser": "Firefox", + "Foot Server": "Terminal" + } + }, + // Hyprland Window + "hyprland/window": { + "rewrite": { + "(.*) - Brave": "$1", + "(.*) - Chromium": "$1", + "(.*) - Brave Search": "$1", + "(.*) - Outlook": "$1", + "(.*) Microsoft Teams": "$1" + }, + "separate-outputs": true + }, + // ML4W Welcome App + "custom/ml4w-welcome": { + "on-click": "sleep 0.1 && ~/dotfiles/eww/ml4w-sidebar/launch.sh", + "on-click-right": "sleep 0.1 && ~/dotfiles/apps/ML4W_Welcome-x86_64.AppImage", + "format": " ", + "tooltip": false + }, + // ML4W Welcome App + "custom/ml4w-hyprland-settings": { + "on-click": "~/dotfiles/apps/ML4W_Hyprland_Settings-x86_64.AppImage", + "format": " ", + "tooltip": false + }, + // Empty + "custom/empty": { + "format": "" + }, + // Youtube Subscriber Count + "custom/youtube": { + "format": " {}", + "exec": "python ~/private/youtube.py", + "restart-interval": 600, + "on-click": "chromium https://studio.youtube.com", + "tooltip": false + }, + // Cliphist + "custom/cliphist": { + "format": "", + "on-click": "sleep 0.1 && ~/dotfiles/scripts/cliphist.sh", + "on-click-right": "sleep 0.1 && ~/dotfiles/scripts/cliphist.sh d", + "on-click-middle": "sleep 0.1 && ~/dotfiles/scripts/cliphist.sh w", + "tooltip": false + }, + // Updates Count + "custom/updates": { + "format": " {}", + "tooltip-format": "{}", + "escape": true, + "return-type": "json", + "exec": "~/dotfiles/scripts/updates.sh", + "restart-interval": 60, + "on-click": "alacritty --class dotfiles-floating -e ~/dotfiles/scripts/installupdates.sh", + "on-click-right": "~/dotfiles/.settings/software.sh", + "tooltip": false + }, + // Wallpaper + "custom/wallpaper": { + "format": "", + "on-click": "~/dotfiles/hypr/scripts/wallpaper.sh select", + "on-click-right": "~/dotfiles/hypr/scripts/wallpaper.sh", + "tooltip": false + }, + // Waybar Themes + "custom/waybarthemes": { + "format": "", + "on-click": "~/dotfiles/waybar/themeswitcher.sh", + "tooltip": false + }, + // Settings + "custom/settings": { + "format": "", + "on-click": "~/dotfiles/apps/ML4W_Dotfiles_Settings-x86_64.AppImage", + "tooltip": false + }, + // Keybindings + "custom/keybindings": { + "format": "", + "on-click": "~/dotfiles/hypr/scripts/keybindings.sh", + "tooltip": false + }, + // Filemanager Launcher + "custom/filemanager": { + "format": "", + "on-click": "thunar", + "tooltip": false + }, + // Browser Launcher + "custom/browser": { + "format": "", + "on-click": "microsoft-edge", + "tooltip": false + }, + // ChatGPT Launcher + "custom/chatgpt": { + "format": "󰭹", + "on-click": "chromium --app=https://chat.openai.com", + "tooltip": false + }, + // Calculator + "custom/calculator": { + "format": "", + "on-click": "qalculate-gtk", + "tooltip": false + }, + // Windows VM + "custom/windowsvm": { + "format": "", + "on-click": "~/dotfiles/scripts/launchvm.sh", + "tooltip": false + }, + // Rofi Application Launcher + "custom/appmenu": { + // START APPS LABEL + "format": "Apps", + // END APPS LABEL + "on-click": "sleep 0.2;rofi -show drun -replace", + "on-click-right": "~/dotfiles/hypr/scripts/keybindings.sh", + "tooltip": false + }, + // Rofi Application Launcher + "custom/appmenuicon": { + "format": "", + "on-click": "rofi -show drun -replace", + "on-click-right": "~/dotfiles/hypr/scripts/keybindings.sh", + "tooltip": false + }, + // Power Menu + "custom/exit": { + "format": "", + "on-click": "wlogout", + "tooltip": false + }, + // Keyboard State + "keyboard-state": { + "numlock": true, + "capslock": true, + "format": "{name} {icon}", + "format-icons": { + "locked": "", + "unlocked": "" + } + }, + // System tray + "tray": { + "icon-size": 21, + "spacing": 10 + }, + // Clock + "clock": { + "format": "{:%H:%M %a}", + // "timezone": "America/New_York", + "tooltip-format": "{:%Y %B}\n{calendar}", + // START CLOCK FORMAT + "format-alt": "{:%Y-%m-%d}" + // END CLOCK FORMAT + }, + // System + "custom/system": { + "format": "", + "tooltip": false + }, + // CPU + "cpu": { + "format": "/ C {usage}% ", + "on-click": "kitty --override confirm_os_window_close=0 btop" + }, + // Memory + "memory": { + "format": "/ M {}% ", + "on-click": "kitty --override confirm_os_window_close=0 btop" + }, + // Harddisc space used + "disk": { + "interval": 30, + "format": "D {percentage_used}% ", + "path": "/", + "on-click": "kitty --override confirm_os_window_close=0 btop" + }, + "hyprland/language": { + "format": "/ K {short}" + }, + // Group Hardware + "group/hardware": { + "orientation": "inherit", + "drawer": { + "transition-duration": 300, + "children-class": "not-memory", + "transition-left-to-right": false + }, + "modules": ["custom/system", "disk", "cpu", "memory", "hyprland/language"] + }, + // Group Settings + "group/links": { + "orientation": "horizontal", + "modules": ["custom/chatgpt", "custom/empty"] + }, + // Group Settings + "group/settings": { + "orientation": "inherit", + "drawer": { + "transition-duration": 300, + "children-class": "not-memory", + "transition-left-to-right": false + }, + "modules": [ + "custom/settings", + "custom/waybarthemes", + "custom/wallpaper", + "custom/ml4w-hyprland-settings" + ] + }, + // Group Quicklinks + "group/quicklinks": { + "orientation": "horizontal", + "modules": ["custom/browser", "custom/filemanager", "custom/chatgpt"] + }, + // Network + "network": { + "format": "{ifname}", + "format-wifi": " {signalStrength}%", + "format-ethernet": " {ifname}", + "format-disconnected": "Disconnected", + "tooltip-format": " {ifname} via {gwaddri}", + "tooltip-format-wifi": " {ifname} @ {essid}\nIP: {ipaddr}\nStrength: {signalStrength}%\nFreq: {frequency}MHz\nUp: {bandwidthUpBits} Down: {bandwidthDownBits}", + "tooltip-format-ethernet": " {ifname}\nIP: {ipaddr}\n up: {bandwidthUpBits} down: {bandwidthDownBits}", + "tooltip-format-disconnected": "Disconnected", + "max-length": 50, + "on-click": "nm-connection-editor" + }, + // Battery + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{icon} {capacity}%", + "format-charging": " {capacity}%", + "format-plugged": " {capacity}%", + "format-alt": "{icon} {time}", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": [" ", " ", " ", " ", " "] + }, + // Pulseaudio + "pulseaudio": { + // "scroll-step": 1, // %, can be a float + "format": "{icon} {volume}%", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " {format_source}", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": " ", + "hands-free": " ", + "headset": " ", + "phone": " ", + "portable": " ", + "car": " ", + "default": [" ", " ", " "] + }, + "on-click": "pavucontrol" + }, + // Bluetooth + "bluetooth": { + "format": " {status}", + "format-disabled": "", + "format-off": "", + "interval": 30, + "on-click": "blueman-manager", + "format-no-controller": "" + }, + // Other + "user": { + "format": "{user}", + "interval": 60, + "icon": false + }, + // Idle Inhibator + "idle_inhibitor": { + "format": "{icon}", + "tooltip": true, + "format-icons": { + "activated": "", + "deactivated": "" + }, + "on-click-right": "hyprlock" + } +} diff --git a/home/modules/hyprland/waybar.nix b/home/modules/hyprland/waybar.nix new file mode 100644 index 0000000..7284033 --- /dev/null +++ b/home/modules/hyprland/waybar.nix @@ -0,0 +1,76 @@ +{ lib, config, unstable, pkgs, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ pkgs.btop ]; + home.file.".config/waybar/modules.jsonc".source = ./waybar-modules.jsonc; + home.file.".config/waybar/hyprland.jsonc".text = builtins.toJSON { + "hyprland/workspaces" = { + "on-click" = "activate"; + "active-only" = false; + "all-outputs" = false; + "format" = "{icon}"; + "format-icons" = { + "1" = "1"; + "2" = "2"; + "3" = "3"; + "4" = "4"; + "5" = " 5"; + "6" = " 6"; + "7" = "󰙯 7"; + "8" = "8"; + "9" = "9"; + "10" = "10"; + }; + "persistent-workspaces" = cfg.waybar.persistent-workspaces; + "ignore-workspaces" = [ + ''^-'' # Ignore negatives (Scratchpads takes negavite workspace values). + ]; + }; + }; + programs.waybar = { + package = unstable.waybar; + enable = true; + settings = { + mainBar = { + layer = "top"; + padding-left = 4; + margin-top = 0; + margin-bottom = 0; + margin-left = 0; + margin-right = 0; + spacing = 0; + reload_style_on_change = true; + include = [ + "~/.config/waybar/modules.jsonc" + "~/.config/waybar/hyprland.jsonc" + ]; + modules-left = [ + "group/quicklinks" + "hyprland/window" + ]; + modules-center = [ + "hyprland/workspaces" + ]; + modules-right = [ + "pulseaudio" + "bluetooth" + "battery" + "network" + "group/hardware" + "custom/cliphist" + "idle_inhibitor" + "tray" + "custom/exit" + "clock" + ]; + }; + }; + # style = '' + # @import "${config.home.homeDirectory}/.cache/wallust/waybar.css"; + # ''; + }; + }; +} diff --git a/home/modules/hyprland/wlogout-icons/hibernate.png b/home/modules/hyprland/wlogout-icons/hibernate.png new file mode 100644 index 0000000..bf2b001 Binary files /dev/null and b/home/modules/hyprland/wlogout-icons/hibernate.png differ diff --git a/home/modules/hyprland/wlogout-icons/lock.png b/home/modules/hyprland/wlogout-icons/lock.png new file mode 100644 index 0000000..da59b10 Binary files /dev/null and b/home/modules/hyprland/wlogout-icons/lock.png differ diff --git a/home/modules/hyprland/wlogout-icons/logout.png b/home/modules/hyprland/wlogout-icons/logout.png new file mode 100644 index 0000000..8a25922 Binary files /dev/null and b/home/modules/hyprland/wlogout-icons/logout.png differ diff --git a/home/modules/hyprland/wlogout-icons/reboot.png b/home/modules/hyprland/wlogout-icons/reboot.png new file mode 100644 index 0000000..e5fd221 Binary files /dev/null and b/home/modules/hyprland/wlogout-icons/reboot.png differ diff --git a/home/modules/hyprland/wlogout-icons/shutdown.png b/home/modules/hyprland/wlogout-icons/shutdown.png new file mode 100644 index 0000000..663ca03 Binary files /dev/null and b/home/modules/hyprland/wlogout-icons/shutdown.png differ diff --git a/home/modules/hyprland/wlogout-icons/suspend.png b/home/modules/hyprland/wlogout-icons/suspend.png new file mode 100644 index 0000000..af099b9 Binary files /dev/null and b/home/modules/hyprland/wlogout-icons/suspend.png differ diff --git a/home/modules/hyprland/wlogout.nix b/home/modules/hyprland/wlogout.nix new file mode 100644 index 0000000..a560e10 --- /dev/null +++ b/home/modules/hyprland/wlogout.nix @@ -0,0 +1,142 @@ +{ lib, config, ... }: +let + cfg = config.profile.hyprland; +in +{ + config = lib.mkIf cfg.enable { + home.file.".config/wlogout/icons" = { + source = ./wlogout-icons; + recursive = true; + }; + programs.wlogout = { + style = '' + /* ----------------------------------------------------- + * Import Pywal colors + * ----------------------------------------------------- */ + @import "${config.home.homeDirectory}/.cache/wallust/wlogout.css"; + + /* ----------------------------------------------------- + * General + * ----------------------------------------------------- */ + + * { + font-family: "Fira Sans Semibold", FontAwesome, Roboto, Helvetica, Arial, sans-serif; + background-image: none; + transition: 20ms; + box-shadow: none; + } + + window { + background: url("../../.cache/blurred_wallpaper.png"); + background-size: cover; + } + + button { + color: #ffffff; + font-size: 20px; + + background-repeat: no-repeat; + background-position: center; + background-size: 25%; + + border-style: solid; + background-color: rgba(12, 12, 12, 0.3); + border: 3px solid #ffffff; + + box-shadow: + 0 4px 8px 0 rgba(0, 0, 0, 0.2), + 0 6px 20px 0 rgba(0, 0, 0, 0.19); + } + + button:focus, + button:active, + button:hover { + color: @color11; + background-color: rgba(12, 12, 12, 0.5); + border: 3px solid @color11; + } + + /* + ----------------------------------------------------- + Buttons + ----------------------------------------------------- + */ + + #lock { + margin: 10px; + border-radius: 20px; + background-image: image(url("icons/lock.png")); + } + + #logout { + margin: 10px; + border-radius: 20px; + background-image: image(url("icons/logout.png")); + } + + #suspend { + margin: 10px; + border-radius: 20px; + background-image: image(url("icons/suspend.png")); + } + + #hibernate { + margin: 10px; + border-radius: 20px; + background-image: image(url("icons/hibernate.png")); + } + + #shutdown { + margin: 10px; + border-radius: 20px; + background-image: image(url("icons/shutdown.png")); + } + + #reboot { + margin: 10px; + border-radius: 20px; + background-image: image(url("icons/reboot.png")); + } + ''; + enable = true; + layout = [ + { + label = "lock"; + action = "hyprlock"; + text = "Lock"; + keybind = "l"; + } + { + label = "hibernate"; + action = "sleep 1; systemctl hibernate"; + text = "Hibernate"; + keybind = "h"; + } + { + label = "logout"; + action = "hyprctl dispatch exit"; + text = "Exit"; + keybind = "e"; + } + { + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + } + { + label = "suspend"; + action = "systemctl suspend"; + text = "Suspend"; + keybind = "u"; + } + { + label = "reboot"; + action = "systemctl reboot"; + text = "Reboot"; + keybind = "r"; + } + ]; + }; + }; +} diff --git a/home/modules/obs.nix b/home/modules/obs.nix new file mode 100644 index 0000000..2c2b5d6 --- /dev/null +++ b/home/modules/obs.nix @@ -0,0 +1,16 @@ +{ lib, config, pkgs, ... }: +let + cfg = config.profile.obs; +in +{ + config = lib.mkIf cfg.enable { + programs.obs-studio = { + enable = true; + plugins = with pkgs.obs-studio-plugins; [ + obs-vaapi + obs-pipewire-audio-capture + wlrobs + ]; + }; + }; +} diff --git a/home/modules/sway/default.nix b/home/modules/sway/default.nix new file mode 100644 index 0000000..8f17050 --- /dev/null +++ b/home/modules/sway/default.nix @@ -0,0 +1,10 @@ +{ ... }: +{ + imports = [ + ./mako.nix + ./sway.nix + ./swaylock.nix + ./swayosd.nix + ./waybar.nix + ]; +} diff --git a/home/modules/sway/mako.nix b/home/modules/sway/mako.nix new file mode 100644 index 0000000..a33dae7 --- /dev/null +++ b/home/modules/sway/mako.nix @@ -0,0 +1,18 @@ +{ lib, config, ... }: +with lib; +let + cfg = config.profile.sway; +in +{ + # Notification daemon for wayland + config = mkIf (cfg.enable && cfg.mako.enable) { + services.mako = { + enable = true; + padding = "5"; + backgroundColor = "#050505"; + borderSize = 1; + borderColor = "#454545"; + font = "JetBrainsMono Nerd Font 10"; + }; + }; +} diff --git a/home/modules/sway/sway.nix b/home/modules/sway/sway.nix new file mode 100644 index 0000000..ae1576b --- /dev/null +++ b/home/modules/sway/sway.nix @@ -0,0 +1,66 @@ +{ pkgs, lib, config, ... }: +let + cfg = config.profile.sway; +in +{ + config = lib.mkIf cfg.enable { + home.packages = with pkgs; [ + alacritty + tofi + findutils + networkmanagerapplet + ]; + + wayland.windowManager.sway = { + enable = true; + }; + + wayland.windowManager.sway.extraConfigEarly = '' + exec "nm-applet --indicator" + ''; + wayland.windowManager.sway.config = + let + mod = "Mod4"; + in + { + modifier = mod; + keybindings = lib.mkOptionDefault + { + "${mod}+Return" = "exec ${pkgs.alacritty}/bin/alacritty"; + "${mod}+Shift+q" = "kill"; + "${mod}+d" = "exec ${pkgs.tofi}/bin/tofi-drun | ${pkgs.findutils}/bin/xargs swaymsg exec --"; + "XF86AudioRaiseVolume" = "exec wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+"; + "XF86AudioLowerVolume" = "exec wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%-"; + "XF86AudioMute" = "exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + "XF86MonBrightnessUp" = "exec light -A 5"; + "XF86MonBrightnessDown" = "exec light -U 5"; + }; + + fonts = { + names = [ "JetBrainsMono Nerd Font" ]; + style = "Bold Semi-Condensed"; + size = 11.0; + }; + bars = [ ]; + }; + wayland.windowManager.sway.extraConfig = '' + default_border none + + # class border backgr. text indicator child_border + client.focused #373b41 #373b41 #373b41 #373b41 #373b41 + client.focused_inactive #282a2e #282a2e #282a2e #282a2e #282a2e + client.urgent #f0c674 #f0c674 #f0c674 #f0c674 #f0c674 + client.placeholder #373b41 #373b41 #373b41 #373b41 #373b41 + + # swayfx config + blur enable + blur_xray enable + blur_passes 3 + blur_radius 5 + layer_effects "waybar" shadows enable; blur enable; + corner_radius 4 + # default_dim_inactive 0.2 + shadows enable + ''; + }; +} diff --git a/home/modules/sway/swaylock.nix b/home/modules/sway/swaylock.nix new file mode 100644 index 0000000..a739178 --- /dev/null +++ b/home/modules/sway/swaylock.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: +with lib; +let + cfg = config.profile.sway; +in +{ + config = mkIf cfg.enable { + programs.swaylock = { + enable = true; + settings = { + show-failed-attempts = true; + }; + }; + }; +} diff --git a/home/modules/sway/swayosd.nix b/home/modules/sway/swayosd.nix new file mode 100644 index 0000000..80161fa --- /dev/null +++ b/home/modules/sway/swayosd.nix @@ -0,0 +1,12 @@ +{ config, lib, ... }: +with lib; +let + cfg = config.profile.sway; +in +{ + config = mkIf cfg.enable { + services.swayosd = { + enable = true; + }; + }; +} diff --git a/home/modules/sway/waybar.css b/home/modules/sway/waybar.css new file mode 100644 index 0000000..9a00113 --- /dev/null +++ b/home/modules/sway/waybar.css @@ -0,0 +1,90 @@ +* { + border: none; + border-radius: 0; + min-height: 0; + font-family: Iosevka nerd font; + font-weight: bold; + font-size: 14px; + padding: 0; +} + +window#waybar { + background: rgba(29, 31, 33, 0.75); + border-radius: 6px; + border: 2px solid #303030; +} + +#workspaces { + background-color: transparent; +} + +#workspaces button { + all: initial; /* Remove GTK theme values (waybar #1351) */ + min-width: 0; /* Fix weird spacing in materia (waybar #450) */ + box-shadow: inset 0 -3px transparent; /* Use box-shadow instead of border so the text isn't offset */ + padding: 6px 12px; + color: #6c757d; +} + +#workspaces button.visible { + color: #ede0d4; +} + +#workspaces button:hover { + box-shadow: inherit; + text-shadow: inherit; + color: #ede0d4; +} + +#workspaces button.urgent { + background-color: #ffcb70; +} + +#battery, +#backlight, +#network, +#clock, +#tray, +#pulseaudio { + margin: 8px; + padding-right: 16px; + background-color: transparent; + color: #ede0d4; +} + +#custom-swww { + padding-right: 16px; + background-color: transparent; + color: #ede0d4; +} + +#battery { + background-color: #ede0d4; +} +#battery.warning, +#battery.critical, +#battery.urgent { + color: #ede0d4; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} +#battery.charging { + background-color: #97a97c; +} + +@keyframes blink { + to { + background-color: #ffcb70; + color: #ede0d4; + } +} + +tooltip { + padding: 15px; + background-color: #050505; + border-radius: 6px; + border: 2px solid #303030; +} diff --git a/home/modules/sway/waybar.nix b/home/modules/sway/waybar.nix new file mode 100644 index 0000000..86f7a3a --- /dev/null +++ b/home/modules/sway/waybar.nix @@ -0,0 +1,103 @@ +{ config, lib, unstable, ... }: +let + cfg = config.profile.sway; +in +{ + config = lib.mkIf cfg.enable { + programs.waybar = { + enable = true; + style = ./waybar.css; + systemd.enable = true; + package = unstable.waybar; + }; + + programs.waybar.settings = { + main = { + layer = "top"; + position = "bottom"; + spacing = 0; + margin-bottom = 0; + margin-left = 300; + margin-right = 300; + modules-left = [ + "sway/workspaces" + ]; + modules-center = [ + "clock" + ]; + modules-right = [ + "tray" + "network" + "battery" + "pulseaudio" + ]; + + "sway/taskbar" = { + format = "{icon}"; + on-click = "activate"; + on-click-right = "fullscreen"; + icon-size = 25; + tooltip-format = "{title}"; + }; + + "sway/workspaces" = { + disable-scroll = true; + all-outputs = true; + format-icons = { + "1" = ""; + "2" = ""; + "3" = ""; + "4" = ""; + "5" = ""; + }; + persistent-workspaces = { + "1" = [ ]; + "2" = [ ]; + "3" = [ ]; + "4" = [ ]; + "5" = [ ]; + }; + }; + + tray.spacing = 10; + clock.format = "{:%I:%M %p - %a, %d %b %Y}"; + network = { + format-wifi = "{icon}"; + format-icons = [ "󰤯" "󰤟" "󰤢" "󰤥" "󰤨" ]; + format-ethernet = ""; + format-disconnected = "󰤮"; + interval = 5; + }; + + pulseaudio = { + scroll-step = 5; + max-volume = 150; + format = "{icon} {volume}%"; + format-bluetooth = "󰂰"; + nospacing = 1; + format-muted = "󰝟"; + format-icons = { + headphone = ""; + default = [ "" "" " " ]; + }; + on-click = "pamixer -t"; + }; + + battery = { + format = "{icon} {capacity}%"; + format-icons = { + charging = [ "󰢜" "󰂆" "󰂇" "󰂈" "󰢝" "󰂉" "󰢞" "󰂊" "󰂋" "󰂅" ]; + default = [ "󰁺" "󰁻" "󰁼" "󰁽" "󰁾" "󰁿" "󰂀" "󰂁" "󰂂" "󰁹" ]; + }; + format-full = "Charged "; + interval = 5; + states = { + warning = 20; + critical = 10; + }; + tooltip = false; + }; + }; + }; + }; +} diff --git a/home/modules/syncthing.nix b/home/modules/syncthing.nix new file mode 100644 index 0000000..728c4ab --- /dev/null +++ b/home/modules/syncthing.nix @@ -0,0 +1,12 @@ +{ lib, config, ... }: +let + cfg = config.profile.syncthing; +in +{ + config = lib.mkIf cfg.enable { + services.syncthing = { + enable = true; + tray.enable = false; + }; + }; +} diff --git a/home/tigor/config/ideavim/.ideavimrc b/home/tigor/config/ideavim/.ideavimrc new file mode 100644 index 0000000..686b5ff --- /dev/null +++ b/home/tigor/config/ideavim/.ideavimrc @@ -0,0 +1,31 @@ +set nrformats-=octal +set incsearch +set scrolloff=5 +set sidescrolloff=5 +set history=1000 + +set clipboard^=unnamedplus,unnamed +set hlsearch +set ignorecase +set smartcase +set visualbell + +set showmode +set number relativenumber + +" change leader key to space +nmap +let mapleader = " " + +" Smart join for +set ideajoin +" Map vim marks to IDEA global marks +set ideamarks + +" Mappings +nmap gd (GotoTypeDeclaration) +nmap gi (GotoImplementation) +nmap (RenameElement) +nmap K (ShowHoverInfo) + +nmap db (ToggleLineBreakpoint) diff --git a/home/tigor/config/ideavim/default.nix b/home/tigor/config/ideavim/default.nix new file mode 100644 index 0000000..19eefd7 --- /dev/null +++ b/home/tigor/config/ideavim/default.nix @@ -0,0 +1,5 @@ +{ + home.file.".ideavimrc" = { + source = ./.ideavimrc; + }; +} diff --git a/home/tigor/config/kitty/default.nix b/home/tigor/config/kitty/default.nix new file mode 100644 index 0000000..2b088a0 --- /dev/null +++ b/home/tigor/config/kitty/default.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + programs.kitty.enable = true; + + home.file.".config/kitty" = { + source = ./.; + recursive = true; + }; +} diff --git a/home/tigor/config/kitty/kitty.conf b/home/tigor/config/kitty/kitty.conf new file mode 100644 index 0000000..5204942 --- /dev/null +++ b/home/tigor/config/kitty/kitty.conf @@ -0,0 +1 @@ +globinclude kitty.d/**/*.conf diff --git a/home/tigor/config/kitty/kitty.d/00-base.conf b/home/tigor/config/kitty/kitty.d/00-base.conf new file mode 100644 index 0000000..f6494e9 --- /dev/null +++ b/home/tigor/config/kitty/kitty.d/00-base.conf @@ -0,0 +1,2 @@ +underline_hyperlinks always +enable_audio_bell no diff --git a/home/tigor/config/kitty/kitty.d/01-fonts.conf b/home/tigor/config/kitty/kitty.d/01-fonts.conf new file mode 100644 index 0000000..68e2c12 --- /dev/null +++ b/home/tigor/config/kitty/kitty.d/01-fonts.conf @@ -0,0 +1,2 @@ +font_family JetBrainsMono Nerd Font Mono + diff --git a/home/tigor/config/kitty/kitty.d/10-layout.conf b/home/tigor/config/kitty/kitty.d/10-layout.conf new file mode 100644 index 0000000..cadfea7 --- /dev/null +++ b/home/tigor/config/kitty/kitty.d/10-layout.conf @@ -0,0 +1,16 @@ +# enabled_layouts tall:bias=80;full_size=1;mirrored=false,fat:bias=75;full_size=1;mirrored=false,splits + +# map ctrl+a>enter launch --location=hsplit --cwd=current +# map ctrl+a>backspace launch --location=vsplit --cwd=current +# +# map ctrl+a>h neighboring_window left +# map ctrl+a>j neighboring_window down +# map ctrl+a>k neighboring_window up +# map ctrl+a>l neighboring_window right +# +# map ctrl+a>shift+k move_window up +# map ctrl+a>shift+j move_window down +# map ctrl+a>shift+h move_window left +# map ctrl+a>shift+l move_window right +# +# map ctrl+a>t new_tab_with_cwd diff --git a/home/tigor/config/kitty/kitty.d/20-window.conf b/home/tigor/config/kitty/kitty.d/20-window.conf new file mode 100644 index 0000000..834c1f7 --- /dev/null +++ b/home/tigor/config/kitty/kitty.d/20-window.conf @@ -0,0 +1,3 @@ +tab_bar_edge top +tab_bar_margin_width 0.2 +tab_bar_style slant diff --git a/home/tigor/config/kitty/kitty.d/30-transparency.conf b/home/tigor/config/kitty/kitty.d/30-transparency.conf new file mode 100644 index 0000000..72f3ee6 --- /dev/null +++ b/home/tigor/config/kitty/kitty.d/30-transparency.conf @@ -0,0 +1,3 @@ +background_blur 40 +background_opacity 0.90 +# background_tint 0.5 diff --git a/home/tigor/config/nvim/.gitignore b/home/tigor/config/nvim/.gitignore new file mode 100644 index 0000000..eac713a --- /dev/null +++ b/home/tigor/config/nvim/.gitignore @@ -0,0 +1,12 @@ +tt.* +.tests +doc/tags +debug +.repro +foo.* +*.log +data +lazy-lock.json +lazyvim.json + +.luarc.json diff --git a/home/tigor/config/nvim/.neoconf.json b/home/tigor/config/nvim/.neoconf.json new file mode 100644 index 0000000..7c48087 --- /dev/null +++ b/home/tigor/config/nvim/.neoconf.json @@ -0,0 +1,15 @@ +{ + "neodev": { + "library": { + "enabled": true, + "plugins": true + } + }, + "neoconf": { + "plugins": { + "lua_ls": { + "enabled": true + } + } + } +} diff --git a/home/tigor/config/nvim/LICENSE b/home/tigor/config/nvim/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/home/tigor/config/nvim/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/home/tigor/config/nvim/README.md b/home/tigor/config/nvim/README.md new file mode 100644 index 0000000..185280b --- /dev/null +++ b/home/tigor/config/nvim/README.md @@ -0,0 +1,4 @@ +# 💤 LazyVim + +A starter template for [LazyVim](https://github.com/LazyVim/LazyVim). +Refer to the [documentation](https://lazyvim.github.io/installation) to get started. diff --git a/home/tigor/config/nvim/default.nix b/home/tigor/config/nvim/default.nix new file mode 100644 index 0000000..c8090b0 --- /dev/null +++ b/home/tigor/config/nvim/default.nix @@ -0,0 +1,24 @@ +{ pkgs, unstable, ... }: + +{ + home.file.".config/nvim" = { + source = ./.; + recursive = true; + }; + + home.packages = with pkgs; [ + docker-compose-language-service + emmet-ls + # golangci-lint-langserver + mongodb-compass + silicon # For code screenshots + + ###### Golang development tools ###### + gomodifytags + gotests + iferr + curl + + unstable.lua-language-server + ]; +} diff --git a/home/tigor/config/nvim/init.lua b/home/tigor/config/nvim/init.lua new file mode 100644 index 0000000..08cbdbb --- /dev/null +++ b/home/tigor/config/nvim/init.lua @@ -0,0 +1,2 @@ +-- bootstrap lazy.nvim, LazyVim and your plugins +require "config.lazy" diff --git a/home/tigor/config/nvim/lua/config/autocmds.lua b/home/tigor/config/nvim/lua/config/autocmds.lua new file mode 100644 index 0000000..af95f49 --- /dev/null +++ b/home/tigor/config/nvim/lua/config/autocmds.lua @@ -0,0 +1,27 @@ +-- Autocmds are automatically loaded on the VeryLazy event +-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua +-- Add any additional autocmds here + +local opt = vim.opt + +opt.shiftwidth = 4 +opt.tabstop = 4 + +-- vim.api.nvim_create_autocmd("BufReadPost", { +-- group = vim.api.nvim_create_augroup("LazyVim_AutoUpdate", {}), +-- once = true, +-- callback = function() +-- require("lazy").update { +-- show = false, +-- wait = false, +-- concurrency = 4, +-- } +-- end, +-- }) + +-- Golang templ filetype +vim.filetype.add { + extension = { + templ = "templ", + }, +} diff --git a/home/tigor/config/nvim/lua/config/keymaps.lua b/home/tigor/config/nvim/lua/config/keymaps.lua new file mode 100644 index 0000000..e4b6322 --- /dev/null +++ b/home/tigor/config/nvim/lua/config/keymaps.lua @@ -0,0 +1,11 @@ +-- Keymaps are automatically loaded on the VeryLazy event +-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua +-- Add any additional keymaps here + +require "config.neovide" + +vim.keymap.set("t", "", "", { silent = true, desc = "Exit Terminal Mode" }) + +-- LazyVim hardcode tabs to jump snippet completions. Very fucking annoying. +vim.keymap.del({ "i" }, "") +vim.keymap.del({ "i" }, "") diff --git a/home/tigor/config/nvim/lua/config/lazy.lua b/home/tigor/config/nvim/lua/config/lazy.lua new file mode 100644 index 0000000..7aac0a0 --- /dev/null +++ b/home/tigor/config/nvim/lua/config/lazy.lua @@ -0,0 +1,65 @@ +local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + -- bootstrap lazy.nvim + -- stylua: ignore + vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath }) +end +vim.opt.rtp:prepend(vim.env.LAZY or lazypath) + +require("lazy").setup { + spec = { + -- add LazyVim and import its plugins + { "LazyVim/LazyVim", import = "lazyvim.plugins" }, + -- import any extras modules here + { import = "lazyvim.plugins.extras.lang.typescript" }, + { import = "lazyvim.plugins.extras.lang.json" }, + { import = "lazyvim.plugins.extras.coding.copilot" }, + { import = "lazyvim.plugins.extras.coding.yanky" }, + { import = "lazyvim.plugins.extras.coding.luasnip" }, + { import = "lazyvim.plugins.extras.formatting.prettier" }, + + { import = "lazyvim.plugins.extras.dap.core" }, + { import = "lazyvim.plugins.extras.dap.nlua" }, + { import = "lazyvim.plugins.extras.test.core" }, + { import = "lazyvim.plugins.extras.lang.docker" }, + { import = "lazyvim.plugins.extras.lang.go" }, + { import = "lazyvim.plugins.extras.lang.json" }, + -- { import = "lazyvim.plugins.extras.lang.markdown" }, + { import = "lazyvim.plugins.extras.lang.tailwind" }, + { import = "lazyvim.plugins.extras.lang.typescript" }, + { import = "lazyvim.plugins.extras.lang.yaml" }, + { import = "lazyvim.plugins.extras.lsp.none-ls" }, + { import = "lazyvim.plugins.extras.lang.java" }, + { import = "lazyvim.plugins.extras.util.project" }, + { import = "lazyvim.plugins.extras.editor.mini-files" }, + -- { import = "lazyvim.plugins.extras.ui.edgy" }, + -- import/override with your plugins + { import = "plugins" }, + }, + defaults = { + -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. + -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. + lazy = false, + -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, + -- have outdated releases, which may break your Neovim install. + version = false, -- always use the latest git commit + -- version = "*", -- try installing the latest stable version for plugins that support semver + }, + install = { colorscheme = { "tokyonight", "habamax" } }, + checker = { enabled = false }, -- automatically check for plugin updates + performance = { + rtp = { + -- disable some rtp plugins + disabled_plugins = { + "gzip", + -- "matchit", + -- "matchparen", + -- "netrwPlugin", + "tarPlugin", + "tohtml", + "tutor", + "zipPlugin", + }, + }, + }, +} diff --git a/home/tigor/config/nvim/lua/config/neovide.lua b/home/tigor/config/nvim/lua/config/neovide.lua new file mode 100644 index 0000000..e08f30f --- /dev/null +++ b/home/tigor/config/nvim/lua/config/neovide.lua @@ -0,0 +1,21 @@ +if not vim.g.neovide then + return +end + +local font = "JetBrainsMono Nerd Font Mono" + +local font_size = vim.o.lines < 60 and 11 or 12 + +vim.o.guifont = font .. ":h" .. font_size + +vim.keymap.set("n", "", function() + font_size = font_size - 1 + vim.o.guifont = font .. ":h" .. font_size + vim.notify("Font Set: " .. font .. ":h" .. font_size) +end, { desc = "Decrease font size" }) + +vim.keymap.set("n", "", function() + font_size = font_size + 1 + vim.o.guifont = font .. ":h" .. font_size + vim.notify("Font Set: " .. font .. ":h" .. font_size) +end, { desc = "Increase font size" }) diff --git a/home/tigor/config/nvim/lua/config/options.lua b/home/tigor/config/nvim/lua/config/options.lua new file mode 100644 index 0000000..a0c827f --- /dev/null +++ b/home/tigor/config/nvim/lua/config/options.lua @@ -0,0 +1,10 @@ +-- Options are automatically loaded before lazy.nvim startup +-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua +-- Add any additional options here + +-- Disable swap files +vim.opt.swapfile = false + +vim.defer_fn(function() + vim.opt.title = true +end, 100) diff --git a/home/tigor/config/nvim/lua/plugins/arrow.lua b/home/tigor/config/nvim/lua/plugins/arrow.lua new file mode 100644 index 0000000..2d19830 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/arrow.lua @@ -0,0 +1,10 @@ +return { + "otavioschwanck/arrow.nvim", + opts = { + show_icons = true, + leader_key = [[\]], -- Recommended to be a single key + }, + keys = { + { "", desc = "Open Arrow bookmarks" }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/base16.lua b/home/tigor/config/nvim/lua/plugins/base16.lua new file mode 100644 index 0000000..566db61 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/base16.lua @@ -0,0 +1,70 @@ +return { + { + "rktjmp/fwatch.nvim", + dependencies = { + "xiyaowong/transparent.nvim", -- For Transparency support + { "echasnovski/mini.nvim", version = false }, + }, + lazy = false, + config = function() + local fwatch = require "fwatch" + + local color_file = vim.fn.getenv "HOME" .. "/.cache/wallust/base16-nvim.lua" + local error_fn = function(err) + vim.notify("Watch Error: " .. err, vim.log.levels.ERROR, { title = "fwatch.nvim" }) + end + local command = {} + local source_fn = function(_, _, unwatch) + vim.schedule(function() + if vim.fn.filereadable(color_file) == 1 then + vim.cmd(("source %s"):format(color_file)) + if not vim.g.neovide then + require("transparent").setup { + groups = { + "Normal", + "NormalNC", + "Comment", + "Constant", + "Special", + "Identifier", + "Statement", + "PreProc", + "Type", + "Underlined", + "Todo", + "String", + "Function", + "Conditional", + "Repeat", + "Operator", + "Structure", + "LineNr", + "NonText", + "SignColumn", + -- "CursorLine", + -- "CursorLineNr", + "StatusLine", + "StatusLineNC", + "EndOfBuffer", + }, + } + end + if unwatch then + unwatch() + end + fwatch.watch(color_file, command) + end + end) + end + command.on_event = source_fn + command.on_error = error_fn + source_fn() + fwatch.watch(color_file, command) + end, + }, + { + "brenoprata10/nvim-highlight-colors", + opts = {}, + event = "VeryLazy", + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/before.lua b/home/tigor/config/nvim/lua/plugins/before.lua new file mode 100644 index 0000000..206524b --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/before.lua @@ -0,0 +1,9 @@ +return { + "bloznelis/before.nvim", + opts = {}, + event = { "InsertEnter" }, + keys = { + { "", "lua require'before'.jump_to_last_edit()", desc = "Jump to last edit" }, + { "", "lua require'before'.jump_to_next_edit()", desc = "Jump to next edit" }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/caddyfile.lua b/home/tigor/config/nvim/lua/plugins/caddyfile.lua new file mode 100644 index 0000000..0f71ab9 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/caddyfile.lua @@ -0,0 +1,4 @@ +return { + "isobit/vim-caddyfile", + event = { "BufReadPre", "BufNewFile" }, +} diff --git a/home/tigor/config/nvim/lua/plugins/catppuccin.lua b/home/tigor/config/nvim/lua/plugins/catppuccin.lua new file mode 100644 index 0000000..f489ccb --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/catppuccin.lua @@ -0,0 +1,18 @@ +return { + { + "catppuccin/nvim", + name = "catppuccin", + opts = { + styles = { + functions = { "italic" }, + keywords = { "italic" }, + }, + }, + }, + -- { + -- "LazyVim/LazyVim", + -- opts = { + -- colorscheme = "catppuccin", + -- }, + -- }, +} diff --git a/home/tigor/config/nvim/lua/plugins/cmp.lua b/home/tigor/config/nvim/lua/plugins/cmp.lua new file mode 100644 index 0000000..49ae531 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/cmp.lua @@ -0,0 +1,62 @@ +return { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-cmdline", + "hrsh7th/cmp-nvim-lsp-document-symbol", + -- "hrsh7th/cmp-nvim-lsp-signature-help", + { "lukas-reineke/cmp-rg", enabled = vim.fn.exepath "rg" ~= "" }, + }, + event = { "InsertEnter", "CmdlineEnter" }, + opts = function(_, opts) + local cmp = require "cmp" + + if vim.fn.exepath "rg" ~= "" then + table.insert(opts.sources, 3, { name = "rg" }) + end + + opts.preselect = cmp.PreselectMode.None + + opts.mapping = cmp.mapping.preset.insert { + [""] = function(fallback) + cmp.abort() + fallback() + end, + [""] = cmp.mapping.confirm { select = true }, + [""] = cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Insert }, + [""] = cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Insert }, + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }, -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. + } + + ---@diagnostic disable-next-line: missing-fields + cmp.setup.cmdline(":", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources { + { name = "path" }, + { + name = "cmdline", + option = { + ignore_cmds = { "Man", "!" }, + }, + }, + }, + }) + + ---@diagnostic disable-next-line: missing-fields + cmp.setup.cmdline("/", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources { + { name = "nvim_lsp_document_symbol" }, + { name = "buffer" }, + }, + }) + + return opts + end, +} diff --git a/home/tigor/config/nvim/lua/plugins/conform.lua b/home/tigor/config/nvim/lua/plugins/conform.lua new file mode 100644 index 0000000..5858a1b --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/conform.lua @@ -0,0 +1,9 @@ +return { + "conform.nvim", + opts = { + formatters_by_ft = { + nix = { "nixpkgs_fmt" }, + templ = { "templ" }, + }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/copilot.lua b/home/tigor/config/nvim/lua/plugins/copilot.lua new file mode 100644 index 0000000..8234922 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/copilot.lua @@ -0,0 +1,28 @@ +return { + { + "zbirenbaum/copilot.lua", + event = { "InsertEnter" }, + opts = { + panel = { enabled = false }, + suggestion = { + enabled = true, + auto_trigger = true, + keymap = { + accept = "", + accept_word = false, + accept_line = false, + next = "", + prev = "", + dismiss = "", + }, + }, + filetypes = { + ["*"] = true, + }, + }, + }, + { + "zbirenbaum/copilot-cmp", + enabled = false, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/corn.lua b/home/tigor/config/nvim/lua/plugins/corn.lua new file mode 100644 index 0000000..9f46ae3 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/corn.lua @@ -0,0 +1,21 @@ +return { + "RaafatTurki/corn.nvim", + event = { "LspAttach" }, + opts = { + border_style = "rounded", + icons = { + error = " ", + warn = " ", + hint = " ", + info = " ", + }, + item_preprocess_func = function(item) + return item + end, + }, + config = function(_, opts) + vim.diagnostic.config { virtual_text = false } + require("corn").setup(opts) + end, + enabled = false, +} diff --git a/home/tigor/config/nvim/lua/plugins/diagflow.lua b/home/tigor/config/nvim/lua/plugins/diagflow.lua new file mode 100644 index 0000000..d751e5a --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/diagflow.lua @@ -0,0 +1,18 @@ +return { + "dgagn/diagflow.nvim", + event = { "LspAttach" }, + opts = { + scope = "line", + show_sign = false, + show_borders = true, + text_align = "right", + max_width = 60, + format = function(diagnostic) + if diagnostic.source and #diagnostic.source > 0 then + return string.format("[%s] %s: %s", diagnostic.source, diagnostic.code, diagnostic.message) + end + return diagnostic.message + end, + }, + -- enabled = false, +} diff --git a/home/tigor/config/nvim/lua/plugins/discord-presence.lua b/home/tigor/config/nvim/lua/plugins/discord-presence.lua new file mode 100644 index 0000000..d9c766e --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/discord-presence.lua @@ -0,0 +1,5 @@ +return { + "andweeb/presence.nvim", + event = "BufReadPost", + config = true, +} diff --git a/home/tigor/config/nvim/lua/plugins/gitsigns.lua b/home/tigor/config/nvim/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..655de4f --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/gitsigns.lua @@ -0,0 +1,6 @@ +return { + "lewis6991/gitsigns.nvim", + opts = { + current_line_blame = true, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/incline.lua b/home/tigor/config/nvim/lua/plugins/incline.lua new file mode 100644 index 0000000..ba19cd7 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/incline.lua @@ -0,0 +1,28 @@ +return { + -- Show filenames in the right top most of buffer + "b0o/incline.nvim", + config = function() + local helpers = require "incline.helpers" + local devicons = require "nvim-web-devicons" + require("incline").setup { + window = { + padding = 0, + margin = { horizontal = 0 }, + }, + render = function(props) + local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ":t") + local ft_icon, ft_color = devicons.get_icon_color(filename) + local modified = vim.bo[props.buf].modified + return { + ft_icon and { " ", ft_icon, " ", guibg = ft_color, guifg = helpers.contrast_color(ft_color) } or "", + " ", + { filename, gui = modified and "bold,italic" or "bold" }, + " ", + guibg = "#44406e", + } + end, + } + end, + -- Optional: Lazy load Incline + event = "VeryLazy", +} diff --git a/home/tigor/config/nvim/lua/plugins/java.lua b/home/tigor/config/nvim/lua/plugins/java.lua new file mode 100644 index 0000000..a1510a0 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/java.lua @@ -0,0 +1,40 @@ +return { + { + "conform.nvim", + opts = function(_, opts) + opts.formatters_by_ft = opts.formatters_by_ft or {} + opts.formatters_by_ft.xml = { "xmlformat" } + + require("conform").formatters.xmlformat = { + prepend_args = { "--indent", "1", "--indent-char", "\t" }, + } + end, + }, + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "xmlformatter" }) + end, + }, + { + -- Add lombok support + "mfussenegger/nvim-jdtls", + opts = function(_, opts) + local lombok_jar_path = (vim.fn.expand "$MASON") .. "/packages/jdtls/lombok.jar" + opts.cmd = { + vim.fn.exepath "jdtls", + ([[--jvm-arg=-javaagent:%s]]):format(lombok_jar_path), + } + end, + }, + { "rcasia/neotest-java", lazy = true }, + { + "nvim-neotest/neotest", + opts = function(_, opts) + opts = opts or {} + opts.adapters = opts.adapters or {} + vim.list_extend(opts.adapters, { "neotest-java" }) + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/lang-go.lua b/home/tigor/config/nvim/lua/plugins/lang-go.lua new file mode 100644 index 0000000..5e31068 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/lang-go.lua @@ -0,0 +1,108 @@ +return { + { + "neovim/nvim-lspconfig", + opts = { + servers = { + gopls = { + settings = { + gopls = { + analyses = { + fieldalignment = false, + }, + usePlaceholders = false, + hints = { + assignVariableTypes = false, + compositeLiteralFields = false, + compositeLiteralTypes = false, + constantValues = false, + functionTypeParameters = false, + parameterNames = false, + rangeVariableTypes = false, + }, + }, + }, + }, + }, + setup = { + gopls = function(_, opts) + require("lazyvim.util").lsp.on_attach(function(client, bufnr) + if client.name == "gopls" then + -- workaround for gopls not supporting semanticTokensProvider + -- https://github.com/golang/go/issues/54531#issuecomment-1464982242 + if not client.server_capabilities.semanticTokensProvider then + local semantic = client.config.capabilities.textDocument.semanticTokens + client.server_capabilities.semanticTokensProvider = { + full = true, + legend = { + tokenTypes = semantic.tokenTypes, + tokenModifiers = semantic.tokenModifiers, + }, + range = true, + } + end + -- end workaround + + -- run lsp imports code action on save. + vim.api.nvim_create_autocmd("BufWritePre", { + desc = "Auto format and organize imports on save (gopls)", + group = vim.api.nvim_create_augroup("GoplsAutoFormat", {}), + buffer = bufnr, + callback = function(event) + local context = { source = { organizeImports = true } } + local params = vim.lsp.util.make_range_params() + params.context = context + local result = + vim.lsp.buf_request_sync(event.buf, "textDocument/codeAction", params, 3000) + if not result then + return + end + if not result[1] then + return + end + result = result[1].result + if not result then + return + end + if not result[1] then + return + end + local edit = result[1].edit + if not edit then + return + end + vim.lsp.util.apply_workspace_edit(edit, "utf-8") + end, + }) + end + end) + end, + }, + }, + }, + { + "olexsmir/gopher.nvim", + ft = "go", + }, + { + "edolphin-ydf/goimpl.nvim", + ft = "go", + config = function() + require("telescope").load_extension "goimpl" + vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("GoImpl", {}), + callback = function(ctx) + local client = vim.lsp.get_client_by_id(ctx.data.client_id) or {} + if client.name == "gopls" then + vim.api.nvim_create_user_command("Impl", [[Telescope goimpl]], {}) + vim.keymap.set( + "n", + "ci", + [[Telescope goimpl]], + { buffer = ctx.buf, desc = "Generate implementation stub" } + ) + end + end, + }) + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/lazygit.lua b/home/tigor/config/nvim/lua/plugins/lazygit.lua new file mode 100644 index 0000000..6c93d2c --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/lazygit.lua @@ -0,0 +1,11 @@ +return { + "kdheepak/lazygit.nvim", + -- optional for floating window border decoration + dependencies = { + "nvim-lua/plenary.nvim", + }, + enabled = vim.fn.exepath("lazygit") ~= "", + keys = { + { "z", "LazyGit", desc = "Symbols Outline" }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/lsp-html.lua b/home/tigor/config/nvim/lua/plugins/lsp-html.lua new file mode 100644 index 0000000..77a5f36 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/lsp-html.lua @@ -0,0 +1,9 @@ +return { + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "html-lsp" }) + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/lsp-lazy.lua b/home/tigor/config/nvim/lua/plugins/lsp-lazy.lua new file mode 100644 index 0000000..9c85bb6 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/lsp-lazy.lua @@ -0,0 +1,8 @@ +return { + "dundalek/lazy-lsp.nvim", + dependencies = { "neovim/nvim-lspconfig" }, + opts = { + excluded_servers = { "jdtls", "gopls", "tsserver" }, + }, + enabled = false, +} diff --git a/home/tigor/config/nvim/lua/plugins/lspconfig.lua b/home/tigor/config/nvim/lua/plugins/lspconfig.lua new file mode 100644 index 0000000..f02af8c --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/lspconfig.lua @@ -0,0 +1,61 @@ +return { + "nvim-lspconfig", + init = function() + local keys = require("lazyvim.plugins.lsp.keymaps").get() + keys[#keys + 1] = { + "gD", + "lua require('telescope.builtin').lsp_definitions({ jump_type = 'vsplit' })", + desc = "Jump to definitions in vsplit", + } + keys[#keys + 1] = { + "grr", + "Trouble lsp_references focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "gri", + "Trouble lsp_implementations focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "grt", + "Trouble lsp_type_definitions focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "grs", + "Trouble lsp_document_symbols focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "", + vim.lsp.buf.rename, + desc = "Rename Symbol", + } + keys[#keys + 1] = { + "", + false, + mode = { "i" }, + } + keys[#keys + 1] = { + "gr", + false, + } + end, + opts = { + servers = { + templ = { + on_attach = function(client, _) + client.server_capabilities.documentFormattingProvider = false + client.server_capabilities.documentRangeFormattingProvider = false + end, + }, + html = { + on_attach = function(client, _) + client.server_capabilities.documentFormattingProvider = false + client.server_capabilities.documentRangeFormattingProvider = false + end, + }, + }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/luasnip.lua b/home/tigor/config/nvim/lua/plugins/luasnip.lua new file mode 100644 index 0000000..b0c3d42 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/luasnip.lua @@ -0,0 +1,7 @@ +return { + "L3MON4D3/LuaSnip", + opts = function(_, opts) + require "snippets" + return opts + end, +} diff --git a/home/tigor/config/nvim/lua/plugins/makefile.lua b/home/tigor/config/nvim/lua/plugins/makefile.lua new file mode 100644 index 0000000..4cdcd35 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/makefile.lua @@ -0,0 +1,14 @@ +return { + "sopa0/telescope-makefile", + dependencies = { + "akinsho/toggleterm.nvim", + }, + cmd = { "Make" }, + keys = { + { "m", "Telescope make", { desc = "Launch Make Items" } }, + }, + config = function() + require("telescope").load_extension "make" + vim.api.nvim_create_user_command("Make", [[Telescope make]], {}) + end, +} diff --git a/home/tigor/config/nvim/lua/plugins/mason.lua b/home/tigor/config/nvim/lua/plugins/mason.lua new file mode 100644 index 0000000..5f53c0d --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/mason.lua @@ -0,0 +1,7 @@ +return { + "mason.nvim", + opts = { + -- NixOS packages should override Mason packages if exist + PATH = vim.loop.os_uname().version:find("NixOS") and "append" or "prepend", + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/mini_files.lua b/home/tigor/config/nvim/lua/plugins/mini_files.lua new file mode 100644 index 0000000..d1c2d07 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/mini_files.lua @@ -0,0 +1,55 @@ +return { + "echasnovski/mini.nvim", + version = false, + opts = { + windows = { + preview = true, + width_preview = 50, + }, + }, + config = function(_, opts) + require("mini.files").setup(opts) + local map_split = function(buf_id, lhs, direction) + local mf = require "mini.files" + local rhs = function() + -- Make new window and set it as target + local new_target_window + vim.api.nvim_win_call(mf.get_target_window(), function() + vim.cmd(direction .. " split") + new_target_window = vim.api.nvim_get_current_win() + end) + + mf.set_target_window(new_target_window) + end + + -- Adding `desc` will result into `show_help` entries + local desc = "Split " .. direction + vim.keymap.set("n", lhs, rhs, { buffer = buf_id, desc = desc }) + end + vim.api.nvim_create_autocmd("User", { + pattern = "MiniFilesBufferCreate", + callback = function(args) + local mf = require "mini.files" + local buf_id = args.data.buf_id + -- Tweak keys to your liking + map_split(buf_id, "gs", "belowright horizontal") + map_split(buf_id, "gv", "belowright vertical") + vim.keymap.set("n", "", function() + mf.go_in { close_on_file = true } + end, { buffer = buf_id, desc = "Open file or directory" }) + end, + }) + end, + keys = { + { + "-", + function() + local mf = require "mini.files" + if not mf.close() then + mf.open(vim.api.nvim_buf_get_name(0), false) + end + end, + desc = "Open/Close mini files from current file directory", + }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/neotree.lua b/home/tigor/config/nvim/lua/plugins/neotree.lua new file mode 100644 index 0000000..1de96e1 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/neotree.lua @@ -0,0 +1,12 @@ +return { + "nvim-neo-tree/neo-tree.nvim", + opts = { + filesystem = { + filtered_items = { + visible = true, + }, + group_empty_dirs = true, + }, + }, + enabled = true, +} diff --git a/home/tigor/config/nvim/lua/plugins/nix.lua b/home/tigor/config/nvim/lua/plugins/nix.lua new file mode 100644 index 0000000..a3f54b5 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/nix.lua @@ -0,0 +1,9 @@ +return { + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "nixpkgs-fmt", "nil" }) + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/notifier.lua b/home/tigor/config/nvim/lua/plugins/notifier.lua new file mode 100644 index 0000000..8bcb51b --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/notifier.lua @@ -0,0 +1,9 @@ +return { + { "rcarriga/nvim-notify", enabled = false }, + { + "folke/noice.nvim", + dependencies = { + "vigoux/notifier.nvim", + }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/obsidian.lua b/home/tigor/config/nvim/lua/plugins/obsidian.lua new file mode 100644 index 0000000..bccdd58 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/obsidian.lua @@ -0,0 +1,53 @@ +local function workspace(name) + return { + name = name, + path = ("%s/Obsidian/%s"):format(vim.env.HOME, name), + } +end + +local function event(name) + return ("%s %s/Obsidian/**.md"):format(name, vim.env.HOME) +end + +return { + "epwalsh/obsidian.nvim", + cmd = { + "ObsidianOpen", + "ObsidianNew", + "ObsidianToday", + "ObsidianYesterday", + "ObsidianWorkspace", + "ObsidianSearch", + "ObsidianQuickSwitch", + }, + dependencies = { + -- Required. + "nvim-lua/plenary.nvim", + + -- see below for full list of optional dependencies 👇 + }, + event = { + event "BufReadPre", + event "BufNewFile", + }, + opts = { + workspaces = { + workspace "personal", + workspace "work", + workspace "stories", + workspace "tigor", + }, + mappings = {}, + }, + config = function(_, opts) + require("obsidian").setup(opts) + + vim.keymap.set("n", "gf", function() + if require("obsidian").util.cursor_on_markdown_link() then + return "ObsidianFollowLink" + else + return "gf" + end + end, { noremap = false, expr = true, desc = "Obsidian Follow Link or Fallback" }) + end, +} diff --git a/home/tigor/config/nvim/lua/plugins/oil.lua b/home/tigor/config/nvim/lua/plugins/oil.lua new file mode 100644 index 0000000..e0a449b --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/oil.lua @@ -0,0 +1,15 @@ +return { + "stevearc/oil.nvim", + opts = { + keymaps = { + ["q"] = "actions.close", + [""] = "actions.parent", + }, + }, + dependencies = { "nvim-tree/nvim-web-devicons" }, + cmd = { "Oil" }, + keys = { + { "-", "Oil", desc = "Open Oil" }, + }, + enabled = false, +} diff --git a/home/tigor/config/nvim/lua/plugins/precognition.lua b/home/tigor/config/nvim/lua/plugins/precognition.lua new file mode 100644 index 0000000..09633c6 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/precognition.lua @@ -0,0 +1,27 @@ +return { + "tris203/precognition.nvim", + event = "VeryLazy", + opts = { + -- startVisible = true, + -- showBlankVirtLine = true, + -- highlightColor = { link = "Comment" }, + -- hints = { + -- Caret = { text = "^", prio = 2 }, + -- Dollar = { text = "$", prio = 1 }, + -- MatchingPair = { text = "%", prio = 5 }, + -- Zero = { text = "0", prio = 1 }, + -- w = { text = "w", prio = 10 }, + -- b = { text = "b", prio = 9 }, + -- e = { text = "e", prio = 8 }, + -- W = { text = "W", prio = 7 }, + -- B = { text = "B", prio = 6 }, + -- E = { text = "E", prio = 5 }, + -- }, + -- gutterHints = { + -- G = { text = "G", prio = 10 }, + -- gg = { text = "gg", prio = 9 }, + -- PrevParagraph = { text = "{", prio = 8 }, + -- NextParagraph = { text = "}", prio = 8 }, + -- }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/protobuf.lua b/home/tigor/config/nvim/lua/plugins/protobuf.lua new file mode 100644 index 0000000..9e48c9a --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/protobuf.lua @@ -0,0 +1,19 @@ +return { + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "buf", "buf-language-server" }) + end, + }, + { + "nvimtools/none-ls.nvim", + opts = function(_, opts) + local nls = require("null-ls") + opts.sources = vim.list_extend(opts.sources or {}, { + nls.builtins.diagnostics.buf, + nls.builtins.formatting.buf, + }) + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/rest.lua b/home/tigor/config/nvim/lua/plugins/rest.lua new file mode 100644 index 0000000..4a13bb1 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/rest.lua @@ -0,0 +1,17 @@ +return { + { + "nicwest/vim-http", + ft = "http", + init = function() + vim.g.vim_http_tempbuffer = 1 + vim.g.vim_http_clean_before_do = 0 + end, + }, + { + "nvim-treesitter/nvim-treesitter", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "http", "json" }) + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/rose-pine.lua b/home/tigor/config/nvim/lua/plugins/rose-pine.lua new file mode 100644 index 0000000..2db3418 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/rose-pine.lua @@ -0,0 +1,9 @@ +return { + { "rose-pine/neovim", name = "rose-pine" }, + -- { + -- "LazyVim/LazyVim", + -- opts = { + -- colorscheme = "rose-pine", + -- }, + -- }, +} diff --git a/home/tigor/config/nvim/lua/plugins/silicon.lua b/home/tigor/config/nvim/lua/plugins/silicon.lua new file mode 100644 index 0000000..0d65b6b --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/silicon.lua @@ -0,0 +1,56 @@ +return { + "tigorlazuardi/silicon.lua", + cmd = { "Silicon" }, + config = function() + require("silicon").setup { + output = function() + return ([[%s/Pictures/SILICON_%s.png]]):format(vim.env.HOME, os.date "%Y-%m-%d_%H-%M-%S") + end, + padHoriz = 40, + padVert = 50, + } + vim.api.nvim_create_user_command("Silicon", function(ctx) + local args = (ctx.fargs or {})[1] + local opts = {} + if args == "buffer" then + opts.show_buf = true + end + if args == "visible" then + opts.visible = true + end + if not ctx.bang then + opts.to_clip = true + end + require("silicon").visualise_cmdline(opts) + end, { + range = 2, + desc = "Create screenshot from given range. Add Bang (!) at the end of the command to save to file instead of clipboard", + bang = true, + nargs = "?", + complete = function(arg) + if not arg then + return { "buffer", "visible" } + end + if arg:gsub(" ", "") == "" then + return { "buffer", "visible" } + end + if string.find("buffer", arg) then + return { "buffer" } + end + if string.find("visible", arg) then + return { "visible" } + end + return {} + end, + }) + vim.api.nvim_create_autocmd({ "ColorScheme" }, { + group = vim.api.nvim_create_augroup("SiliconRefresh", {}), + callback = function() + local silicon_utils = require "silicon.utils" + silicon_utils.build_tmTheme() + silicon_utils.reload_silicon_cache { async = true } + end, + desc = "Reload silicon themes cache on colorscheme switch", + }) + end, +} diff --git a/home/tigor/config/nvim/lua/plugins/ssh.lua b/home/tigor/config/nvim/lua/plugins/ssh.lua new file mode 100644 index 0000000..b297d82 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/ssh.lua @@ -0,0 +1,13 @@ +return { + "ojroques/nvim-osc52", + cond = vim.env.SSH_CLIENT ~= nil, + config = function() + require("osc52").setup({}) + vim.api.nvim_create_autocmd("TextYankPost", { + callback = function() + require("osc52").copy(table.concat(vim.v.event.regcontents, "\n")) + end, + desc = "Copy to Clipboard from SSH Session", + }) + end, +} diff --git a/home/tigor/config/nvim/lua/plugins/tailwind.lua b/home/tigor/config/nvim/lua/plugins/tailwind.lua new file mode 100644 index 0000000..80099ef --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/tailwind.lua @@ -0,0 +1,15 @@ +return { + "neovim/nvim-lspconfig", + opts = { + servers = { + tailwindcss = { + -- exclude a filetype from the default_config + filetypes_exclude = { "markdown", "javascript", "typescript" }, + -- add additional filetypes to the default_config + filetypes_include = {}, + -- to fully override the default_config, change the below + -- filetypes = {} + }, + }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/telescope-fzf-native.lua b/home/tigor/config/nvim/lua/plugins/telescope-fzf-native.lua new file mode 100644 index 0000000..16689b4 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/telescope-fzf-native.lua @@ -0,0 +1,10 @@ +return { + "telescope.nvim", + dependencies = { + "nvim-telescope/telescope-fzf-native.nvim", + build = "make", + config = function() + require("telescope").load_extension("fzf") + end, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/toggleterm.lua b/home/tigor/config/nvim/lua/plugins/toggleterm.lua new file mode 100644 index 0000000..a3263a1 --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/toggleterm.lua @@ -0,0 +1,21 @@ +return { + "akinsho/toggleterm.nvim", + keys = { + { "", "Open Toggleterm" }, + }, + cmd = { "ToggleTerm" }, + version = "*", + opts = { + size = function(term) + if term.direction == "horizontal" then + if vim.o.lines < 60 then + return 12 + end + return 20 + elseif term.direction == "vertical" then + return vim.o.columns * 0.3 + end + end, + open_mapping = [[]], + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/treesitter.lua b/home/tigor/config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..145c07d --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,38 @@ +return { + { + "nvim-treesitter/nvim-treesitter", + dependencies = { + "RRethy/nvim-treesitter-endwise", + }, + opts = { + endwise = { + enable = true, + }, + }, + }, + { + "windwp/nvim-ts-autotag", + opts = { + filetypes = { + "astro", + "glimmer", + "handlebars", + "hbs", + "html", + "javascript", + "javascriptreact", + "jsx", + "markdown", + "php", + "rescript", + "svelte", + "templ", + "tsx", + "typescript", + "typescriptreact", + "vue", + "xml", + }, + }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/vim-test.lua b/home/tigor/config/nvim/lua/plugins/vim-test.lua new file mode 100644 index 0000000..af2352f --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/vim-test.lua @@ -0,0 +1,10 @@ +return { + "vim-test/vim-test", + keys = { + { "Tr", "TestNearest", desc = "Test Run Nearest" }, + { "Tt", "TestFile", desc = "Test File" }, + { "TT", "TestSuite", desc = "Test All Files" }, + { "Tl", "TestLast", desc = "Test Last" }, + { "Tg", "TestVisit", desc = "Test Visit" }, + }, +} diff --git a/home/tigor/config/nvim/lua/plugins/yanky.lua b/home/tigor/config/nvim/lua/plugins/yanky.lua new file mode 100644 index 0000000..e6e450a --- /dev/null +++ b/home/tigor/config/nvim/lua/plugins/yanky.lua @@ -0,0 +1,10 @@ +return { + "gbprod/yanky.nvim", + dependencies = { + { "kkharji/sqlite.lua" }, + }, + opts = { + ring = { storage = "sqlite" }, + highlight = { timer = 150 }, + }, +} diff --git a/home/tigor/config/nvim/lua/snippets/go/apm_span.lua b/home/tigor/config/nvim/lua/snippets/go/apm_span.lua new file mode 100644 index 0000000..8475af9 --- /dev/null +++ b/home/tigor/config/nvim/lua/snippets/go/apm_span.lua @@ -0,0 +1,170 @@ +local ls = require "luasnip" +local sn = ls.sn +local s = ls.s +local i = ls.insert_node +local t = ls.text_node +local d = ls.dynamic_node +local f = ls.function_node +local fmta = require("luasnip.extras.fmt").fmta +local c = ls.choice_node + +local get_node_text = vim.treesitter.get_node_text + +local create_package_query = function() + return vim.treesitter.query.parse( + "go", + [[ + ((package_identifier) @package) + ]] + ) +end + +local function get_method_receiver_type_text(node) + local query = vim.treesitter.query.parse( + "go", + [[ + (method_declaration receiver: (parameter_list + (parameter_declaration type: (_) @method_receiver))) + ]] + ) + + for _, capture in query:iter_captures(node, 0) do + return get_node_text(capture, 0) + end + return "Method Receiver Not Found" +end + +local function get_package_node(node) + local root = node:tree():root() + local query = create_package_query() + for _, capture in query:iter_captures(root, 0) do + return capture + end + return nil +end + +local function get_method_or_function_declaration_node(node) + local parent = node:parent() + while parent ~= nil do + if parent:type() == "function_declaration" or parent:type() == "method_declaration" then + return parent + end + parent = parent:parent() + end +end + +local root_types = { + method_declaration = true, + function_declaration = true, + func_literal = true, +} + +local handlers = { + ["context.Context"] = function(node) + local var_name_node = node:prev_named_sibling() + local text = get_node_text(var_name_node, 0) + return text + end, + ["*http.Request"] = function(node) + local var_name_node = node:prev_named_sibling() + local text = get_node_text(var_name_node, 0) + return text .. ".Context()" + end, +} + +local build_context_node = function() + local query = assert(vim.treesitter.query.get("go", "search-context"), "No Query") + local node = vim.treesitter.get_node() + while node ~= nil do + if root_types[node:type()] then + for _, capture in query:iter_captures(node, 0) do + local text = get_node_text(capture, 0) + local handle = handlers[text] + if handle then + return handle(capture) + end + end + end + node = node:parent() + end + return "context.Background()" +end + +local function get_method_or_function_name(node) + if node:type() == "method_declaration" then + return get_node_text(node:named_child(1), 0) + end + return get_node_text(node:named_child(0), 0) +end + +local build_span_type_node = function(ctx) + local node = vim.treesitter.get_node() + local method_or_function_node = get_method_or_function_declaration_node(node) + if method_or_function_node == nil then + vim.notify "Not inside method or function" + return { t "" } + end + local package_node = get_package_node(node) + if package_node == nil then + vim.notify "No package node found" + return { t "" } + end + local package_text = get_node_text(package_node, 0) + local final_name = "" + if method_or_function_node:type() == "method_declaration" then + local method_node = method_or_function_node + local receiver_type = get_method_receiver_type_text(method_node) + final_name = ([[%s.%s]]):format(package_text, receiver_type) + else + if method_or_function_node:type() == "function_declaration" then + local function_node = method_or_function_node + local fn_name = get_method_or_function_name(function_node) + final_name = ([[%s.%s]]):format(package_text, fn_name) + end + end + ctx.index = ctx.index + 1 + return { i(ctx.index, final_name) } +end + +local build_span_name_node = function(ctx) + local node = vim.treesitter.get_node() + local method_or_function_node = get_method_or_function_declaration_node(node) + if method_or_function_node == nil then + vim.notify "Not inside method or function" + return { t "" } + end + local fn_name = get_method_or_function_name(method_or_function_node) + ctx.index = ctx.index + 1 + return { i(ctx.index, fn_name) } +end + +local get_span_name_node = function() + return sn(nil, build_span_name_node { index = 0 }) +end + +local get_span_type_node = function() + return sn(nil, build_span_type_node { index = 0 }) +end + +ls.add_snippets("go", { + s( + "apm:span", + fmta( + [[ +span, := apm.StartSpan(, "", "") +defer span.End() + +]], + { + ctx_var = c(1, { + t "ctx", + t "_", + }), + ctx = f(build_context_node, {}), + span_name = d(2, get_span_name_node), + span_type = d(3, get_span_type_node), + finish = i(0), + } + ) + ), +}) diff --git a/home/tigor/config/nvim/lua/snippets/go/efi.lua b/home/tigor/config/nvim/lua/snippets/go/efi.lua new file mode 100644 index 0000000..8684849 --- /dev/null +++ b/home/tigor/config/nvim/lua/snippets/go/efi.lua @@ -0,0 +1,178 @@ +local ls = require "luasnip" + +local sn = ls.sn + +local s = ls.s +local i = ls.insert_node +local t = ls.text_node +local d = ls.dynamic_node +local c = ls.choice_node +local fmta = require("luasnip.extras.fmt").fmta +local rep = require("luasnip.extras").rep + +local get_node_text = vim.treesitter.get_node_text + +local default_values = { + int = "0", + int8 = "0", + int16 = "0", + int32 = "0", + int64 = "0", + uint = "0", + uint8 = "0", + uint16 = "0", + uint32 = "0", + uint64 = "0", + ["time.Time"] = "time.Time{}", + ["time.Duration"] = "time.Duration(0)", + bool = "false", + string = [[""]], + float32 = "0", + float64 = "0", + error = function(_, info) + if info then + info.index = info.index + 1 + + return c(info.index, { + t(info.err_name), + t(string.format('errors.Wrap(%s, "%s")', info.err_name, info.func_name)), + }) + else + return t "err" + end + end, + + -- Types with a "*" mean they are pointers, so return nil + [function(text) + return string.find(text, "*", 1, true) ~= nil + end] = function(_, _) + return t "nil" + end, + + [function(text) + return not string.find(text, "*", 1, true) and string.upper(string.sub(text, 1, 1)) == string.sub(text, 1, 1) + end] = function(text, info) + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) + end, +} + +local transform = function(text, info) + local condition_matches = function(condition, ...) + if type(condition) == "string" then + return condition == text + else + return condition(...) + end + end + + for condition, result in pairs(default_values) do + if condition_matches(condition, text, info) then + if type(result) == "string" then + return t(result) + end + return result(text, info) + end + end + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) +end + +local handlers = { + parameter_list = function(node, info) + local result = {} + + local count = node:named_child_count() + for idx = 0, count - 1 do + local matching_node = node:named_child(idx) + local type_node = matching_node:field("type")[1] + table.insert(result, transform(get_node_text(type_node, 0), info)) + if idx ~= count - 1 then + table.insert(result, t { ", " }) + end + end + + return result + end, + + type_identifier = function(node, info) + local text = get_node_text(node, 0) + return { transform(text, info) } + end, +} + +local function_node_types = { + function_declaration = true, + method_declaration = true, + func_literal = true, +} + +local function go_result_type(info) + local node = vim.treesitter.get_node() + while node ~= nil do + if function_node_types[node:type()] then + break + end + node = node:parent() + end + if not node then + vim.notify("Not inside a function", vim.log.levels.ERROR, { title = "Snippet" }) + return t "" + end + + local query = assert(vim.treesitter.query.get("go", "return-snippet"), "No Query") + + for _, capture in query:iter_captures(node, 0) do + if handlers[capture:type()] then + return handlers[capture:type()](capture, info) + end + end + + info.index = info.index + 1 + return { i(info.index, "nil") } +end + +local go_return_values = function(args) + return sn( + nil, + go_result_type { + index = 0, + err_name = args[1][1], + func_name = args[2][1], + } + ) +end + +ls.add_snippets("go", { + s( + "efi", + fmta( + [[ +, := () +if != nil { + return +} + +]], + { + val = i(1), + err = i(2, "err"), + f = i(3), + args = i(4), + err_same = rep(2), + result = d(5, go_return_values, { 2, 3 }), + finish = i(0), + } + ) + ), +}) diff --git a/home/tigor/config/nvim/lua/snippets/go/err_tower.lua b/home/tigor/config/nvim/lua/snippets/go/err_tower.lua new file mode 100644 index 0000000..0d92326 --- /dev/null +++ b/home/tigor/config/nvim/lua/snippets/go/err_tower.lua @@ -0,0 +1,452 @@ +local ls = require "luasnip" + +local sn = ls.snippet_node +local isn = ls.indent_snippet_node + +local s = ls.s +local i = ls.insert_node +local t = ls.text_node +local d = ls.dynamic_node +local c = ls.choice_node +local f = ls.function_node +local fmta = require("luasnip.extras.fmt").fmta +local rep = require("luasnip.extras").rep + +local get_node_text = vim.treesitter.get_node_text + +local default_values = { + int = "0", + int8 = "0", + int16 = "0", + int32 = "0", + int64 = "0", + uint = "0", + uint8 = "0", + uint16 = "0", + uint32 = "0", + uint64 = "0", + ["time.Time"] = "time.Time{}", + ["time.Duration"] = "time.Duration(0)", + bool = "false", + string = [[""]], + float32 = "0", + float64 = "0", + error = "errt", + + -- Types with a "*" mean they are pointers, so return nil + [function(text) + return string.find(text, "*", 1, true) ~= nil + end] = function(_, _) + return t "nil" + end, + + [function(text) + return not string.find(text, "*", 1, true) and string.upper(string.sub(text, 1, 1)) == string.sub(text, 1, 1) + end] = function(text, info) + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) + end, +} + +local transform = function(text, info) + local condition_matches = function(condition, ...) + if type(condition) == "string" then + return condition == text + else + return condition(...) + end + end + + for condition, result in pairs(default_values) do + if condition_matches(condition, text, info) then + if type(result) == "string" then + return t(result) + end + return result(text, info) + end + end + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) +end + +local handlers = { + parameter_list = function(node, info) + local result = {} + + local count = node:named_child_count() + for idx = 0, count - 1 do + local matching_node = node:named_child(idx) + local type_node = matching_node:field("type")[1] + table.insert(result, transform(get_node_text(type_node, 0), info)) + if idx ~= count - 1 then + table.insert(result, t { ", " }) + end + end + + return result + end, + + type_identifier = function(node, info) + local text = get_node_text(node, 0) + return { transform(text, info) } + end, +} + +local function_node_types = { + function_declaration = true, + method_declaration = true, + func_literal = true, +} + +local function go_result_type(info) + local node = vim.treesitter.get_node() + while node ~= nil do + if function_node_types[node:type()] then + break + end + node = node:parent() + end + if not node then + vim.notify("Not inside a function", vim.log.levels.ERROR, { title = "Snippet" }) + return t "" + end + + local query = assert(vim.treesitter.query.get("go", "return-snippet"), "No Query") + + for _, capture in query:iter_captures(node, 0) do + if handlers[capture:type()] then + return handlers[capture:type()](capture, info) + end + end + return {} +end + +local go_return_values = function() + return sn( + nil, + go_result_type { + index = 0, + } + ) +end + +local function get_method_or_function_declaration_node(node) + local parent = node:parent() + while parent ~= nil do + if parent:type() == "function_declaration" or parent:type() == "method_declaration" then + return parent + end + parent = parent:parent() + end +end + +local function get_method_or_function_name(node) + if node:type() == "method_declaration" then + return get_node_text(node:named_child(1), 0) + end + return get_node_text(node:named_child(0), 0) +end + +local function get_method_receiver_type_text(node) + local query = vim.treesitter.query.parse( + "go", + [[ + (method_declaration receiver: (parameter_list + (parameter_declaration type: (_) @method_receiver))) + ]] + ) + + for _, capture in query:iter_captures(node, 0) do + local text = get_node_text(capture, 0) + if text:sub(1, 1) == "*" then + return "(" .. text .. ")" + end + return text + end + return "Method Receiver Not Found" +end + +local function get_package_node(node) + local root = node:tree():root() + local query = assert(vim.treesitter.query.get("go", "package-node"), "No Query") + for _, capture in query:iter_captures(root, 0) do + return capture + end + return nil +end + +local function get_package_text(node) + local package_node = get_package_node(node) + if package_node then + return get_node_text(package_node, 0) .. "." + end + vim.notify("Package name not found", vim.log.levels.ERROR, { title = "Snippet" }) + return "" +end + +local function get_function_name() + local node = vim.treesitter.get_node() + local method_or_function_node = get_method_or_function_declaration_node(node) + if not method_or_function_node then + vim.notify("Not inside a function", vim.log.levels.ERROR, { title = "Snippet" }) + return "" + end + local fn_name = get_method_or_function_name(method_or_function_node) + if method_or_function_node:type() == "method_declaration" then + return ([[(%s.%s.%s)]]):format(get_package_text(node), get_method_receiver_type_text(node), fn_name) + end + return ([[(%s.%s)]]):format(get_package_text(node), fn_name) +end + +local function get_context_var_name() + local node = vim.treesitter.get_node() + while node ~= nil do + if function_node_types[node:type()] then + local query = assert(vim.treesitter.query.get("go", "get-function-params"), "No Query") + for _, capture in query:iter_captures(node, 0) do + local var_name = capture:named_child(0) + if var_name:type() == "identifier" then + local type_name = capture:named_child(1) + local type_text = get_node_text(type_name, 0) + if type_text == "context.Context" then + return get_node_text(var_name, 0) + end + end + end + end + node = node:parent() + end + return "context.Background()" +end + +local create_tower_build_choice = function(index) + return c(index, { + t "Freeze()", + sn(nil, { i(1), t "Log(", f(get_context_var_name), t ")" }), + -- stylua: ignore start + isn(nil, { + i(1), t "Log(", f(get_context_var_name), t ").", + t {"", "Notify("}, f(get_context_var_name), t ")", + }, "$PARENT_INDENT\t\t"), + -- stylua: ignore end + }, { + node_ext_opts = { + active = { + virt_text = { { "<-- Choose build choice" } }, + }, + }, + }) +end + +local function register_snippet() + ls.add_snippets("go", { + s( + "errt", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + build = create_tower_build_choice(3), + result = d(4, go_return_values), + finish = i(0), + } + ) + ), + s( + "errtc", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + Context(). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + fields = i(3), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errtp", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + PublicMessage(""). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errtpc", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + PublicMessage(""). + Context(). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + fields = i(4), + build = create_tower_build_choice(5), + result = d(6, go_return_values), + finish = i(0), + } + ) + ), + s( + "errb", + fmta( + [[ +if { + errt := tower. + Bail(" "). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + build = create_tower_build_choice(3), + result = d(4, go_return_values), + finish = i(0), + } + ) + ), + s( + "errbc", + fmta( + [[ +if { + errt := tower. + Bail(" "). + Context(). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + fields = i(3), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errbp", + fmta( + [[ +if { + errt := tower. + Bail(" "). + PublicMessage(""). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errbpc", + fmta( + [[ +if { + errt := tower. + Bail(" "). + PublicMessage(""). + Context(). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + fields = i(4), + build = create_tower_build_choice(5), + result = d(6, go_return_values), + finish = i(0), + } + ) + ), + }) +end + +register_snippet() diff --git a/home/tigor/config/nvim/lua/snippets/go/init.lua b/home/tigor/config/nvim/lua/snippets/go/init.lua new file mode 100644 index 0000000..77b9f3c --- /dev/null +++ b/home/tigor/config/nvim/lua/snippets/go/init.lua @@ -0,0 +1,9 @@ +-- Use to clear snippets when sourced. +-- +-- Useful when building a new snippet. +-- +-- require("luasnip.session.snippet_collection").clear_snippets("go") + +require "snippets.go.efi" +require "snippets.go.apm_span" +require "snippets.go.err_tower" diff --git a/home/tigor/config/nvim/lua/snippets/init.lua b/home/tigor/config/nvim/lua/snippets/init.lua new file mode 100644 index 0000000..144dbbf --- /dev/null +++ b/home/tigor/config/nvim/lua/snippets/init.lua @@ -0,0 +1 @@ +require "snippets.go" diff --git a/home/tigor/config/nvim/queries/go/get-function-params.scm b/home/tigor/config/nvim/queries/go/get-function-params.scm new file mode 100644 index 0000000..64b8fbc --- /dev/null +++ b/home/tigor/config/nvim/queries/go/get-function-params.scm @@ -0,0 +1,10 @@ +[ + (method_declaration + parameters: (parameter_list + (parameter_declaration) @params)) + (function_declaration + parameters: (parameter_list + (parameter_declaration) @params)) + (func_literal parameters: + (parameter_list (parameter_declaration) @params)) +] diff --git a/home/tigor/config/nvim/queries/go/package-node.scm b/home/tigor/config/nvim/queries/go/package-node.scm new file mode 100644 index 0000000..06edc37 --- /dev/null +++ b/home/tigor/config/nvim/queries/go/package-node.scm @@ -0,0 +1 @@ +(source_file (package_clause (package_identifier) @package_name) ) diff --git a/home/tigor/config/nvim/queries/go/return-snippet.scm b/home/tigor/config/nvim/queries/go/return-snippet.scm new file mode 100644 index 0000000..0a68f81 --- /dev/null +++ b/home/tigor/config/nvim/queries/go/return-snippet.scm @@ -0,0 +1,5 @@ +[ + (method_declaration result: (_) @type) + (function_declaration result: (_) @type) + (func_literal result: (_) @type) +] diff --git a/home/tigor/config/nvim/queries/go/search-context.scm b/home/tigor/config/nvim/queries/go/search-context.scm new file mode 100644 index 0000000..5969a4e --- /dev/null +++ b/home/tigor/config/nvim/queries/go/search-context.scm @@ -0,0 +1,11 @@ +[ + (method_declaration + parameters: (parameter_list + (parameter_declaration type: (_) @type))) + (function_declaration + parameters: (parameter_list + (parameter_declaration type: (_) @type))) + (func_literal + parameters: (parameter_list + (parameter_declaration type: (_) @type))) +] diff --git a/home/tigor/config/nvim/stylua.toml b/home/tigor/config/nvim/stylua.toml new file mode 100644 index 0000000..02ed90b --- /dev/null +++ b/home/tigor/config/nvim/stylua.toml @@ -0,0 +1,4 @@ +indent_type = "Spaces" +indent_width = 4 +column_width = 120 +call_parentheses = "None" diff --git a/home/tigor/config/wezterm/default.nix b/home/tigor/config/wezterm/default.nix new file mode 100644 index 0000000..2608597 --- /dev/null +++ b/home/tigor/config/wezterm/default.nix @@ -0,0 +1,14 @@ +{ ... }: + +{ + programs.wezterm = { + enable = true; + enableZshIntegration = true; + enableBashIntegration = true; + }; + + home.file.".config/wezterm" = { + source = ./.; + recursive = true; + }; +} diff --git a/home/tigor/config/wezterm/keys.lua b/home/tigor/config/wezterm/keys.lua new file mode 100644 index 0000000..1dfe01d --- /dev/null +++ b/home/tigor/config/wezterm/keys.lua @@ -0,0 +1,211 @@ +local wezterm = require('wezterm') +local act = wezterm.action + +wezterm.on('update-status', function(window) + local name = window:active_key_table() + if name then + name = 'TABLE: ' .. name + end + window:set_left_status(name or '') +end) + +local M = {} + +M.keys = { + { + key = ':', + mods = 'LEADER|SHIFT', + action = act.ShowLauncherArgs({ flags = 'FUZZY|TABS|LAUNCH_MENU_ITEMS|DOMAINS' }), + }, + { + key = 'phys:Backspace', + mods = 'LEADER', + action = act.SplitPane({ direction = 'Down', size = { Percent = 25 } }), + }, + { + key = 'phys:Backspace', + mods = 'LEADER|SHIFT', + action = act.SplitPane({ direction = 'Down' }), + }, + { + key = 'Enter', + mods = 'LEADER', + action = act.SplitPane({ direction = 'Right', size = { Percent = 25 } }), + }, + { + key = 'Enter', + mods = 'LEADER|SHIFT', + action = act.SplitPane({ direction = 'Right' }), + }, + { + key = 'h', + mods = 'LEADER', + action = act.ActivatePaneDirection('Left'), + }, + { + key = 'j', + mods = 'LEADER', + action = act.ActivatePaneDirection('Down'), + }, + { + key = 'k', + mods = 'LEADER', + action = act.ActivatePaneDirection('Up'), + }, + { + key = 'l', + mods = 'LEADER', + action = act.ActivatePaneDirection('Right'), + }, + { + key = 'w', + mods = 'LEADER', + action = act.CloseCurrentPane({ confirm = false }), + }, + { + key = 'v', + mods = 'LEADER', + action = act.ActivateCopyMode, + }, + { + key = 'f', + mods = 'LEADER', + action = act.Search({ CaseInSensitiveString = '' }), + }, + { + key = 'x', + mods = 'LEADER', + action = act.CloseCurrentTab({ confirm = true }), + }, + -- Tab Management + { + key = 't', + mods = 'LEADER', + action = act.SpawnTab('CurrentPaneDomain'), + }, + { + key = 'n', + mods = 'LEADER', + action = act.ActivateTabRelative(1), + }, + { + key = 'p', + mods = 'LEADER', + action = act.ActivateTabRelative(-1), + }, + { + key = 'r', + mods = 'LEADER', + action = act.ActivateKeyTable({ + name = 'resize_pane', + one_shot = false, + }), + }, + { + key = 'F4', + mods = '', + action = act.TogglePaneZoomState, + }, + { + key = "'", + mods = 'LEADER', + action = act.ShowDebugOverlay, + }, + { + key = 'o', + mods = 'ALT', + action = wezterm.action.QuickSelectArgs({ + label = 'open', + patterns = { + [[\bhttps?://\S+\b]], + }, + action = wezterm.action_callback(function(window, pane) + local url = window:get_selection_text_for_pane(pane) + wezterm.log_info('opening: ' .. url) + wezterm.open_with(url) + end), + }), + }, + { + key = 's', + mods = 'LEADER', + action = act.PaneSelect, + }, + { + key = 's', + mods = 'LEADER|SHIFT', + action = act.PaneSelect({ mode = 'SwapWithActive' }), + }, + { + key = 'a', + mods = 'LEADER|CTRL', + action = act.ShowTabNavigator, + }, +} + +for i = 1, 9 do + table.insert(M.keys, { + key = tostring(i), + mods = 'LEADER', + action = act.ActivateTab(i - 1), + }) +end + +M.key_tables = { + resize_pane = (function(size) + return { + { key = 'LeftArrow', action = act.AdjustPaneSize({ 'Left', size }) }, + { key = 'h', action = act.AdjustPaneSize({ 'Left', size }) }, + + { key = 'RightArrow', action = act.AdjustPaneSize({ 'Right', size }) }, + { key = 'l', action = act.AdjustPaneSize({ 'Right', size }) }, + + { key = 'UpArrow', action = act.AdjustPaneSize({ 'Up', size }) }, + { key = 'k', action = act.AdjustPaneSize({ 'Up', size }) }, + + { key = 'DownArrow', action = act.AdjustPaneSize({ 'Down', size }) }, + { key = 'j', action = act.AdjustPaneSize({ 'Down', size }) }, + + -- Cancel the mode by pressing escape + { key = 'Escape', action = 'PopKeyTable' }, + { key = 'c', mods = 'CTRL', action = 'PopKeyTable' }, + { key = '[', mods = 'CTRL', action = 'PopKeyTable' }, + } + end)(3), +} + +M.mouse_bindings = { + { + event = { Up = { streak = 1, button = 'Left' } }, + mods = 'NONE', + action = act.CompleteSelection('Clipboard'), + }, + { + event = { Up = { streak = 1, button = 'Left' } }, + mods = 'CTRL', + action = wezterm.action.CompleteSelectionOrOpenLinkAtMouseCursor('Clipboard'), + }, + -- Disable the 'Down' event of CTRL-Click to avoid weird program behaviors + { + event = { Down = { streak = 1, button = 'Left' } }, + mods = 'CTRL', + action = act.Nop, + }, + -- Scrolling up while holding CTRL increases the font size + { + event = { Down = { streak = 1, button = { WheelUp = 1 } } }, + mods = 'CTRL', + action = act.IncreaseFontSize, + }, + + -- Scrolling down while holding CTRL decreases the font size + { + event = { Down = { streak = 1, button = { WheelDown = 1 } } }, + mods = 'CTRL', + action = act.DecreaseFontSize, + }, +} + +M.leader = { key = 'a', mods = 'CTRL', timeout_milliseconds = 5000 } + +return M diff --git a/home/tigor/config/wezterm/stylua.toml b/home/tigor/config/wezterm/stylua.toml new file mode 100644 index 0000000..158e02b --- /dev/null +++ b/home/tigor/config/wezterm/stylua.toml @@ -0,0 +1,5 @@ +column_width = 120 +indent_type = "Tabs" +indent_width = 4 +quote_style = "AutoPreferSingle" + diff --git a/home/tigor/config/wezterm/wezterm.lua b/home/tigor/config/wezterm/wezterm.lua new file mode 100644 index 0000000..2658df6 --- /dev/null +++ b/home/tigor/config/wezterm/wezterm.lua @@ -0,0 +1,78 @@ +local wezterm = require('wezterm') + +local shortcuts = require('keys') + +return { + font = wezterm.font_with_fallback({ + -- 'Comic Code Ligatures', + 'JetBrainsMono Nerd Font Mono', + 'Noto Color Emoji', + 'Material Design Icons', + 'codicon', + 'monospace', + }), + hide_tab_bar_if_only_one_tab = true, + use_fancy_tab_bar = false, + tab_max_width = 32, + window_close_confirmation = 'NeverPrompt', + color_scheme = 'Catppuccin Mocha', + warn_about_missing_glyphs = false, + check_for_updates = false, + ssh_domains = { + { + name = 'home', + remote_address = 'home', + username = 'tigor', + ssh_option = { + identityfile = wezterm.home_dir .. '/.ssh/id_ed25519.pub', + }, + }, + }, + unix_domains = { + { + name = 'unix', + }, + }, + mouse_bindings = shortcuts.mouse_bindings, + leader = shortcuts.leader, + keys = shortcuts.keys, + key_tables = shortcuts.key_tables, + window_background_opacity = 1, + text_background_opacity = 1, + hyperlink_rules = { + -- Linkify things that look like URLs and the host has a TLD name. + -- Compiled-in default. Used if you don't specify any hyperlink_rules. + { + regex = '\\b\\w+://[\\w.-]+\\.[a-z]{2,15}\\S*\\b', + format = '$0', + }, + + -- linkify email addresses + -- Compiled-in default. Used if you don't specify any hyperlink_rules. + { + regex = [[\b\w+@[\w-]+(\.[\w-]+)+\b]], + format = 'mailto:$0', + }, + + -- file:// URI + -- Compiled-in default. Used if you don't specify any hyperlink_rules. + { + regex = [[\bfile://\S*\b]], + format = '$0', + }, + + -- filename:linenumber + { + regex = [[/.*:\d+]], + format = '$0', + }, + + -- Linkify things that look like URLs with numeric addresses as hosts. + -- E.g. http://127.0.0.1:8000 for a local development server, + -- or http://192.168.1.1 for the web interface of many routers. + { + regex = [[\b\w+://(?:[\d]{1,3}\.){3}[\d]{1,3}\S*\b]], + format = '$0', + }, + }, +} diff --git a/home/tigor/default.nix b/home/tigor/default.nix new file mode 100644 index 0000000..ad725e6 --- /dev/null +++ b/home/tigor/default.nix @@ -0,0 +1,29 @@ +{ pkgs, profile-path, ... }: +{ + imports = [ + profile-path + + ./programs + ../modules + + ./config/wezterm + ./config/nvim + ./direnv.nix + ./config/kitty + ./config/ideavim + ./secrets.nix + ]; + + home = { + username = "tigor"; + homeDirectory = "/home/tigor"; + stateVersion = "23.11"; + }; + + + systemd.user.sessionVariables = { + XDG_CONFIG_HOME = "/home/tigor/.config"; + }; + + services.mpris-proxy.enable = true; +} diff --git a/home/tigor/direnv.nix b/home/tigor/direnv.nix new file mode 100644 index 0000000..701f7b3 --- /dev/null +++ b/home/tigor/direnv.nix @@ -0,0 +1,7 @@ +{ + programs.direnv = { + enable = true; + nix-direnv.enable = true; + enableZshIntegration = true; + }; +} diff --git a/home/tigor/programs/autostart.nix b/home/tigor/programs/autostart.nix new file mode 100644 index 0000000..d9cf690 --- /dev/null +++ b/home/tigor/programs/autostart.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: +{ + home.packages = with pkgs; [ + variety + bitwarden + ]; + + home.file = { + ".config/autostart/variety.desktop" = { + source = "${pkgs.variety}/share/applications/variety.desktop"; + }; + + ".config/autostart/bitwarden.desktop" = { + source = "${pkgs.bitwarden}/share/applications/bitwarden.desktop"; + }; + }; +} diff --git a/home/tigor/programs/default.nix b/home/tigor/programs/default.nix new file mode 100644 index 0000000..43f784a --- /dev/null +++ b/home/tigor/programs/default.nix @@ -0,0 +1,104 @@ +{ pkgs, unstable, ... }: +{ + imports = [ + ./autostart.nix + ./git.nix + ./mpv.nix + ./node.nix + ./starship.nix + ./tofi.nix + ./vscode.nix + ./zsh.nix + ./discord.nix + ./neovide.nix + ./slack.nix + ./whatsapp.nix + ]; + + programs.home-manager.enable = true; + + programs.fzf = { + enable = true; + enableZshIntegration = true; + enableBashIntegration = true; + defaultCommand = "fd --type f"; + }; + programs.zoxide = { + enable = true; + enableBashIntegration = true; + enableZshIntegration = true; + }; + programs.ripgrep.enable = true; + + programs.go = { + enable = true; + goPrivate = [ + "gitlab.bareksa.com" + ]; + package = unstable.go_1_22; + }; + + programs.chromium = { + enable = true; + extensions = [ + { id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"; } # ublock origin + { id = "jinjaccalgkegednnccohejagnlnfdag"; } # violent monkey + { id = "nngceckbapebfimnlniiiahkandclblb"; } # bitwarden + { id = "mnjggcdmjocbbbhaepdhchncahnbgone"; } # sponsor block + { id = "pkehgijcmpdhfbdbbnkijodmdjhbjlgp"; } # privacy badger + { id = "fhcgjolkccmbidfldomjliifgaodjagh"; } # cookie auto delete + { id = "cimiefiiaegbelhefglklhhakcgmhkai"; } # Plasma Integration + ]; + commandLineArgs = [ + "--enable-features=UseOzonePlatform" + "--ozone-platform=wayland" + ]; + }; + + programs.nnn = { + enable = true; + }; + + programs.htop.enable = true; + + programs.mpv.enable = true; + + home.packages = with pkgs; [ + unstable.gh # github cli + wget + curl + openssl + zig + unzip + libcap + gcc + cargo + nixpkgs-fmt + fd + wl-clipboard + unstable.dbeaver-bin + unstable.jellyfin-media-player + stylua + luarocks + du-dust + just + modd + lefthook + spotify + # seafile-client + lsof + # scrcpy + masterpdfeditor4 + watchexec + kcalc + pdfarranger + unstable.microsoft-edge + # (floorp.override { + # nativeMessagingHosts = with pkgs; [ + # plasma5Packages.plasma-browser-integration + # ]; + # }) + nextcloud-client + # qownnotes + ]; +} diff --git a/home/tigor/programs/discord.nix b/home/tigor/programs/discord.nix new file mode 100644 index 0000000..8a89a6d --- /dev/null +++ b/home/tigor/programs/discord.nix @@ -0,0 +1,54 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.profile.discord; +in +{ + config = mkIf cfg.enable { + home.packages = with pkgs; [ + discord + ]; + + systemd.user = lib.mkIf cfg.autostart { + services.discord = { + Unit = { + Description = "Automatically start Discord on Login"; + # Only runs on sessions with a graphical target like X11 or Wayland. + Wants = [ "graphical.target" ]; + # Only run after the network is online. + After = [ "nss-lookup.target" ]; + StartLimitIntervalSec = 300; + StartLimitBurst = 10; + }; + Service = + let + bash = "${pkgs.bash}/bin/bash"; + ping = "${pkgs.unixtools.ping}/bin/ping"; + host = "discord.com"; + sleep = "${pkgs.coreutils}/bin/sleep"; + discord = "${pkgs.discord}/bin/discord"; + exec = ''${bash} -c "until ${ping} -c 1 ${host}; do ${sleep} 1; done; ${discord}"''; + in + { + Type = "simple"; + ExecStartPre = "${sleep} 5"; + ExecStart = exec; + Restart = "on-failure"; + RemainAfterExit = "yes"; + Environment = [ "NIXOS_OZONE_WL=1" ]; + }; + Install = { + WantedBy = [ "default.target" ]; # After user login. + }; + }; + }; + + home.file = { + ".config/discord/settings.json".text = '' + { + "SKIP_HOST_UPDATE": true + } + ''; + }; + }; +} diff --git a/home/tigor/programs/git.nix b/home/tigor/programs/git.nix new file mode 100644 index 0000000..b2c9230 --- /dev/null +++ b/home/tigor/programs/git.nix @@ -0,0 +1,114 @@ +{ pkgs, ... }: +{ + home.packages = with pkgs; [ + delta + difftastic + ]; + programs.git = { + enable = true; + extraConfig = { + init.defaultBranch = "main"; + diff = { + algorithm = "histogram"; + colorMoved = "default"; + colorMovedWS = "allow-indentation-change"; + context = 10; + tool = "difftastic"; + external = "difft"; + }; + difftastic = { + prompt = false; + "difftastic" = { + cmd = ''difft "$LOCAL" "$REMOTE"''; + }; + }; + pager.difftool = true; + commit.verbose = true; + help.autocorrect = 1; + push = { + autoSetupRemote = true; + default = "current"; + }; + pull.rebase = true; + merge.conflictStyle = "zdiff3"; + rebase.autosquash = true; + url = { + "git@gitlab.bareksa.com:" = { + insteadOf = "https://gitlab.bareksa.com"; + }; + "git@github.com:" = { + pushInsteadOf = "https://github.com"; + }; + }; + includeIf = { + "gitdir:~/bareksa/" = { + path = "~/bareksa/.gitconfig"; + }; + }; + + # Submodules + status.submodulesummary = true; + diff.submodule = "log"; + fetch.recurseSubmodules = "on-demand"; + submodule.recurse = true; + }; + userEmail = "tigor.hutasuhut@gmail.com"; + userName = "Tigor Hutasuhut"; + }; + + programs.lazygit = { + enable = true; + settings = { + git.paging = { + colorArg = "always"; + pager = "delta --dark --paging=never"; + }; + keybinding = { + files = { + # Swap commit changes and commit changes with editor + # + # since it's better to use neovim to write commit message + commitChanges = "C"; + commitChangesWithEditor = "c"; + }; + + commits = { + # Also swap rename commit and rename commit with editor + renameCommitWithEditor = "r"; + renameCommit = "R"; + }; + }; + theme = { + # Catppuccin Macchiato Rosewater + activeBorderColor = [ + "#f4dbd6" + "bold" + ]; + inactiveBorderColor = [ + "#a5adcb" + ]; + optionsTextColor = [ + "#8aadf4" + ]; + selectedLineBgColor = [ + "#363a4f" + ]; + cherryPickedCommitBgColor = [ + "#494d64" + ]; + cherryPickedCommitFgColor = [ + "#f4dbd6" + ]; + unstagedChangesColor = [ + "#ed8796" + ]; + defaultFgColor = [ + "#cad3f5" + ]; + searchingActiveBorderColor = [ + "#eed49f" + ]; + }; + }; + }; +} diff --git a/home/tigor/programs/mpv.nix b/home/tigor/programs/mpv.nix new file mode 100644 index 0000000..0e16340 --- /dev/null +++ b/home/tigor/programs/mpv.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +{ + programs.mpv = { + enable = true; + scripts = with pkgs.mpvScripts; [ + uosc + mpris + thumbnail + sponsorblock + ]; + }; +} diff --git a/home/tigor/programs/neovide.nix b/home/tigor/programs/neovide.nix new file mode 100644 index 0000000..fb74e85 --- /dev/null +++ b/home/tigor/programs/neovide.nix @@ -0,0 +1,27 @@ +{ config, unstable, pkgs, ... }: +{ + home.packages = [ + unstable.neovide + ]; + + home.file.".config/neovide/config.toml".source = + let + toml = pkgs.formats.toml { }; + in + toml.generate "config.toml" { + font = { + normal = [ "JetBrainsMono Nerd Font" ]; + size = 11.0; + }; + fork = false; + frame = if config.profile.hyprland.enable then "none" else "full"; + idle = true; + maximied = false; + no-multigrid = false; + tabs = false; + theme = "auto"; + title-hidden = true; + vsync = true; + wsl = false; + }; +} diff --git a/home/tigor/programs/node.nix b/home/tigor/programs/node.nix new file mode 100644 index 0000000..2006630 --- /dev/null +++ b/home/tigor/programs/node.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: +{ + home.packages = with pkgs.nodePackages_latest; [ + nodejs + pnpm + prettier + ]; +} diff --git a/home/tigor/programs/slack.nix b/home/tigor/programs/slack.nix new file mode 100644 index 0000000..d0c29a2 --- /dev/null +++ b/home/tigor/programs/slack.nix @@ -0,0 +1,57 @@ +{ pkgs, lib, config, ... }: +let + cfg = config.profile.slack; +in +{ + config = lib.mkIf cfg.enable { + home.packages = with pkgs; [ slack ]; + + systemd.user = lib.mkIf cfg.autostart { + # Unlike Discord, Slack is only used on office hours, + # so we will use a timer to start it on office hours only. + timers.slack = { + Unit = { + Description = "Start Slack Desktop Client on Weekdays on Login"; + }; + Timer = { + OnCalendar = "Mon..Fri 09..18:*:*"; + }; + Install = { + WantedBy = [ "default.target" ]; + }; + }; + services.slack = { + Unit = { + Description = "Slack Desktop Client"; + Wants = [ "graphical.target" ]; + After = [ "nss-lookup.target" ]; + StartLimitIntervalSec = 300; + StartLimitBurst = 10; + }; + Service = + let + bash = "${pkgs.bash}/bin/bash"; + ping = "${pkgs.unixtools.ping}/bin/ping"; + host = "google.com"; # slack.com does not respond to ping + sleep = "${pkgs.coreutils}/bin/sleep"; + slack = "${pkgs.slack}/bin/slack"; + exec = ''${bash} -c "until ${ping} -c 1 ${host}; do ${sleep} 1; done; ${slack}"''; + in + { + Type = "simple"; + ExecStartPre = "${sleep} 5"; + ExecStart = exec; + Restart = "on-failure"; + # Prevent Slack from auto-restarting when user closes it. + # The timer setup above will trigger this service + # if RemaiAfterExit is not set to "yes". + # + # This will mark the service as still "Active" by systemd + # hence the timer will not trigger the service again. + RemainAfterExit = "yes"; + Environment = [ "NIXOS_OZONE_WL=1" ]; + }; + }; + }; + }; +} diff --git a/home/tigor/programs/starship.nix b/home/tigor/programs/starship.nix new file mode 100644 index 0000000..a28f637 --- /dev/null +++ b/home/tigor/programs/starship.nix @@ -0,0 +1,41 @@ +{ pkgs, ... }: +{ + programs.starship = + let + flavour = "mocha"; + in + { + enable = true; + enableBashIntegration = true; + enableZshIntegration = true; + settings = { + scan_timeout = 10; + character = { + success_symbol = "[➜](bold green)"; + error_symbol = "[✘](bold red)"; + }; + format = "$all"; + directory = { + truncation_length = 8; + truncation_symbol = "…/"; + truncate_to_repo = false; + }; + username = { + show_always = true; + format = "\\[[$user]($style)@"; + }; + hostname = { + ssh_only = false; + format = "[$ssh_symbol$hostname]($style)\\] "; + }; + palette = "catppuccin_${flavour}"; + } // builtins.fromTOML (builtins.readFile + (pkgs.fetchFromGitHub + { + owner = "catppuccin"; + repo = "starship"; + rev = "5629d2356f62a9f2f8efad3ff37476c19969bd4f"; # Replace with the latest commit hash + sha256 = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; + } + /palettes/${flavour}.toml)); + }; +} diff --git a/home/tigor/programs/tofi.nix b/home/tigor/programs/tofi.nix new file mode 100644 index 0000000..ce17f71 --- /dev/null +++ b/home/tigor/programs/tofi.nix @@ -0,0 +1,34 @@ +{ pkgs, config, lib, ... }: +let + cfg = config.profile.tofi; +in +{ + config = lib.mkIf cfg.enable { + home.packages = with pkgs; [ tofi ]; + home.file = { + ".config/tofi/neovide.zsh" = { + executable = true; + text = '' + #/usr/bin/env zsh + folder=$(zoxide query --list | tofi) + [[ -z "$folder" ]] || (zsh -c "cd \"$folder\"; neovide --maximized") + ''; + }; + + ".config/tofi/config" = { + text = '' + width = 100% + height = 100% + border-width = 0 + outline-width = 0 + padding-left = 35% + padding-top = 35% + result-spacing = 25 + num-results = 5 + font = monospace + background-color = #000A + ''; + }; + }; + }; +} diff --git a/home/tigor/programs/vscode.nix b/home/tigor/programs/vscode.nix new file mode 100644 index 0000000..adcc3cd --- /dev/null +++ b/home/tigor/programs/vscode.nix @@ -0,0 +1,14 @@ +{ unstable, ... }: + +{ + programs.vscode = { + enable = true; + package = unstable.vscode; + extensions = with unstable.vscode-extensions; [ + dracula-theme.theme-dracula + golang.go + esbenp.prettier-vscode + catppuccin.catppuccin-vsc + ]; + }; +} diff --git a/home/tigor/programs/whatsapp.nix b/home/tigor/programs/whatsapp.nix new file mode 100644 index 0000000..06dce79 --- /dev/null +++ b/home/tigor/programs/whatsapp.nix @@ -0,0 +1,40 @@ +{ lib, config, pkgs, ... }: +let + cfg = config.profile.whatsapp; +in +{ + config = lib.mkIf cfg.enable { + home.packages = [ pkgs.whatsapp-for-linux ]; + + systemd.user = lib.mkIf cfg.autostart { + services.whatsapp = { + Unit = { + Description = "WhatsApp for Linux"; + Wants = [ "graphical.target" ]; + After = [ "nss-lookup.target" ]; + StartLimitIntervalSec = 300; + StartLimitBurst = 10; + }; + Service = + let + bash = "${pkgs.bash}/bin/bash"; + ping = "${pkgs.unixtools.ping}/bin/ping"; + host = "web.whatsapp.com"; + sleep = "${pkgs.coreutils}/bin/sleep"; + whatsapp = "${pkgs.whatsapp-for-linux}/bin/whatsapp-for-linux"; + exec = ''${bash} -c "until ${ping} -c 1 ${host}; do ${sleep} 1; done; ${whatsapp}"''; + in + { + Type = "simple"; + ExecStartPre = "${sleep} 10"; + ExecStart = exec; + Restart = "on-failure"; + RemainAfterExit = "yes"; + }; + Install = { + WantedBy = [ "default.target" ]; + }; + }; + }; + }; +} diff --git a/home/tigor/programs/zsh.nix b/home/tigor/programs/zsh.nix new file mode 100644 index 0000000..57658ad --- /dev/null +++ b/home/tigor/programs/zsh.nix @@ -0,0 +1,59 @@ +{ pkgs, ... }: + +{ + home.packages = with pkgs; [ + eza + bat + gojq + ]; + programs.zsh = { + enable = true; + autosuggestion.enable = true; + enableCompletion = false; + defaultKeymap = "emacs"; + dirHashes = { + docs = "$HOME/Documents"; + dl = "$HOME/Downloads"; + videos = "$HOME/Videos"; + pictures = "$HOME/Pictures"; + }; + shellAliases = { + ls = "eza -lah"; + cat = "bat"; + update = "sudo nixos-rebuild switch --flake $HOME/dotfiles"; + superupdate = "(cd $HOME/dotfiles && nix flake update && sudo nixos-rebuild switch --flake $HOME/dotfiles)"; + lg = "lazygit"; + du = "dust -H"; + uptest = "sudo nixos-rebuild test --flake $HOME/dotfiles"; + dry = "sudo nixos-rebuild dry-activate --flake $HOME/dotfiles"; + jq = "gojq"; + n = "neovide --fork"; + v = "nvim"; + }; + dotDir = ".config/zsh"; + history = { + expireDuplicatesFirst = true; + extended = true; + ignoreAllDups = true; + path = "$HOME/.local/share/zsh/zsh_history"; + save = 40000; + size = 40000; + }; + initExtraFirst = '' + _ZSH_COLOR_SCHEME_FILE=$HOME/.cache/wallust/sequences + if [ -f "$_ZSH_COLOR_SCHEME_FILE" ]; then + (cat "$_ZSH_COLOR_SCHEME_FILE" &) + fi + ''; + antidote = { + enable = true; + plugins = [ + # "zdharma-continuum/fast-syntax-highlighting kind:defer" + "zsh-users/zsh-autosuggestions kind:defer" + "zsh-users/zsh-history-substring-search kind:defer" + "zsh-users/zsh-completions" + "marlonrichert/zsh-autocomplete" + ]; + }; + }; +} diff --git a/home/tigor/secrets.nix b/home/tigor/secrets.nix new file mode 100644 index 0000000..ab6fdb4 --- /dev/null +++ b/home/tigor/secrets.nix @@ -0,0 +1,14 @@ +{ config, ... }: +{ + sops = { + defaultSopsFile = ../../secrets/secrets.yaml; + defaultSopsFormat = "yaml"; + age.keyFile = "/home/${config.home.username}/.config/sops/age/keys.txt"; + + secrets = { + "docker/config" = { + path = "${config.home.homeDirectory}/.docker/config.json"; + }; + }; + }; +} diff --git a/options/default.nix b/options/default.nix new file mode 100644 index 0000000..6cf154e --- /dev/null +++ b/options/default.nix @@ -0,0 +1,55 @@ +{ lib, ... }: +{ + imports = [ + ./programs.nix + ./hyprland.nix + ]; + options.profile = { + hostname = lib.mkOption { + type = lib.types.str; + }; + + android.enable = lib.mkEnableOption "android"; + avahi.enable = lib.mkEnableOption "avahi"; + bluetooth.enable = lib.mkEnableOption "bluetooth"; + docker.enable = lib.mkEnableOption "docker"; + flatpak.enable = lib.mkEnableOption "flatpak"; + gnome.enable = lib.mkEnableOption "gnome"; + kde.enable = lib.mkEnableOption "kde"; + networking.firewall.enable = lib.mkEnableOption "firewall"; + printing.enable = lib.mkEnableOption "printing"; + scanner.enable = lib.mkEnableOption "scanner"; + steam.enable = lib.mkEnableOption "steam"; + sway.enable = lib.mkEnableOption "sway"; + tofi.enable = lib.mkEnableOption "tofi"; + vial.enable = lib.mkEnableOption "vial"; + security.sudo = { + wheelNeedsPassword = lib.mkOption { + type = lib.types.bool; + default = true; + }; + }; + + security.sudo-rs = { + enable = lib.mkEnableOption "sudo-rs"; + wheelNeedsPassword = lib.mkEnableOption "wheel password"; + }; + + xkb = { + options = lib.mkOption { + type = lib.types.str; + default = "caps:ctrl_modifier,shift:both_capslock_cancel"; + }; + layout = lib.mkOption { + type = lib.types.str; + default = "us"; + }; + }; + + keyboard.language.japanese = lib.mkEnableOption "Japanese keyboard input"; + + firefox.enable = lib.mkEnableOption "firefox"; + + brightnessctl.enable = lib.mkEnableOption "brightnessctl"; + }; +} diff --git a/options/hyprland.nix b/options/hyprland.nix new file mode 100644 index 0000000..b0b52f7 --- /dev/null +++ b/options/hyprland.nix @@ -0,0 +1,108 @@ +{ lib, ... }: +let + types = lib.types; +in +{ + options.profile.hyprland = { + enable = lib.mkEnableOption "hyperland"; + settings = { + monitors = lib.mkOption { + type = with types; listOf str; + default = [ ]; + description = ''List of monitors hyprland should manage''; + example = ''[ ",preffered,auto,1" ]''; + }; + workspaces = lib.mkOption { + type = with types; listOf str; + default = [ ]; + description = ''List of workspaces to create''; + example = ''[ "1,default:true" "2" "3" "4" "5" "6" "7" "8" "9" "10" ]''; + }; + }; + + displayManager = lib.mkOption { + type = lib.types.enum [ "sddm" "tuigreet" ]; + default = "tuigreet"; + }; + + swayosd.display = lib.mkOption { + type = lib.types.str; + default = "eDP-1"; + }; + waybar.persistent-workspaces = lib.mkOption { + type = lib.types.attrs; + default = { }; + description = ''List of hyprland workspaces to keep in waybar, in the format of { [monitor] = [workspace] }''; + example = '' + { + DP-1 = [ 1 2 3 4 5 6 7]; + DP-1 = [ 8 9 10 ]; + } + ''; + }; + + pyprland = { + wallpaper-dirs = lib.mkOption { + type = with types; listOf str; + default = [ ]; + description = ''List of directories to search for wallpapers''; + }; + }; + + dunst.monitor = lib.mkOption { + type = lib.types.str; + default = "0"; + }; + + wallust = { + backend = lib.mkOption { + type = lib.types.enum [ "full" "resized" "wal" "thumb" "fastresize" "kmeans" ]; + default = "kmeans"; + description = "How the image is parse, in order to get the colors"; + }; + colorSpace = lib.mkOption { + type = lib.types.enum [ "lab" "labmixed" "lch" "lchmixed" ]; + default = "lch"; + description = "What color space to use to produce and select the most prominent colors"; + }; + alpha = lib.mkOption { + type = lib.types.int; + default = 100; + }; + threshold = lib.mkOption { + type = lib.types.int; + default = 1; + }; + palette = lib.mkOption { + type = lib.types.enum [ + "dark" + "dark16" + "darkcomp" + "darkcomp16" + "light" + "light16" + "lightcomp" + "lightcomp16" + "harddark" + "harddark16" + "harddarkcomp" + "harddarkcomp16" + "softdark" + "softdark16" + "softdarkcomp" + "softdarkcomp16" + "softlight" + "softlight16" + "softlightcomp" + "softlightcomp16" + ]; + default = "dark"; + description = ''Use the most prominent colors in a way that makes sense. A Scheme color palette.''; + }; + checkContrast = lib.mkOption { + type = lib.types.bool; + default = true; + }; + }; + }; +} diff --git a/options/programs.nix b/options/programs.nix new file mode 100644 index 0000000..920930a --- /dev/null +++ b/options/programs.nix @@ -0,0 +1,35 @@ +{ lib, ... }: +{ + options.profile = { + discord = { + enable = lib.mkEnableOption "discord"; + autostart = lib.mkEnableOption "discord autostart"; + window_rule = lib.mkOption { + type = lib.types.str; + default = "workspace 7 silent,class:(discord)"; + }; + }; + + slack = { + enable = lib.mkEnableOption "slack"; + autostart = lib.mkEnableOption "slack autostart"; + window_rule = lib.mkOption { + type = lib.types.str; + default = "workspace 6 silent,class:(Slack)"; + }; + }; + + whatsapp = { + enable = lib.mkEnableOption "whatsapp"; + autostart = lib.mkEnableOption "whatsapp autostart"; + window_rule = lib.mkOption { + type = lib.types.str; + default = "workspace 5 silent,class:(whatsapp-for-linux)"; + }; + }; + + syncthing.enable = lib.mkEnableOption "syncthing"; + + obs.enable = lib.mkEnableOption "obs"; + }; +} diff --git a/profiles/castle.nix b/profiles/castle.nix new file mode 100644 index 0000000..8dbe402 --- /dev/null +++ b/profiles/castle.nix @@ -0,0 +1,59 @@ +{ ... }: +let + primaryMonitor = "AOC U34G3G3R3 QXVP2JA000099"; + secondaryMonitor = "ViewSonic Corporation VX3276-QHD V9W204243765"; +in +{ + imports = [ + ../options + ]; + + profile = { + hostname = "castle"; + + hyprland = { + enable = true; + settings = { + monitors = [ + "desc:${primaryMonitor},3440x1440@165,0x0,1" + "desc:${secondaryMonitor},2560x1440@75,440x-1440,1" + ]; + workspaces = [ + "1, monitor:desc:${primaryMonitor}, default:true" + "2, monitor:desc:${primaryMonitor}" + "3, monitor:desc:${primaryMonitor}" + "4, monitor:desc:${primaryMonitor}" + "5, monitor:desc:${primaryMonitor}" + "6, monitor:desc:${primaryMonitor}" + "7, monitor:desc:${primaryMonitor}" + "8, monitor:desc:${secondaryMonitor}, default:true" + "9, monitor:desc:${secondaryMonitor}" + "10, monitor:desc:${secondaryMonitor}" + ]; + }; + waybar.persistent-workspaces = { + DP-1 = [ 1 2 3 4 5 6 7 ]; + DP-2 = [ 8 9 10 ]; + }; + pyprland.wallpaper-dirs = [ "/nas/redmage/images/windows" ]; + wallust.alpha = 80; + swayosd.display = "DP-1"; + dunst.monitor = "1"; + }; + discord.enable = true; + slack.enable = true; + whatsapp.enable = true; + obs.enable = true; + avahi.enable = true; + steam.enable = true; + scanner.enable = true; + vial.enable = true; + printing.enable = true; + + firefox.enable = true; + + security.sudo.wheelNeedsPassword = false; + + keyboard.language.japanese = true; + }; +} diff --git a/profiles/fort.nix b/profiles/fort.nix new file mode 100644 index 0000000..b8b8006 --- /dev/null +++ b/profiles/fort.nix @@ -0,0 +1,45 @@ +{ ... }: +{ + imports = [ + ../options + ]; + + profile = { + hostname = "fort"; + hyprland = { + enable = true; + settings = { + monitors = [ + ",preferred,auto,1" + ]; + workspaces = [ + "1,default:true" + "2" + "3" + "4" + "5" + "6" + "7" + "8" + "9" + "10" + ]; + }; + waybar.persistent-workspaces = { + eDP-1 = [ 1 2 3 4 5 6 7 8 9 10 ]; + }; + pyprland.wallpaper-dirs = [ "/home/tigor/Syncthing/Redmage/Laptop-Kerja" ]; + wallust.alpha = 80; + }; + discord.enable = true; + slack.enable = true; + whatsapp.enable = true; + syncthing.enable = true; + bluetooth.enable = true; + + firefox.enable = true; + + brightnessctl.enable = true; + keyboard.language.japanese = true; + }; +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..e58abbc --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,29 @@ +gnome-keyring: + tigor: ENC[AES256_GCM,data:fUJzIUburewNo6eSLdk0d4RJuL0XIWc=,iv:4pVbLT91IoS6XDEOd9jg4GQkVpQxYNasUeqv2otMgT8=,tag:aSFQKgu7N4p/73omC0wqNw==,type:str] +smb: + secrets: ENC[AES256_GCM,data:DKG6wjW/gBLX4cqisodnCX5OO6vVMQFerlAzlvW434xLQjHfn/SyTr3D/8GOSsMO,iv:4Qqdg2bDzNeCNeLifySfxwN/rA+qcAG0JSjt8ByFG/o=,tag:ALOoJ7h3EtjRIHskBfIouA==,type:str] +spotify: + username: ENC[AES256_GCM,data:7uYX5Co=,iv:zc03i9P/nX6hIe/SfUulH2T3BkxD/1xiqG2izmaJbho=,tag:/djGWrxvsG9L5x3vHc9TwQ==,type:str] + password: ENC[AES256_GCM,data:Yf2NCLuXVd28kPCHLLc=,iv:Ip4tAMOW5h8TPKavB7pTMt/ojtCq1wxw3Syhey4dGQI=,tag:b2FGiXAo66S6goiH43NQBA==,type:str] +docker: + config: ENC[AES256_GCM,data:zVV89tPNeaJUHHGVZjFtfps1KRiVa6/+FEpmaHTp5oy9KcNG/AOO75bypW2jzoRjaCigFzPElzSYZidD7Nt1x6XSzAT+y/YrDRosWUBqadnm/5U4DAP3HfLT9AuTzBCd/qNN3GZvdzXO+SLWpZszcL99V1JUOYLgU4fnQ7bS59ilMqKco0YJsohPcDZHyOIQiKRaPP8HmsxjBtlMzjWnqho4JUMQRT/2jO6wQiJ2dwD+5WR3EFWXcmGAhmhTISHjoMWUnK0iyYe0miVMVAKDgFEN4LKYaQMDFjU=,iv:hsQB+woy8NZYxFI5ZVtWyV9eJQVyNbNfLDS8Jho1tmk=,tag:MeWjOkLOUuMWBWE+2QfJCw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1kruum2varzua7w5n6n52vhwyek2arc685rhcwt0u7k2jf5mecsjslkl9ll + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiOGR4ejNva1pVTy9tTmlx + R095ZDJDczVYN3kvK1ZjQkQybDREemtiR1drCkRSclhTdzh5V29rbU5TYW82S1ZO + a2VsUDAyKzhIWU1ZZnJUdU04V0U0U1EKLS0tIEdLS3phVitrb2FHa3RRS1FoTXNH + UFFON2V5UWp1UUpETzZNSnVJdk5GcWsKupkOEN8OI/EOeu4Kkjo/SNhxMw2pa/gs + DzlsQRvytwCvAtr7zqHJvS6oeWlyjbirAHlpSzNS4QcqtbtK3mHC/Q== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-05-27T05:11:18Z" + mac: ENC[AES256_GCM,data:AFMJxL0TX2TienR+8Th4gPLV+FpeFJGFi81LLek8r1KKj5EEnDqCUyytPnDhBTEXCGnNJ7kYxoSy0qrrku6OuLLIknY5WxQXbuvqoP4t5NEkPdoaZFd9f+tuuwjKM87XhaxCjjlJxFImRaJJQOMY0aIp2rUkgvjhhTzwU2RCc+o=,iv:VXF1nH3Yt05BsNzN5sXy9CdDk43sFdVDEEy5sdl+RTs=,tag:+ls+k+jQuIO2+jbWJ+zVWQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/system/default.nix b/system/default.nix new file mode 100644 index 0000000..a8a0d72 --- /dev/null +++ b/system/default.nix @@ -0,0 +1,73 @@ +{ hardware-configuration, profile-path, config, ... }: +{ + imports = [ + profile-path + hardware-configuration + ./modules + ./programs.nix + ./user.nix + ./keyboard.nix + ]; + + security.sudo = + let + cfg = config.profile.security.sudo; + in + { + wheelNeedsPassword = cfg.wheelNeedsPassword; + extraConfig = '' + Defaults timestamp_timeout=30 + Defaults timestamp_type=global + ''; + }; + networking.hostName = config.profile.hostname; + + + nixpkgs.config.allowUnfree = true; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.extraOptions = '' + http-connections = 8 + connect-timeout = 5 + ''; + + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 7d"; + }; + + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "id_ID.UTF-8"; + LC_IDENTIFICATION = "id_ID.UTF-8"; + LC_MEASUREMENT = "id_ID.UTF-8"; + LC_MONETARY = "id_ID.UTF-8"; + LC_NAME = "id_ID.UTF-8"; + LC_NUMERIC = "id_ID.UTF-8"; + LC_PAPER = "id_ID.UTF-8"; + LC_TELEPHONE = "id_ID.UTF-8"; + LC_TIME = "id_ID.UTF-8"; + }; + + time.timeZone = "Asia/Jakarta"; + + documentation.man = { + man-db.enable = false; + generateCaches = true; + mandoc.enable = true; + }; + + system.stateVersion = "23.11"; # Did you read the comment? + + systemd.services.decrypt-sops = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = ''/run/current-system/activate''; + Type = "oneshot"; + Restart = "on-failure"; # because oneshot + RestartSec = "10s"; + }; + }; +} diff --git a/system/keyboard.nix b/system/keyboard.nix new file mode 100644 index 0000000..f46b549 --- /dev/null +++ b/system/keyboard.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.keyboard; +in +lib.mkMerge [ + { + i18n.inputMethod = { + enabled = "fcitx5"; + fcitx5.waylandFrontend = true; + }; + } + { + i18n.inputMethod = lib.mkIf cfg.language.japanese ({ + fcitx5.addons = with pkgs; [ + fcitx5-mozc + fcitx5-gtk + ]; + }); + } + { + environment.variables = lib.mkIf (config.i18n.inputMethod.enabled == "fcitx5") { + # Integration with some tools and binaries like kitty. + GLFW_IM_MODULE = "ibus"; + }; + } +] diff --git a/system/modules/android.nix b/system/modules/android.nix new file mode 100644 index 0000000..297b3a3 --- /dev/null +++ b/system/modules/android.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.android; +in +{ + config = lib.mkIf cfg.enable { + programs.adb.enable = true; + environment.systemPackages = with pkgs; [ + androidenv.androidPkgs_9_0.platform-tools + ]; + }; +} diff --git a/system/modules/audio.nix b/system/modules/audio.nix new file mode 100644 index 0000000..67cae37 --- /dev/null +++ b/system/modules/audio.nix @@ -0,0 +1,19 @@ +{ ... }: +{ + # Enable sound with pipewire. + # sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # If you want to use JACK applications, uncomment this + #jack.enable = true; + + # use the example session manager (no others are packaged yet so this is enabled by default, + # no need to redefine it in your config for now) + #media-session.enable = true; + }; +} diff --git a/system/modules/avahi.nix b/system/modules/avahi.nix new file mode 100644 index 0000000..f3c2a58 --- /dev/null +++ b/system/modules/avahi.nix @@ -0,0 +1,20 @@ +# Avahi is service discovery service. Depending on environment +# this may preferred to be disabled. + +{ config, lib, ... }: +let + cfg = config.profile.avahi; +in +{ + config = lib.mkIf cfg.enable { + services.avahi = { + enable = true; + nssmdns4 = true; + publish = { + enable = true; + addresses = true; + userServices = true; + }; + }; + }; +} diff --git a/system/modules/bluetooth.nix b/system/modules/bluetooth.nix new file mode 100644 index 0000000..1edf5a8 --- /dev/null +++ b/system/modules/bluetooth.nix @@ -0,0 +1,13 @@ +{ config, lib, ... }: +let + cfg = config.profile.bluetooth; +in +{ + config = lib.mkIf cfg.enable { + hardware.bluetooth = { + enable = true; + powerOnBoot = true; + }; + services.blueman.enable = true; + }; +} diff --git a/system/modules/boot_loader.nix b/system/modules/boot_loader.nix new file mode 100644 index 0000000..dabe5f9 --- /dev/null +++ b/system/modules/boot_loader.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + boot.loader = { + efi = { + efiSysMountPoint = "/boot"; + canTouchEfiVariables = true; + }; + grub = { + enable = true; + efiSupport = true; + useOSProber = true; + device = "nodev"; # used nodev because of efi support + }; + }; +} diff --git a/system/modules/brightnessctl.nix b/system/modules/brightnessctl.nix new file mode 100644 index 0000000..ef84f5d --- /dev/null +++ b/system/modules/brightnessctl.nix @@ -0,0 +1,9 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.brightnessctl; +in +{ + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.brightnessctl ]; + }; +} diff --git a/system/modules/default.nix b/system/modules/default.nix new file mode 100644 index 0000000..ee3ab51 --- /dev/null +++ b/system/modules/default.nix @@ -0,0 +1,24 @@ +{ ... }: +{ + imports = [ + ./android.nix + ./audio.nix + ./avahi.nix + ./brightnessctl.nix + ./flatpak.nix + ./gnome.nix + ./kde.nix + ./bluetooth.nix + ./boot_loader.nix + ./docker.nix + ./sops.nix + ./font.nix + ./hyprland.nix + ./networking.nix + ./printing.nix + ./scanner.nix + ./steam.nix + ./sudo.nix + ./vial.nix + ]; +} diff --git a/system/modules/docker.nix b/system/modules/docker.nix new file mode 100644 index 0000000..15ebe57 --- /dev/null +++ b/system/modules/docker.nix @@ -0,0 +1,9 @@ +{ config, lib, ... }: +let + cfg = config.profile.docker; +in +{ + config = lib.mkIf cfg.enable { + virtualisation.docker.enable = true; + }; +} diff --git a/system/modules/flatpak.nix b/system/modules/flatpak.nix new file mode 100644 index 0000000..464acc4 --- /dev/null +++ b/system/modules/flatpak.nix @@ -0,0 +1,55 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.profile.flatpak; +in +{ + config = lib.mkIf cfg.enable { + # Allow flatpak to access fonts + fonts.fontDir.enable = true; + + services.flatpak.enable = true; + # system.fsPackages = [ pkgs.bindfs ]; + + # Allows user installed fonts to be accessed by flatpak + # fileSystems = + # let + # mkRoSymBind = path: { + # device = path; + # fsType = "fuse.bindfs"; + # options = [ "ro" "resolve-symlinks" "x-gvfs-hide" ]; + # }; + # aggregatedFonts = pkgs.buildEnv { + # name = "system-fonts"; + # paths = config.fonts.packages; + # pathsToLink = [ "/share/fonts" ]; + # }; + # in + # { + # # Create an FHS mount to support flatpak host icons/fonts + # "/usr/share/icons" = mkRoSymBind (config.system.path + "/share/icons"); + # "/usr/share/fonts" = mkRoSymBind (aggregatedFonts + "/share/fonts"); + # }; + + xdg.portal = { + enable = true; + xdgOpenUsePortal = true; + # extraPortals = with pkgs; [ + # # xdg-desktop-portal-gtk + # # xdg-desktop-portal-kde + # # xdg-desktop-portal-gnome + # ]; + }; + + # Auto update flatpak every boot with systemd + # systemd.services.flatpak-update = { + # wantedBy = [ "multi-user.target" ]; + # after = [ "network-online.target" ]; + # wants = [ "network-online.target" ]; + # description = "Auto update flatpak every boot after network is online"; + # serviceConfig = { + # Type = "oneshot"; + # ExecStart = ''${pkgs.flatpak}/bin/flatpak update --assumeyes --noninteractive --system''; + # }; + # }; + }; +} diff --git a/system/modules/font.nix b/system/modules/font.nix new file mode 100644 index 0000000..a9db98d --- /dev/null +++ b/system/modules/font.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: +{ + fonts = { + packages = with pkgs; + [ + # icon fonts + material-design-icons + + # normal fonts + noto-fonts + noto-fonts-cjk + noto-fonts-emoji + noto-fonts-color-emoji + + # nerdfonts + (nerdfonts.override { + fonts = [ "FiraCode" "JetBrainsMono" "Iosevka" ]; + }) + ]; + + # use fonts specified by user rather than default ones + enableDefaultPackages = false; + + # user defined fonts + # the reason there's Noto Color Emoji everywhere is to override DejaVu's + # B&W emojis that would sometimes show instead of some Color emojis + fontconfig.defaultFonts = { + serif = [ "Noto Serif" "Noto Color Emoji" ]; + sansSerif = [ "Noto Sans" "Noto Color Emoji" ]; + monospace = [ "JetBrainsMono Nerd Font" "Noto Color Emoji" ]; + emoji = [ "Noto Color Emoji" ]; + }; + }; +} diff --git a/system/modules/gnome.nix b/system/modules/gnome.nix new file mode 100644 index 0000000..6fdf56c --- /dev/null +++ b/system/modules/gnome.nix @@ -0,0 +1,20 @@ +{ config, lib, ... }: +let + cfg = config.profile.gnome; +in +{ + config = lib.mkIf cfg.enable { + services.xserver = { + enable = true; + displayManager = { + gdm = { + enable = true; + wayland = true; + }; + defaultSession = "gnome"; + }; + desktopManager.gnome.enable = true; + }; + services.gnome.gnome-browser-connector.enable = true; + }; +} diff --git a/system/modules/hyprland.nix b/system/modules/hyprland.nix new file mode 100644 index 0000000..1e97b5b --- /dev/null +++ b/system/modules/hyprland.nix @@ -0,0 +1,106 @@ +{ inputs, config, lib, pkgs, ... }: +let + cfg = config.profile.hyprland; + hyprlandPkg = inputs.hyprland.packages."${pkgs.system}".hyprland; +in +{ + config = lib.mkIf cfg.enable { + programs.thunar = { + enable = true; + plugins = with pkgs.xfce; [ + thunar-volman + thunar-archive-plugin + ]; + }; + programs.xfconf.enable = true; + programs.hyprland = { + enable = true; + package = hyprlandPkg; + xwayland.enable = true; + }; + services.gvfs.enable = true; # Mount, trash, and other functionalities + services.tumbler.enable = true; # Thumbnail support for images + + environment = { + sessionVariables = { + NIXOS_OZONE_WL = "1"; + }; + systemPackages = with pkgs; [ + # Thunar Extended Support + webp-pixbuf-loader # webp images + poppler # .pdf filees + ffmpegthumbnailer # video thumbnailer + mcomix # comicbook archives + gwenview + + # Hyprland Programs + meson + wayland-protocols + wayland-utils + wl-clipboard + wlroots + networkmanagerapplet + dunst + libnotify + + gnome.gnome-keyring + gnome.seahorse + + greetd.tuigreet + + libappindicator-gtk2 + libappindicator + catppuccin-sddm + ]; + }; + + fonts.packages = with pkgs; [ + nerdfonts + meslo-lgs-nf + font-awesome + roboto + ]; + + nixpkgs.overlays = [ + (self: super: { + waybar = super.waybar.overrideAttrs (oldAttrs: { + mesonFlags = oldAttrs.mesonFlags ++ [ "-Dexperimental=true" ]; + }); + }) + ]; + + services.dbus.enable = true; + xdg.portal = { + enable = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-gtk + ]; + }; + + programs.file-roller.enable = true; + + services.greetd = lib.mkIf (cfg.displayManager == "tuigreet") { + enable = true; + restart = true; + settings = { + terminal = { + vt = 5; + }; + default_session = { + command = ''tuigreet --remember --cmd "dbus-run-session Hyprland"''; + user = "tigor"; + }; + }; + }; + + services.displayManager.sddm = lib.mkIf (cfg.displayManager == "sddm") { + enable = true; + wayland.enable = true; + theme = "catppuccin-mocha"; + }; + + xdg.portal.xdgOpenUsePortal = true; + + services.libinput.enable = true; + }; +} diff --git a/system/modules/kde.nix b/system/modules/kde.nix new file mode 100644 index 0000000..97b1843 --- /dev/null +++ b/system/modules/kde.nix @@ -0,0 +1,37 @@ +{ pkgs, config, lib, ... }: +let + cfg = config.profile.kde; +in +{ + config = lib.mkIf cfg.enable { + # Enable the X11 windowing system. + services.xserver.enable = true; + + services.xserver.desktopManager.plasma5.enable = true; + services.xserver.displayManager = { + sddm.enable = true; + defaultSession = "plasmawayland"; + }; + + environment.systemPackages = with pkgs; [ + catppuccin-kde + catppuccin-cursors + catppuccin-sddm-corners + plasma-browser-integration + kwin-dynamic-workspaces + libsForQt5.bismuth + haruna + ]; + + environment.etc."chromium/native-messaging-hosts/org.kde.plasma.browser_integration.json".source = + "${pkgs.plasma-browser-integration}/etc/chromium/native-messaging-hosts/org.kde.plasma.browser_integration.json"; + + # Configure keymap in X11 + services.xserver = { + layout = "us"; + xkbVariant = ""; + }; + + programs.kdeconnect.enable = true; + }; +} diff --git a/system/modules/networking.nix b/system/modules/networking.nix new file mode 100644 index 0000000..c222252 --- /dev/null +++ b/system/modules/networking.nix @@ -0,0 +1,8 @@ +{ config, ... }: +{ + networking.networkmanager.enable = true; + networking.extraHosts = '' + 192.168.50.217 gitlab.bareksa.com + ''; + networking.firewall.enable = config.profile.networking.firewall.enable; +} diff --git a/system/modules/printing.nix b/system/modules/printing.nix new file mode 100644 index 0000000..901db66 --- /dev/null +++ b/system/modules/printing.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.printing; +in +{ + config = lib.mkIf cfg.enable { + services.printing = { + enable = true; + drivers = [ pkgs.brlaser ]; # Brother Laser Printer + }; + }; +} diff --git a/system/modules/scanner.nix b/system/modules/scanner.nix new file mode 100644 index 0000000..6c58b2f --- /dev/null +++ b/system/modules/scanner.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.scanner; +in +{ + config = lib.mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + skanlite + ]; + hardware.sane = { + enable = true; + brscan4.enable = true; # Brother Scanner + extraBackends = with pkgs; [ + sane-airscan + ]; + }; + }; +} diff --git a/system/modules/sops.nix b/system/modules/sops.nix new file mode 100644 index 0000000..61c1201 --- /dev/null +++ b/system/modules/sops.nix @@ -0,0 +1,24 @@ +{ pkgs, ... }: +let + owner = "tigor"; +in +{ + environment.systemPackages = with pkgs; [ + age + sops + ]; + + sops = { + defaultSopsFile = ../../secrets/secrets.yaml; + defaultSopsFormat = "yaml"; + age.keyFile = "/home/${owner}/.config/sops/age/keys.txt"; + + secrets = { + "smb/secrets" = { inherit owner; }; + "docker/config" = { + inherit owner; + path = "/home/${owner}/.docker/config.json"; + }; + }; + }; +} diff --git a/system/modules/steam.nix b/system/modules/steam.nix new file mode 100644 index 0000000..394d1ba --- /dev/null +++ b/system/modules/steam.nix @@ -0,0 +1,13 @@ +{ config, lib, ... }: +let + cfg = config.profile.steam; +in +{ + config = lib.mkIf cfg.enable { + programs.steam = { + enable = true; + remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play + dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server + }; + }; +} diff --git a/system/modules/sudo.nix b/system/modules/sudo.nix new file mode 100644 index 0000000..574b69a --- /dev/null +++ b/system/modules/sudo.nix @@ -0,0 +1,13 @@ +{ config, lib, ... }: +let + cfg = config.profile.security.sudo-rs; +in +{ + config = lib.mkIf cfg.enable { + security.sudo.enable = false; + security.sudo-rs = { + enable = true; + wheelNeedsPassword = cfg.wheelNeedsPassword; + }; + }; +} diff --git a/system/modules/sway.nix b/system/modules/sway.nix new file mode 100644 index 0000000..a831798 --- /dev/null +++ b/system/modules/sway.nix @@ -0,0 +1,117 @@ +{ pkgs, ... }: +let + dbus-sway-environment = pkgs.writeTextFile { + name = "dbus-sway-environment"; + destination = "/bin/dbus-sway-enviroment"; + executable = true; + + text = '' + dbus-update-activation-enviroment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway + systemctl --user stop pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr + systemctl --user start pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr + ''; + }; + + configure-gtk = pkgs.writeTextFile { + name = "configure-gtk"; + destination = "/bin/configure/-gtk"; + executable = true; + text = + let + schema = pkgs.gsettings-desktop-schemas; + datadir = "${schema}/share/gsetting-schemas/${schema.name}"; + in + '' + export XDG_DATA_DIRS=${datadir}:$XDG_DATA_DIRS + gnome_schema=org.gnome.desktop.interface + gsettings set $gnome_schema gtk-theme 'WhiteSur-dark' + gsettings set $gnome_schema cursor-theme 'capitaine-cursors-white' + ''; + }; + + gnome-keyring-greetd-integration = pkgs.writeTextFile { + name = "gnome-keyring-greetd-integration"; + destination = "/etc/pam.d/greetd"; + text = '' + #%PAM-1.0 + + auth required pam_securetty.so + auth requisite pam_nologin.so + auth include system-local-login + auth optional pam_gnome_keyring.so + account include system-local-login + session include system-local-login + session optional pam_gnome_keyring.so auto_start + ''; + }; +in +{ + programs.light.enable = true; + users.users.tigor.extraGroups = [ "video" ]; + + environment.systemPackages = with pkgs; [ + dbus-sway-environment + configure-gtk + gnome-keyring-greetd-integration + + alacritty + sway + wayland + xdg-utils + glib + whitesur-icon-theme + grim + slurp + wl-clipboard + capitaine-cursors + swayfx + ]; + + services.dbus.enable = true; + + xdg.portal = { + enable = true; + wlr.enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + }; + + programs.sway = { + enable = true; + wrapperFeatures.gtk = true; + }; + + # programs.regreet.enable = true; + # login manager + services.greetd = { + enable = true; + settings = { + default_session = { + command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time -r --cmd ${pkgs.swayfx}/bin/sway"; + user = "tigor"; + }; + terminal = { + vt = 7; + }; + }; + # # clear bootlogs when greetd starts + # serviceConfig = { + # Type = "idle"; + # StandardInput = "tty"; + # StandardOutput = "tty"; + # StandardError = "journal"; + # TTYReset = true; + # TTYVHangup = true; + # TTYVTDisallocate = true; + # }; + }; + + ### Securities + + # Allow swaylock to use PAM + security.pam.services.swaylock = { }; + security.polkit.enable = true; + + # Save passwords, etc like wifi passwords + services.gnome.gnome-keyring.enable = true; + programs.ssh.startAgent = true; +} diff --git a/system/modules/vial.nix b/system/modules/vial.nix new file mode 100644 index 0000000..54d38b4 --- /dev/null +++ b/system/modules/vial.nix @@ -0,0 +1,21 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.profile.vial; +in +{ + config = lib.mkIf cfg.enable { + services.udev.packages = with pkgs; [ + vial + via + ]; + + environment.systemPackages = with pkgs; [ + vial + via + ]; + + services.udev.extraRules = '' + KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{serial}=="*vial:f64c2b3c*", MODE="0660", GROUP="users", TAG+="uaccess", TAG+="udev-acl" + ''; + }; +} diff --git a/system/modules/wallpaper_yia9bmhvhhsc1.png b/system/modules/wallpaper_yia9bmhvhhsc1.png new file mode 100644 index 0000000..ff7c9e6 Binary files /dev/null and b/system/modules/wallpaper_yia9bmhvhhsc1.png differ diff --git a/system/programs.nix b/system/programs.nix new file mode 100644 index 0000000..ba6e976 --- /dev/null +++ b/system/programs.nix @@ -0,0 +1,29 @@ +{ inputs, pkgs, ... }: +{ + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + package = inputs.neovim-nightly-overlay.packages.${pkgs.system}.default; + }; + + environment.systemPackages = with pkgs; [ + git + neofetch + curl + wget + lm_sensors # for sensors command + nnn + killall + gnumake + sqlite + nurl + ]; + + environment.sessionVariables = { + LIBSQLITE = "${pkgs.sqlite.out}/lib/libsqlite3.so"; + }; + + programs.zsh.enable = true; +} diff --git a/system/user.nix b/system/user.nix new file mode 100644 index 0000000..49aa702 --- /dev/null +++ b/system/user.nix @@ -0,0 +1,21 @@ +{ pkgs, ... }: +let + user = "tigor"; + fullName = "Tigor Hutasuhut"; +in +{ + users.users.${user} = { + isNormalUser = true; + description = fullName; + extraGroups = [ "networkmanager" "wheel" "docker" "adbusers" "scanner" "lp" ]; + shell = pkgs.zsh; + }; + + users.groups.work = { + name = "work"; + gid = 5555; + members = [ user ]; + }; + + nix.settings.trusted-users = [ user ]; +}