diff --git a/nix/modules/darwin/cli-apps/neovim/default.nix b/nix/modules/darwin/cli-apps/neovim/default.nix new file mode 100644 index 0000000..1a6d42a --- /dev/null +++ b/nix/modules/darwin/cli-apps/neovim/default.nix @@ -0,0 +1,23 @@ +inputs @ { + options, + config, + lib, + pkgs, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.cli-apps.neovim; +in { + options.custom.cli-apps.neovim = with types; { + enable = mkBoolOpt false "Whether or not to enable neovim."; + }; + + config = mkIf cfg.enable { + programs.neovim = { + enable = true; + defaultEditor = true; + vimAlias = true; + }; + }; +} diff --git a/nix/modules/darwin/desktop/addons/skhd/default.nix b/nix/modules/darwin/desktop/addons/skhd/default.nix new file mode 100644 index 0000000..0ae5746 --- /dev/null +++ b/nix/modules/darwin/desktop/addons/skhd/default.nix @@ -0,0 +1,153 @@ +{ + lib, + pkgs, + config, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.desktop.addons.skhd; +in { + options.custom.desktop.addons.skhd = { + enable = mkEnableOption "skhd"; + }; + + config = mkIf cfg.enable { + launchd.user.agents.skhd.serviceConfig = { + StandardOutPath = "/tmp/skhd.log"; + StandardErrorPath = "/tmp/skhd.log"; + }; + services.skhd = { + enable = true; + skhdConfig = '' + # Default mode + :: default + + # Workspace focus + alt - 1 : yabai -m space --focus 1 + alt - 2 : yabai -m space --focus 2 + alt - 3 : yabai -m space --focus 3 + alt - 4 : yabai -m space --focus 4 + alt - 5 : yabai -m space --focus 5 + alt - 6 : yabai -m space --focus 6 + alt - 7 : yabai -m space --focus 7 + alt - 8 : yabai -m space --focus 8 + alt - 9 : yabai -m space --focus 9 + alt - 0 : yabai -m space --focus 10 + + alt - up : yabai -m space --focus 2 + alt - down : yabai -m space --focus (yabai -m query --spaces --display | jq 'map(select(."is-native-fullscreen" == true))[-1].index') + + # change focus between external displays (left and right) + ctrl + alt - left : yabai -m display --focus west + ctrl + alt - right : yabai -m display --focus east + + # Move windows to another workspace + ctrl + shift - 1 : yabai -m window --space 1 + ctrl + shift - 2 : yabai -m window --space 2 + ctrl + shift - 3 : yabai -m window --space 3 + ctrl + shift - 4 : yabai -m window --space 4 + ctrl + shift - 5 : yabai -m window --space 5 + ctrl + shift - 6 : yabai -m window --space 6 + ctrl + shift - 7 : yabai -m window --space 7 + ctrl + shift - 8 : yabai -m window --space 8 + ctrl + shift - 9 : yabai -m window --space 9 + ctrl + shift - 0 : yabai -m window --space 10 + + # Navigation + alt - h : yabai -m window --focus west + alt - j : yabai -m window --focus south + alt - k : yabai -m window --focus north + alt - l : yabai -m window --focus east + alt - left : yabai -m window --focus west + alt - down : yabai -m window --focus south + alt - up : yabai -m window --focus north + alt - right : yabai -m window --focus east + + # Close current window + alt - q : yabai -m window --close + + # Moving windows + shift + alt - h : yabai -m window --warp west + shift + alt - j : yabai -m window --warp south + shift + alt - k : yabai -m window --warp north + shift + alt - l : yabai -m window --warp east + + # Move floating window + shift + alt - h : yabai -m window --move rel:-20:0 + shift + alt - j : yabai -m window --move rel:0:20 + shift + alt - k : yabai -m window --move rel:0:-20 + shift + alt - l : yabai -m window --move rel:20:0 + + # Float/unfloat windows + shift + alt - space : yabai -m window --toggle float; \ + yabai -m window --grid 4:4:1:1:2:2 + + # Fullscreen + alt - f : yabai -m window --toggle zoom-fullscreen + ctrl + shift - f : yabai -m window --toggle native-fullscreen + + # Resize mode + :: resize @ + + ## Enter resize mode + alt - r ; resize + + ## Leave resize mode + resize < escape ; default + + ## Resize mode key bindings + resize < h : \ + yabai -m window --resize left:-20:0 ; \ + yabai -m window --resize right:-20:0 + resize < j : \ + yabai -m window --resize bottom:0:20 ; \ + yabai -m window --resize top:0:20 + resize < k : \ + yabai -m window --resize top:0:-20 ; \ + yabai -m window --resize bottom:0:-20 + resize < l : \ + yabai -m window --resize right:20:0 ; \ + yabai -m window --resize left:20:0 + + # Resize windows + ctrl + alt - h : \ + yabai -m window --resize left:-20:0 ; \ + yabai -m window --resize right:-20:0 + + ctrl + alt - j : \ + yabai -m window --resize bottom:0:20 ; \ + yabai -m window --resize top:0:20 + + ctrl + alt - k : \ + yabai -m window --resize top:0:-20 ; \ + yabai -m window --resize bottom:0:-20 + + ctrl + alt - l : \ + yabai -m window --resize right:20:0 ; \ + yabai -m window --resize left:20:0 + + # Toggle window split type with semicolon + ctrl + alt - e : yabai -m window --toggle split + + # Balance size of windows + ctrl + alt - 0 : yabai -m space --balance + + # Workspace init + ctrl + shift - n : yabai -m space --create + ctrl + shift - d : yabai -m space --destroy + + # Applications + alt - x : /Users/sab/.nix-profile/bin/kitty + ctrl + alt - b: /Applications/Firefox.App/Contents/MacOS/firefox + + # -- Starting/Stopping/Restarting Yabai -- + + # stop/start/restart yabai + skhd + ctrl + alt - q : launchctl stop org.nixos.yabai; launchctl stop org.nixos.skhd + ctrl + alt - s : launchctl start org.nixos.yabai; launchctl start org.nixos.skhd + ctrl + alt - r : launchctl stop org.nixos.yabai; launchctl stop org.nixos.skhd; launchctl start org.nixos.yabai; launchctl start org.nixos.skhd + ''; + }; + }; +} diff --git a/nix/modules/darwin/desktop/addons/spacebar/default.nix b/nix/modules/darwin/desktop/addons/spacebar/default.nix new file mode 100644 index 0000000..ce1d5b2 --- /dev/null +++ b/nix/modules/darwin/desktop/addons/spacebar/default.nix @@ -0,0 +1,49 @@ +{ + lib, + pkgs, + config, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.desktop.addons.spacebar; +in { + options.custom.desktop.addons.spacebar = { + enable = mkEnableOption "Spacebar"; + }; + + config = mkIf cfg.enable { + services.spacebar = { + enable = true; + package = pkgs.spacebar; + + config = { + position = "top"; + display = "all"; + height = 32; + title = "on"; + spaces = "on"; + clock = "on"; + power = "off"; + + padding_left = 10; + padding_right = 10; + + spacing_left = 10; + spacing_right = 10; + + foreground_color = "0xffeceff4"; + background_color = "0xff1d2128"; + + text_font = ''"Hack Nerd Font Mono:Regular:14.0"''; + icon_font = ''"Hack Nerd Font Mono:Regular:20.0"''; + + # Shell entries apparently break the whole bar... + # https://github.com/cmacrae/spacebar/issues/104 + # right_shell_icon = ""; + # right_shell_command = ''"whoami"''; + # right_shell = "on"; + }; + }; + }; +} diff --git a/nix/modules/darwin/desktop/yabai/default.nix b/nix/modules/darwin/desktop/yabai/default.nix new file mode 100644 index 0000000..cb7f797 --- /dev/null +++ b/nix/modules/darwin/desktop/yabai/default.nix @@ -0,0 +1,104 @@ +{ + lib, + pkgs, + config, + ... +}: let + cfg = config.custom.desktop.yabai; + + inherit (lib) types mkEnableOption mkIf; + inherit (lib.custom) mkOpt enabled; +in { + options.custom.desktop.yabai = { + enable = mkEnableOption "Yabai"; + enable-scripting-addition = mkOpt types.bool true "Whether to enable the scripting addition for Yabai. (Requires SIP to be disabled)"; + }; + + config = mkIf cfg.enable { + custom.desktop.addons = { + skhd = enabled; + spacebar = disabled; + }; + launchd.user.agents.yabai.serviceConfig = { + StandardOutPath = "/tmp/yabai.log"; + StandardErrorPath = "/tmp/yabai.log"; + }; + + services.yabai = { + enable = true; + enableScriptingAddition = true; + config = { + # Binary space partitioning layout + layout = "bsp"; + # When focusing a window, put the mouse at its center + mouse_follows_focus = "on"; + # Automatically focus the window under the mouse + focus_follows_mouse = "autoraise"; + # New window spawns to the right if vertical split, or bottom if + # horizontal split + window_placement = "second_child"; + # Disable opacity for windows + window_opacity = "off"; + # Padding added around the sides of a space + top_padding = 6; + bottom_padding = 6; + left_padding = 6; + right_padding = 6; + # Size of the gap that separates windows + window_gap = 6; + # Draw shadow for windows, window_border has been removed + window_shadow = "on"; + # Add padding for external status bar + external_bar = "all:0:26"; + }; + + extraConfig = '' + for _ in $(yabai -m query --spaces | jq '.[].index | select(. > 6)'); do + yabai -m space --destroy 7 + done + + function setup_space { + local idx="$1" + local name="$2" + local space= + echo "setup space $idx : $name" + + space=$(yabai -m query --spaces --space "$idx") + if [ -z "$space" ]; then + yabai -m space --create + fi + yabai -m space "$idx" --label "$name" + } + + setup_space 1 main + setup_space 2 web + setup_space 3 code + setup_space 4 social + setup_space 5 media + setup_space 6 other + + yabai -m rule --add app="^Safari$" space=2 + yabai -m rule --add app="^Firefox$" space=2 + yabai -m rule --add app="^Kitty$" space=3 + yabai -m rule --add app="^kitty$" space=3 + yabai -m rule --add app="^Telegram$" space=1 + yabai -m rule --add app="^Slack$" space=1 + yabai -m rule --add app="^Teams$" space=1 + yabai -m rule --add app="^Mail$" space=4 + yabai -m rule --add app="^Calendar$" space=4 + yabai -m rule --add app="^Music$" space=5 + + # Float system settings + yabai -m rule --add app="^(Terminal|Calculator|Software Update|Dictionary|VLC|System Preferences|System Settings|zoom.us|Photo Booth|Archive Utility)$" manage=off + yabai -m rule --add label="Finder" app="^Finder$" title="(Co(py|nnect)|Move|Info|Pref)" manage=off + yabai -m rule --add app="^System Information$" label="^About This Mac$" manage=off + yabai -m rule --add app="^Cisco AnyConnect Secure Mobility Client$" manage=off + yabai -m rule --add app="^Cisco$" manage=off + + # Load scripting addition + yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa" + sudo yabai --load-sa + ''; + }; + }; +} diff --git a/nix/modules/darwin/home/default.nix b/nix/modules/darwin/home/default.nix new file mode 100644 index 0000000..b17c2dd --- /dev/null +++ b/nix/modules/darwin/home/default.nix @@ -0,0 +1,46 @@ +{ + options, + config, + pkgs, + lib, + inputs, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.home; +in { + # imports = with inputs; [ + # home-manager.darwinModules.home-manager + # ]; + + options.custom.home = with types; { + file = + mkOpt attrs {} + "A set of files to be managed by home-manager's ."; + configFile = + mkOpt attrs {} + "A set of files to be managed by home-manager's ."; + extraOptions = mkOpt attrs {} "Options to pass directly to home-manager."; + homeConfig = mkOpt attrs {} "Final config for home-manager."; + }; + + config = { + custom.home.extraOptions = { + home.stateVersion = mkDefault "22.11"; + home.file = mkAliasDefinitions options.custom.home.file; + xdg.enable = true; + xdg.configFile = mkAliasDefinitions options.custom.home.configFile; + }; + + snowfallorg.user.${config.custom.user.name}.home.config = mkAliasDefinitions options.custom.home.extraOptions; + + home-manager = { + useUserPackages = true; + useGlobalPkgs = true; + + # users.${config.custom.user.name} = args: + # mkAliasDefinitions options.custom.home.extraOptions; + }; + }; +} diff --git a/nix/modules/darwin/nix/default.nix b/nix/modules/darwin/nix/default.nix new file mode 100644 index 0000000..789805a --- /dev/null +++ b/nix/modules/darwin/nix/default.nix @@ -0,0 +1,72 @@ +{ + options, + config, + pkgs, + lib, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.nix; +in { + options.custom.nix = with types; { + enable = mkBoolOpt true "Whether or not to manage nix configuration."; + package = mkOpt package pkgs.nixUnstable "Which nix package to use."; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + deploy-rs + nixfmt + nix-index + nix-prefetch-git + ]; + + nix = let + users = ["root" config.custom.user.name]; + in { + package = cfg.package; + + settings = { + experimental-features = "nix-command flakes"; + http-connections = 50; + warn-dirty = false; + log-lines = 50; + + # Large builds apparently fail due to an issue with darwin: + # https://github.com/NixOS/nix/issues/4119 + sandbox = false; + + # This appears to break on darwin + # https://github.com/NixOS/nix/issues/7273 + auto-optimise-store = false; + + allow-import-from-derivation = true; + + trusted-users = users; + allowed-users = users; + + # NOTE: This configuration is generated by nix-installer so I'm adding it here in + # case it becomes important. + extra-nix-path = "nixpkgs=flake:nixpkgs"; + build-users-group = "nixbld"; + }; + #// (lib.optionalAttrs config.custom.tools.direnv.enable { + # keep-outputs = true; + # keep-derivations = true; + #}); + + gc = { + automatic = true; + interval = {Day = 7;}; + options = "--delete-older-than 30d"; + user = config.custom.user.name; + }; + + # flake-utils-plus + generateRegistryFromInputs = true; + generateNixPathFromInputs = true; + linkInputs = true; + }; + }; +} diff --git a/nix/modules/darwin/services/nix-daemon/default.nix b/nix/modules/darwin/services/nix-daemon/default.nix new file mode 100644 index 0000000..44d5d1e --- /dev/null +++ b/nix/modules/darwin/services/nix-daemon/default.nix @@ -0,0 +1,18 @@ +{ + lib, + config, + ... +}: let + inherit (lib) types mkIf; + inherit (lib.custom) mkOpt enabled; + + cfg = config.custom.services.nix-daemon; +in { + options.custom.services.nix-daemon = { + enable = mkOpt types.bool true "Whether to enable the Nix daemon."; + }; + + config = mkIf cfg.enable { + services.nix-daemon = enabled; + }; +} diff --git a/nix/modules/darwin/suites/common/default.nix b/nix/modules/darwin/suites/common/default.nix new file mode 100644 index 0000000..3b6aa48 --- /dev/null +++ b/nix/modules/darwin/suites/common/default.nix @@ -0,0 +1,46 @@ +{ + options, + config, + lib, + pkgs, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.suites.common; +in { + options.custom.suites.common = with types; { + enable = mkBoolOpt false "Whether or not to enable common configuration."; + }; + + config = mkIf cfg.enable { + programs.fish = enabled; + + custom = { + nix = enabled; + + # apps = { + # iterm2 = enabled; + # }; + + cli-apps = { + neovim = enabled; + }; + + # tools = { + # git = enabled; + # flake = enabled; + # }; + + system = { + fonts = enabled; + input = enabled; + interface = enabled; + }; + + # security = { + # gpg = enabled; + # }; + }; + }; +} diff --git a/nix/modules/darwin/suites/development/default.nix b/nix/modules/darwin/suites/development/default.nix new file mode 100644 index 0000000..36c26fb --- /dev/null +++ b/nix/modules/darwin/suites/development/default.nix @@ -0,0 +1,39 @@ +{ + options, + config, + lib, + pkgs, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.suites.development; +in { + options.custom.suites.development = with types; { + enable = + mkBoolOpt false + "Whether or not to enable common development configuration."; + }; + + config = mkIf cfg.enable { + custom = { + # apps = { + # vscode = enabled; + # }; + + tools = { + # at = enabled; + # direnv = enabled; + # go = enabled; + # http = enabled; + # k8s = enabled; + # node = enabled; + # titan = enabled; + # python = enabled; + # java = enabled; + }; + + # virtualisation = { podman = enabled; }; + }; + }; +} diff --git a/nix/modules/darwin/system/fonts/default.nix b/nix/modules/darwin/system/fonts/default.nix new file mode 100644 index 0000000..bf500c4 --- /dev/null +++ b/nix/modules/darwin/system/fonts/default.nix @@ -0,0 +1,37 @@ +{ + options, + config, + pkgs, + lib, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.system.fonts; +in { + options.custom.system.fonts = with types; { + enable = mkBoolOpt false "Whether or not to manage fonts."; + fonts = mkOpt (listOf package) [] "Custom font packages to install."; + }; + + config = mkIf cfg.enable { + environment.variables = { + # Enable icons in tooling since we have nerdfonts. + LOG_ICONS = "true"; + }; + + fonts = { + fontDir = enabled; + + fonts = with pkgs; + [ + noto-fonts + noto-fonts-cjk-sans + noto-fonts-cjk-serif + noto-fonts-emoji + (nerdfonts.override {fonts = ["JetBrainsMono" "CascadiaCode" "FiraCode"];}) + ] + ++ cfg.fonts; + }; + }; +} diff --git a/nix/modules/darwin/system/input/default.nix b/nix/modules/darwin/system/input/default.nix new file mode 100644 index 0000000..3162c43 --- /dev/null +++ b/nix/modules/darwin/system/input/default.nix @@ -0,0 +1,46 @@ +{ + options, + config, + pkgs, + lib, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.system.input; +in { + options.custom.system.input = with types; { + enable = mkEnableOption "macOS input"; + }; + + config = mkIf cfg.enable (mkMerge [ + { + system = { + # keyboard = { + # enableKeyMapping = true; + # remapCapsLockToEscape = true; + # }; + + # defaults = { + # ".GlobalPreferences" = { + # "com.apple.mouse.scaling" = "1"; + # }; + + # NSGlobalDomain = { + # AppleKeyboardUIMode = 3; + # ApplePressAndHoldEnabled = false; + + # KeyRepeat = 2; + # InitialKeyRepeat = 15; + + # NSAutomaticCapitalizationEnabled = false; + # NSAutomaticDashSubstitutionEnabled = false; + # NSAutomaticQuoteSubstitutionEnabled = false; + # NSAutomaticPeriodSubstitutionEnabled = false; + # NSAutomaticSpellingCorrectionEnabled = false; + # }; + # }; + }; + } + ]); +} diff --git a/nix/modules/darwin/system/interface/default.nix b/nix/modules/darwin/system/interface/default.nix new file mode 100644 index 0000000..8132885 --- /dev/null +++ b/nix/modules/darwin/system/interface/default.nix @@ -0,0 +1,36 @@ +{ + options, + config, + pkgs, + lib, + ... +}: +with lib; +with lib.custom; let + cfg = config.custom.system.interface; +in { + options.custom.system.interface = with types; { + enable = mkEnableOption "macOS interface"; + }; + + config = mkIf cfg.enable { + system.defaults = { + # dock.autohide = true; + + LaunchServices = { + LSQuarantine = false; + }; + + finder = { + AppleShowAllExtensions = true; + FXEnableExtensionChangeWarning = false; + _FXShowPosixPathInTitle = false; + }; + + # NSGlobalDomain = { + # _HIHideMenuBar = true; + # AppleShowScrollBars = "Always"; + # }; + }; + }; +} diff --git a/nix/modules/darwin/user/default.nix b/nix/modules/darwin/user/default.nix new file mode 100644 index 0000000..72271c2 --- /dev/null +++ b/nix/modules/darwin/user/default.nix @@ -0,0 +1,42 @@ +{ + lib, + config, + pkgs, + ... +}: let + inherit (lib) types mkIf mkDefault; + inherit (lib.custom) mkOpt; + + cfg = config.custom.user; + + is-linux = pkgs.stdenv.isLinux; + is-darwin = pkgs.stdenv.isDarwin; +in { + options.custom.user = { + name = mkOpt str "sab" "The name to use for the user account."; + fullName = mkOpt str "Sergei Bulavintsev" "The full name of the user."; + email = mkOpt str "bulavintsev.sergey@gmail.com" "The email of the user."; + }; + + config = { + users.users.${cfg.name} = { + # NOTE: Setting the uid here is required for another + # module to evaluate successfully since it reads + # `users.users.${custom.user.name}.uid`. + # uid = mkIf (cfg.uid != null) cfg.uid; + shell = pkgs.fish; + }; + + snowfallorg.user.${config.custom.user.name}.home.config = { + home = { + file = { + ".profile".text = '' + # The default file limit is far too low and throws an error when rebuilding the system. + # See the original with: ulimit -Sa + ulimit -n 4096 + ''; + }; + }; + }; + }; +} diff --git a/nix/systems/aarch64-darwin/mbp/default.nix b/nix/systems/aarch64-darwin/mbp/default.nix new file mode 100644 index 0000000..a5b0be3 --- /dev/null +++ b/nix/systems/aarch64-darwin/mbp/default.nix @@ -0,0 +1,21 @@ +{ + lib, + pkgs, + ... +}: +with lib.custom; { + custom = { + suites = { + common = enabled; + development = enabled; + }; + + desktop.yabai = enabled; + }; + + environment.systemPath = [ + "/opt/homebrew/bin" + ]; + + system.stateVersion = 4; +}