diff options
Diffstat (limited to 'modules/homeModules')
34 files changed, 2946 insertions, 0 deletions
diff --git a/modules/homeModules/alacritty.nix b/modules/homeModules/alacritty.nix new file mode 100644 index 0000000..3fcce6c --- /dev/null +++ b/modules/homeModules/alacritty.nix @@ -0,0 +1,29 @@ +{inputs, ...}: { + flake.homeModules.alacritty = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + alacritty.enable = lib.mkEnableOption "enable alacritty"; + }; + + config = lib.mkIf config.alacritty.enable { + programs.alacritty = { + enable = true; + settings = { + cursor = { + style = "Beam"; + thickness = 0.25; + }; + window = { + padding = { + x = 10; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/attachments/basecat.aseprite b/modules/homeModules/attachments/basecat.aseprite Binary files differnew file mode 100644 index 0000000..16caffd --- /dev/null +++ b/modules/homeModules/attachments/basecat.aseprite diff --git a/modules/homeModules/attachments/basecat.png b/modules/homeModules/attachments/basecat.png Binary files differnew file mode 100644 index 0000000..d202c64 --- /dev/null +++ b/modules/homeModules/attachments/basecat.png diff --git a/modules/homeModules/attachments/cat.png b/modules/homeModules/attachments/cat.png Binary files differnew file mode 100644 index 0000000..5657a78 --- /dev/null +++ b/modules/homeModules/attachments/cat.png diff --git a/modules/homeModules/attachments/hypr-scripts/bitwarden-float.sh b/modules/homeModules/attachments/hypr-scripts/bitwarden-float.sh new file mode 100755 index 0000000..7edd5f2 --- /dev/null +++ b/modules/homeModules/attachments/hypr-scripts/bitwarden-float.sh @@ -0,0 +1,21 @@ +windowtitlev2() { + IFS=',' read -r -a args <<< "$1" + args[0]="${args[0]#*>>}" + + if [[ ${args[1]} =~ "Extension: (Bitwarden Password Manager)" ]]; then + hyprctl --batch "\ + dispatch setfloating address:0x${args[0]}; \ + dispatch resizewindowpixel exact 20% 50%, address:0x${args[0]}; \ + dispatch centerwindow; \ + " + fi +} + +handle() { + case $1 in + windowtitlev2\>*) windowtitlev2 "$1" ;; + esac +} + +socat -U - UNIX-CONNECT:"/$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" \ + | while read -r line; do handle "$line"; done diff --git a/modules/homeModules/attachments/hypr-scripts/hshot.sh b/modules/homeModules/attachments/hypr-scripts/hshot.sh new file mode 100755 index 0000000..0d02b9c --- /dev/null +++ b/modules/homeModules/attachments/hypr-scripts/hshot.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +declare -a cmd + +usage() { + echo -e "-m | monitor\n-s | slurp\n-w | active window\n-c | add copy" +} + +monitor() { + cmd=("grim -o \"\$(hyprctl -j monitors | jq -r '.[] | select(.focused) | .name')\"") +} + +slurp() { + cmd=("grim -g \"\$(slurp)\"") +} + +window() { + cmd=("grim -g \"\$(hyprctl activewindow -j | jq -j '\"\(.at | .[0]),\(.at | .[1]) \(.size | .[0])x\(.size | .[1])\"')\"") +} + +copy() { + if [[ -n ${cmd[0]} ]]; then + cmd+=("- | wl-copy") + else + usage + fi +} + +while getopts ":mswc" opt; do + case ${opt} in + m) monitor;; + s) slurp;; + w) window;; + c) copy;; + *) usage + exit 1;; + esac +done + +if [[ -z $1 ]]; then + usage + exit 1 +fi + +bash -c "${cmd[*]}" diff --git a/modules/homeModules/attachments/hypr-scripts/switch-sink.py b/modules/homeModules/attachments/hypr-scripts/switch-sink.py new file mode 100755 index 0000000..aa7eec1 --- /dev/null +++ b/modules/homeModules/attachments/hypr-scripts/switch-sink.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import subprocess + +status = subprocess.run(["wpctl", "status"], stdout=subprocess.PIPE).stdout.decode('utf-8') +status_lines = status.split('\n') +sink_line = 0 +sinks = [] +sink_names = [] + +# Get sink line +for i in range(len(status_lines) - 1): + if 'Sinks:' in status_lines[i]: + sink_line = i + 1 + break + +# Find unused sinks +for line in status_lines[sink_line:]: + if line == ' │ ': + break + line = line.split('.') + nums = line[0] + name = line[1] + end_name = line[1].index('[') + sink = nums[2:].strip() + if nums[4] == '*': + continue + + sinks.append(sink) + sink_names.append(name[:end_name].strip()) + +if (len(sinks) == 0): + subprocess.run(["notify-send", "Pipewire sink", "No sinks to switch to"]) + exit(0) + +selected_sink = subprocess.run(["rofi", "-dmenu"], input="\n".join(sink_names), capture_output=True, text=True).stdout[:-1] + +if len(selected_sink) == 0: + exit(0) + +try: + next_sink = sink_names.index(selected_sink) +except Exception: + subprocess.run(["notify-send", "Pipewire sink", "Sink not found"]) + exit(1) + +subprocess.run(["wpctl", "set-default", sinks[next_sink]]) + +subprocess.run(["notify-send", "Pipewire sink", "Selected " + selected_sink]) diff --git a/modules/homeModules/attachments/hypr-scripts/toggle-tg.sh b/modules/homeModules/attachments/hypr-scripts/toggle-tg.sh new file mode 100755 index 0000000..44ed52d --- /dev/null +++ b/modules/homeModules/attachments/hypr-scripts/toggle-tg.sh @@ -0,0 +1,14 @@ +#!/bin/sh +TG_CLASS=org.telegram.desktop + +tg_workspace=$(hyprctl clients -j | jq -e ".[] | select((.class | contains(\"${TG_CLASS}\"))) | .workspace.id") +if [[ -z $tg_workspace ]]; then + telegram-desktop +elif [[ $tg_workspace -eq $(hyprctl activeworkspace -j | jq -e '.id') ]]; then + hyprctl dispatch pin class:$TG_CLASS + hyprctl dispatch movetoworkspacesilent special:magic,class:$TG_CLASS +else + hyprctl dispatch movetoworkspacesilent +0,class:$TG_CLASS + hyprctl dispatch pin class:$TG_CLASS + hyprctl dispatch focuswindow +fi diff --git a/modules/homeModules/attachments/hypr-scripts/toggle-vpn.sh b/modules/homeModules/attachments/hypr-scripts/toggle-vpn.sh new file mode 100755 index 0000000..8775f39 --- /dev/null +++ b/modules/homeModules/attachments/hypr-scripts/toggle-vpn.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +ROFI_CMD="rofi -dmenu -theme-str listview{enabled:false;} -p" +LOCAL_STORAGE=~/.local/share/toggle +TMP_PATH=/tmp/vpn-status +V2RAYA_URL="http://localhost:2017" + +DBUS_INTERFACE="com.vpn_status" +DBUS_MEMBER="StatusChanged" + +set_token() { + login=$(echo "" | $ROFI_CMD "Enter login > ") + password=$(echo "" | $ROFI_CMD "Enter password > " -theme-str 'entry {enabled: false;}') + response=$(curl -s -X POST \ + "${V2RAYA_URL}/api/login" \ + -d "{\"username\": \"${login}\", \"password\": \"${password}\"}") + + code=$(echo $response | jq -r ".code") + echo "${response}" | jq ".data.token" -r > "${LOCAL_STORAGE}/token" +} + +get_status() { + token=$1 + response=$(curl -s -X GET \ + "${V2RAYA_URL}/api/touch" \ + -H "Authorization: ${token}") + echo $response | jq ".data.running" -r +} + +toggle() { + token=$1 + method=$2 + response=$(curl -s -X ${method} \ + "${V2RAYA_URL}/api/v2ray" \ + -H "Authorization: ${token}") + code=$(echo $response | jq ".code" -r) + echo $response | jq ".data.running" -r +} + +check_status() { + case $(cat $TMP_PATH) in + true) + output='{"text": ""}' + ;; + *) + output='{"text": ""}' + ;; + esac + echo $output | jq --unbuffered --compact-output +} + + +if [[ ! -d "${LOCAL_STORAGE}" ]]; then + mkdir "${LOCAL_STORAGE}" +fi + +if [[ ! -e "${LOCAL_STORAGE}/token" ]]; then + touch "${LOCAL_STORAGE}/token" +fi + +TOKEN=$(cat "${LOCAL_STORAGE}/token") +if [[ -z "${TOKEN}" ]]; then + set_token + TOKEN=$(cat "${LOCAL_STORAGE}/token") +fi + +STATUS=$(get_status $TOKEN) + +if [[ $1 == "waybar" ]]; then + echo $STATUS > $TMP_PATH + check_status + + dbus-monitor --profile "interface='${DBUS_INTERFACE}',member='${DBUS_MEMBER}'" | + while read -r line; do + check_status + done +else + if [[ $STATUS == "true" ]]; then + NEW_STATUS=$(toggle $TOKEN DELETE) + else + NEW_STATUS=$(toggle $TOKEN POST) + fi + + if [[ $NEW_STATUS == "null" ]]; then + set_token + exit 0 + fi + + echo $NEW_STATUS > $TMP_PATH + dbus-send --type=signal / "${DBUS_INTERFACE}.${DBUS_MEMBER}" + + notify-send v2rayA "running: ${NEW_STATUS}" +fi diff --git a/modules/homeModules/attachments/rofi-theme.rasi b/modules/homeModules/attachments/rofi-theme.rasi new file mode 100644 index 0000000..bba4f6c --- /dev/null +++ b/modules/homeModules/attachments/rofi-theme.rasi @@ -0,0 +1,79 @@ +/******************************************************************************* + * SNITCHED FROM: + * User : LR-Tech + * Theme Repo : https://github.com/lr-tech/rofi-themes-collection + *******************************************************************************/ + +window { + location: center; + width: 480; + y-offset: -160; + border-radius: 7px; + + background-color: @bg0; +} + +inputbar { + spacing: 8px; + padding: 8px; + + background-color: @bg1; +} + +prompt, entry, element-icon, element-text { + vertical-align: 0.5; +} + +prompt { + text-color: @accent-color; +} + +textbox { + padding: 8px; + background-color: @bg1; +} + +listview { + padding: 4px 0; + lines: 8; + columns: 1; + + fixed-height: false; +} + +element { + padding: 8px; + spacing: 8px; +} + +element normal normal { + text-color: @fg0; +} + +element normal urgent { + text-color: @urgent-color; +} + +element normal active { + text-color: @accent-color; +} + +element selected { + text-color: @bg0; +} + +element selected normal, element selected active { + background-color: @accent-color; +} + +element selected urgent { + background-color: @urgent-color; +} + +element-icon { + size: 0.8em; +} + +element-text { + text-color: inherit; +} diff --git a/modules/homeModules/attachments/waybar-style.css b/modules/homeModules/attachments/waybar-style.css new file mode 100644 index 0000000..214c779 --- /dev/null +++ b/modules/homeModules/attachments/waybar-style.css @@ -0,0 +1,30 @@ +* { + font-family: Material Design Icons, Rubik Medium; + font-size: 14px; + color: @base05; +} + +window#waybar { + background: @base01; + border-bottom: 3px solid @base02; +} + +#battery { + margin-right: 6px; +} + +#workspaces button label { + font-size: 15px; + color: @base05; + transition: all 100ms ease-out; +} + +#workspaces button.active label { + font-weight: bolder; + color: @base0A; + transition: all 100ms ease-out; +} + +#battery { + color: @base0A; +} diff --git a/modules/homeModules/bspwm.nix b/modules/homeModules/bspwm.nix new file mode 100644 index 0000000..33b077b --- /dev/null +++ b/modules/homeModules/bspwm.nix @@ -0,0 +1,68 @@ +{inputs, ...}: { + flake.homeModules.bspwm = { + pkgs, + config, + lib, + ... + }: { + imports = [ + ./picom.nix + ./dunst.nix + ./sxhkd.nix + ]; + + options.customs = { + bspwm.enable = lib.mkEnableOption "enable bspwm"; + }; + + config = lib.mkIf config.customs.bspwm.enable { + picom.enable = true; + dunst.enable = true; + sxhkd.enable = true; + + rofi = { + enable = true; + package = pkgs.rofi; + }; + + xsession.windowManager.bspwm = { + enable = true; + + monitors = let + workspaces = [ + "α" + "β" + "γ" + "δ" + "ε" + ]; + in { + "^1" = workspaces; + # "^2" = workspaces; + }; + + settings = { + # focused_border_color = "#908caa"; + # normal_border_color = "#363a4f"; + # presel_feedback_color = "#752f20"; + border_width = 3; + window_gap = 12; + focus_follows_pointer = true; + split_ratio = 0.5; + }; + + startupPrograms = [ + "sxhkd" + "picom -b" + "emacs --daemon" + "feh --bg-fill ${config.wallpaper}" + ]; + }; + home.packages = with pkgs; [ + feh + betterlockscreen + xfce.xfce4-screenshooter + ]; + }; + }; +} diff --git a/modules/homeModules/dunst.nix b/modules/homeModules/dunst.nix new file mode 100644 index 0000000..c95f1e3 --- /dev/null +++ b/modules/homeModules/dunst.nix @@ -0,0 +1,25 @@ +{inputs, ...}: { + flake.homeModules.dunst = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + dunst.enable = lib.mkEnableOption "enable dunst"; + }; + config = lib.mkIf config.customs.dunst.enable { + home.packages = [pkgs.libnotify]; + services.dunst = { + enable = true; + settings = { + global = { + origin = "bottom-right"; + notification_limit = 5; + progress_bar = true; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/emacs/aliases b/modules/homeModules/emacs/aliases new file mode 100644 index 0000000..c6d56c9 --- /dev/null +++ b/modules/homeModules/emacs/aliases @@ -0,0 +1,4 @@ +alias nr sudo nixos-rebuild switch --flake /home/jerpo/nixfiles#ltrr-mini +alias hr home-manager switch --flake /home/jerpo/nixfiles +alias ff find-file $1 +alias ntemplate nix flake init --template github:the-nix-way/dev-templates#$1 diff --git a/modules/homeModules/emacs/default.nix b/modules/homeModules/emacs/default.nix new file mode 100644 index 0000000..b57a25a --- /dev/null +++ b/modules/homeModules/emacs/default.nix @@ -0,0 +1,49 @@ +{inputs, ...}: { + flake.homeModules.emacs = { + pkgs, + config, + lib, + ... + }: let + mkMutableSymlink = config.lib.meta.mkMutableSymlink; + in { + options.customs = { + emacs.enable = lib.mkEnableOption "enable emacs"; + emacs.package = lib.mkPackageOption pkgs "emacs package" {default = ["emacs30-pgtk"];}; + }; + config = lib.mkIf config.emacs.enable { + home.sessionVariables.EDITOR = "emacsclient -a emacs"; + home.packages = with pkgs; + with python311Packages; [ + # required dependencies + ripgrep + fd + tree-sitter + emacs-all-the-icons-fonts + libappindicator + poppler-utils + nixd + alejandra + sqlite + ]; + + programs.emacs = { + enable = true; + package = config.emacs.package; + extraPackages = epkgs: + with epkgs; [ + treesit-grammars.with-all-grammars + mu4e + ]; + }; + + xdg.configFile = { + "emacs/early-init.el".source = mkMutableSymlink ./early-init.el; + "emacs/init.el".source = mkMutableSymlink ./init.el; + "emacs/elpaca.el".source = mkMutableSymlink ./elpaca.el; + "emacs/etc/tempel/templates.eld".source = mkMutableSymlink ./templates.eld; + "emacs/etc/eshell/aliases".source = mkMutableSymlink ./aliases; + }; + }; + }; +} diff --git a/modules/homeModules/emacs/early-init.el b/modules/homeModules/emacs/early-init.el new file mode 100644 index 0000000..c6334f5 --- /dev/null +++ b/modules/homeModules/emacs/early-init.el @@ -0,0 +1,171 @@ +;;;; Optimisations from https://github.com/jamescherti/minimal-emacs.d + +;;; Garbage collection +(setq gc-cons-threshold most-positive-fixnum) + +(add-hook 'emacs-startup-hook + (lambda () + (setq gc-cons-threshold (* 16 1024 1024)))) + +;;; Performance + +;; Prefer loading newer compiled files +(setq load-prefer-newer t) + +;; Increase how much is read from processes in a single chunk (default is 4kb). +(setq read-process-output-max (* 1024 1024)) ; 512kb + +;; Disable warnings from the legacy advice API. They aren't useful. +(setq ad-redefinition-action 'accept) + +(setq warning-suppress-types '((lexical-binding))) + +;; Don't ping things that look like domain names. +(setq ffap-machine-p-known 'reject) + +;; By default, Emacs "updates" its ui more often than it needs to +(setq idle-update-delay 1.0) + +;; Font compacting can be very resource-intensive, especially when rendering +;; icon fonts on Windows. This will increase memory usage. +(setq inhibit-compacting-font-caches t) + +(unless (daemonp) + (unless noninteractive + (progn + ;; Disable mode-line-format during init + (defun minimal-emacs--reset-inhibited-vars-h () + (setq-default inhibit-redisplay nil + ;; Inhibiting `message' only prevents redraws and + inhibit-message nil) + (redraw-frame)) + + (defvar minimal-emacs--default-mode-line-format mode-line-format + "Default value of `mode-line-format'.") + (setq-default mode-line-format nil) + + (defun minimal-emacs--startup-load-user-init-file (fn &rest args) + "Advice for startup--load-user-init-file to reset mode-line-format." + (let (init) + (unwind-protect + (progn + (apply fn args) ; Start up as normal + (setq init t)) + (unless init + ;; If we don't undo inhibit-{message, redisplay} and there's an + ;; error, we'll see nothing but a blank Emacs frame. + (minimal-emacs--reset-inhibited-vars-h)) + (unless (default-toplevel-value 'mode-line-format) + (setq-default mode-line-format + minimal-emacs--default-mode-line-format))))) + + (advice-add 'startup--load-user-init-file :around + #'minimal-emacs--startup-load-user-init-file)) + + ;; Without this, Emacs will try to resize itself to a specific column size + (setq frame-inhibit-implied-resize t) + + ;; A second, case-insensitive pass over `auto-mode-alist' is time wasted. + ;; No second pass of case-insensitive search over auto-mode-alist. + (setq auto-mode-case-fold nil) + + ;; Reduce *Message* noise at startup. An empty scratch buffer (or the + ;; dashboard) is more than enough, and faster to display. + (setq inhibit-startup-screen t + inhibit-startup-echo-area-message user-login-name) + (setq initial-buffer-choice nil + inhibit-startup-buffer-menu t + inhibit-x-resources t) + + ;; Disable bidirectional text scanning for a modest performance boost. + (setq-default bidi-display-reordering 'left-to-right + bidi-paragraph-direction 'left-to-right) + + ;; Give up some bidirectional functionality for slightly faster re-display. + (setq bidi-inhibit-bpa t) + + ;; Remove "For information about GNU Emacs..." message at startup + (advice-add #'display-startup-echo-area-message :override #'ignore) + + ;; Suppress the vanilla startup screen completely. We've disabled it with + ;; `inhibit-startup-screen', but it would still initialize anyway. + (advice-add #'display-startup-screen :override #'ignore) + + ;; Shave seconds off startup time by starting the scratch buffer in + ;; `fundamental-mode' + (setq initial-major-mode 'fundamental-mode + initial-scratch-message nil))) + +;;; Native compilation and Byte compilation + +(if (and (featurep 'native-compile) + (fboundp 'native-comp-available-p) + (native-comp-available-p)) + ;; Activate `native-compile' + (setq native-comp-jit-compilation t + package-native-compile t) + ;; Deactivate the `native-compile' feature if it is not available + (setq features (delq 'native-compile features))) + +;; Suppress compiler warnings and don't inundate users with their popups. +(setq native-comp-async-report-warnings-errors 'silent) + +;;; UI elements + +;; Disable startup screens and messages +(setq inhibit-splash-screen t) + + +(push '(menu-bar-lines . 0) default-frame-alist) +(unless (memq window-system '(mac ns)) + (setq menu-bar-mode nil)) + +(unless (daemonp) + (unless noninteractive + (when (fboundp 'tool-bar-setup) + ;; Temporarily override the tool-bar-setup function to prevent it from + ;; running during the initial stages of startup + (advice-add #'tool-bar-setup :override #'ignore) + (define-advice startup--load-user-init-file + (:before (&rest _) minimal-emacs-setup-toolbar) + (advice-remove #'tool-bar-setup #'ignore) + (tool-bar-setup))))) + +(push '(tool-bar-lines . 0) default-frame-alist) +(setq tool-bar-mode nil) + +(push '(vertical-scroll-bars) default-frame-alist) +(push '(horizontal-scroll-bars) default-frame-alist) +(setq scroll-bar-mode nil) +(when (fboundp 'horizontal-scroll-bar-mode) + (horizontal-scroll-bar-mode -1)) + +(when (bound-and-true-p tooltip-mode) + (tooltip-mode -1)) + +;; Disable GUIs because they are inconsistent across systems, desktop +;; environments, and themes, and they don't match the look of Emacs. +(setq use-file-dialog nil) +(setq use-dialog-box nil) + +;; Allow for shorter responses: "y" for yes and "n" for no. +(if (boundp 'use-short-answers) + (setq use-short-answers t) + (advice-add #'yes-or-no-p :override #'y-or-n-p)) +(defalias #'view-hello-file #'ignore) ; Never show the hello file + +;;; And that's mine + +(setq package-enable-at-startup nil) +(setq-default pgtk-wait-for-event-timeout 0) + +(let ((mono-spaced-font "FiraCode Nerd Font") + (proportionately-spaced-font "Inconsonata")) + (set-face-attribute 'default nil :family mono-spaced-font :height 110 :weight 'medium) + (set-face-attribute 'fixed-pitch nil :family mono-spaced-font :height 1.0) + (set-face-attribute 'variable-pitch nil :family proportionately-spaced-font :height 1.0) + (set-face-attribute 'italic nil :underline nil)) + + +(provide 'early-init) +;;; early-init.el ends here diff --git a/modules/homeModules/emacs/elpaca.el b/modules/homeModules/emacs/elpaca.el new file mode 100644 index 0000000..4e1230f --- /dev/null +++ b/modules/homeModules/emacs/elpaca.el @@ -0,0 +1,46 @@ +(defvar elpaca-installer-version 0.11) +(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory)) +(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory)) +(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory)) +(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git" + :ref nil :depth 1 :inherit ignore + :files (:defaults "elpaca-test.el" (:exclude "extensions")) + :build (:not elpaca--activate-package))) +(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory)) + (build (expand-file-name "elpaca/" elpaca-builds-directory)) + (order (cdr elpaca-order)) + (default-directory repo)) + (add-to-list 'load-path (if (file-exists-p build) build repo)) + (unless (file-exists-p repo) + (make-directory repo t) + (when (<= emacs-major-version 28) (require 'subr-x)) + (condition-case-unless-debug err + (if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*")) + ((zerop (apply #'call-process `("git" nil ,buffer t "clone" + ,@(when-let* ((depth (plist-get order :depth))) + (list (format "--depth=%d" depth) "--no-single-branch")) + ,(plist-get order :repo) ,repo)))) + ((zerop (call-process "git" nil buffer t "checkout" + (or (plist-get order :ref) "--")))) + (emacs (concat invocation-directory invocation-name)) + ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch" + "--eval" "(byte-recompile-directory \".\" 0 'force)"))) + ((require 'elpaca)) + ((elpaca-generate-autoloads "elpaca" repo))) + (progn (message "%s" (buffer-string)) (kill-buffer buffer)) + (error "%s" (with-current-buffer buffer (buffer-string)))) + ((error) (warn "%s" err) (delete-directory repo 'recursive)))) + (unless (require 'elpaca-autoloads nil t) + (require 'elpaca) + (elpaca-generate-autoloads "elpaca" repo) + (let ((load-source-file-function nil)) (load "./elpaca-autoloads")))) +(add-hook 'after-init-hook #'elpaca-process-queues) +(elpaca `(,@elpaca-order)) + +(elpaca elpaca-use-package + ;; Enable :elpaca use-package keyword. + (elpaca-use-package-mode) + (setq use-package-always-ensure t)) + +(provide 'elpaca) +;;; elpaca.el ends here diff --git a/modules/homeModules/emacs/init.el b/modules/homeModules/emacs/init.el new file mode 100644 index 0000000..9a3053c --- /dev/null +++ b/modules/homeModules/emacs/init.el @@ -0,0 +1,848 @@ +(setopt custom-file (locate-user-emacs-file "custom.el")) +(load custom-file :no-error-if-file-is-missing) + + +(load (expand-file-name "elpaca.el" user-emacs-directory)) + + +;;; Basic behaviour + + +(setopt uniquify-buffer-name-style 'forward) + + +(setopt enable-recursive-minibuffers t) + + +;; Auto save +(setopt auto-save-default t) +(setopt auto-save-include-big-deletions t) +(setopt kill-buffer-delete-auto-save-files t) + + +;; Auto revert +(setopt revert-without-query (list ".") ; Do not prompt + auto-revert-stop-on-user-input nil + auto-revert-verbose t) + + +;; Revert other buffers (e.g, Dired) +(setopt global-auto-revert-non-file-buffers t) +(add-hook 'elpaca-after-init-hook #'global-auto-revert-mode) + + +;; Save place in buffer +(setopt save-place-limit 600) +(add-hook 'elpaca-after-init-hook #'save-place-mode) + + +(defun prot/keyboard-quit-dwim () + "Do-What-I-Mean behaviour for a general `keyboard-quit'. + +The generic `keyboard-quit' does not do the expected thing when +the minibuffer is open. Whereas we want it to close the +minibuffer, even without explicitly focusing it. + +The DWIM behaviour of this command is as follows: + +- When the region is active, disable it. +- When a minibuffer is open, but not focused, close the minibuffer. +- When the Completions buffer is selected, close it. +- In every other case use the regular `keyboard-quit'." + (interactive) + (cond + ((region-active-p) + (keyboard-quit)) + ((derived-mode-p 'completion-list-mode) + (delete-completion-window)) + ((> (minibuffer-depth) 0) + (abort-recursive-edit)) + (t + (keyboard-quit)))) + +(keymap-global-set "C-g" #'prot/keyboard-quit-dwim) + + +(use-package no-littering + :config + (no-littering-theme-backups)) + + +(use-package which-key + :ensure nil + :init + (which-key-mode)) + + +(use-package vundo + :commands (vundo) + :hook (vundo-mode . (lambda () (visual-line-mode -1) (setopt truncate-lines t)))) + + +(use-package winner + :ensure nil + :bind ("C-0" . winner-undo) + :custom + (winner-dont-bind-my-keys t) + :hook (elpaca-after-init . winner-mode)) + + +(use-package repeat + :ensure nil + :hook (elpaca-after-init . repeat-mode)) + + +(use-package avy + :bind (("M-j" . avy-goto-char-timer) + ("C-c j" . avy-goto-line))) + + +(use-package helpful + :bind (("C-h f" . helpful-callable) + ("C-h v" . helpful-variable) + ("C-h k" . helpful-key) + ("C-h x" . helpful-command) + ("C-c C-d" . helpful-at-point) + ("C-h F" . helpful-function))) + + +(setopt ediff-window-setup-function #'ediff-setup-windows-plain + ediff-split-window-function #'split-window-horizontally) + + +(electric-pair-mode t) + + +(global-set-key [remap list-buffers] 'ibuffer) + +;;; Tweak the looks of Emacs +(setq-default tab-width 4) + +(global-word-wrap-whitespace-mode t) +(global-visual-line-mode t) +(global-visual-wrap-prefix-mode t) + +;; Mode Line +(defun mood-line-segment-input-method () + "Return the selected input method if it differs from the default one" + (if current-input-method + (propertize (format-mode-line + (format "[%s]" current-input-method-title)) + 'face 'mood-line-unimportant))) + +(use-package mood-line + :config + (mood-line-mode) + :custom + (mood-line-segment-modal-meow-state-alist + '((normal "N" . mood-line-meow-normal) + (insert "I" . mood-line-meow-insert) + (keypad "K" . mood-line-meow-keypad) + (beacon "B" . mood-line-meow-beacon) + (motion "M" . mood-line-meow-motion))) + (mood-line-glyph-alist mood-line-glyphs-fira-code) + + (mood-line-format '((" " (mood-line-segment-modal) " " + (or (mood-line-segment-buffer-status) " ") " " + (mood-line-segment-buffer-name) " " (mood-line-segment-anzu) " " + (mood-line-segment-multiple-cursors) " " + (mood-line-segment-cursor-position) " " (mood-line-segment-scroll) + "") + ((mood-line-segment-vc) " " + (mood-line-segment-major-mode) " " + (mood-line-segment-input-method) " " + (mood-line-segment-misc-info) " " (mood-line-segment-checker) " " + (mood-line-segment-process) " " " "))) + :custom-face + (mood-line-meow-beacon ((t (:inherit 'font-lock-function-name-face :weight bold)))) + (mood-line-meow-insert ((t (:inherit 'font-lock-string-face :weight bold)))) + (mood-line-meow-keypad ((t (:inherit 'font-lock-keyword-face :weight bold)))) + (mood-line-meow-motion ((t (:inherit 'font-lock-constant-face :weight bold)))) + (mood-line-meow-normal ((t (:inherit 'font-lock-variable-use-face :weight bold))))) + + +(defvar after-load-theme-hook nil + "Hook run after a color theme is loaded using `load-theme'.") + +(defun spl3g/after-load-theme-advice (&rest r) + "Run `after-load-theme-hook' and ignore R." + (run-hooks 'after-load-theme-hook)) +(advice-add 'load-theme :after #'spl3g/after-load-theme-advice) + +(defun widen-mode-line () + "Widen the mode-line." + (interactive) + (set-face-attribute 'mode-line nil + :inherit 'mode-line + :box '(:line-width 8 :style flat-button)) + (set-face-attribute 'mode-line-inactive nil + :inherit 'mode-line-inactive + :box '(:line-width 8 :style flat-button))) + +(add-hook 'after-load-theme-hook 'widen-mode-line) + + +(use-package rainbow-delimiters + :hook (prog-mode . rainbow-delimiters-mode)) + + +;; Scrolling +(setopt scroll-conservatively 101) +(setopt scroll-margin 5) +(setopt mouse-wheel-progressive-speed nil) +(setopt fast-but-imprecise-scrolling t) +(setopt scroll-error-top-bottom t) +(setopt scroll-preserve-screen-position t) + + +;; Annoyances +(blink-cursor-mode -1) +(setopt visible-bell nil) +(setopt ring-bell-function #'ignore) +(setopt delete-pair-blink-delay 0.03) +(setopt blink-matching-paren nil) + +(add-hook 'prog-mode-hook 'display-line-numbers-mode) +(setopt display-line-numbers-width 3) + +(kill-ring-deindent-mode) + +;; Overwrite the default function with a patched one +(defun kill-ring-deindent-buffer-substring-function (beg end delete) + "Save the text within BEG and END to kill-ring, decreasing indentation. +Delete the saved text if DELETE is non-nil. + +In the saved copy of the text, remove some of the indentation, such +that the buffer position at BEG will be at column zero when the text +is yanked." + (let ((a beg) + (b end)) + (setq beg (min a b) + end (max a b))) + (let ((indentation (save-excursion (goto-char beg) + (current-column))) + (i-t-m indent-tabs-mode) + (text (if delete + (delete-and-extract-region beg end) + (buffer-substring beg end)))) + (with-temp-buffer + ;; Indent/deindent the same as the major mode in the original + ;; buffer. + (setq indent-tabs-mode i-t-m) + (insert text) + (indent-rigidly (point-min) (point-max) + (- indentation)) + (buffer-string)))) + + +;;; TRAMP +(setq remote-file-name-inhibit-locks t + tramp-use-scp-direct-remote-copying t + remote-file-name-inhibit-auto-save-visited t) + +(setq tramp-copy-size-limit (* 1024 1024) ;; 1MB + tramp-verbose 2) + + +;;; Configure the minibuffer and completions +(use-package vertico + :ensure t + :hook (elpaca-after-init . vertico-mode) + :bind (:map vertico-map + ("RET" . vertico-directory-enter) + ("DEL" . vertico-directory-delete-char) + ("M-DEL" . vertico-directory-delete-word))) + + +(use-package marginalia + :ensure t + :hook (elpaca-after-init . marginalia-mode)) + + +(use-package orderless + :custom + (completion-styles '(orderless basic)) + (completion-category-overrides '((file (styles basic partial-completion))))) + + +(use-package savehist + :ensure nil ; it is built-in + :hook (elpaca-after-init . savehist-mode) + :custom + (savehist-file "~/.config/emacs/var/savehist.el") + (history-length 1000) + (history-delete-duplicates t) + (savehist-additional-variables '(kill-ring search-ring))) + + +(defun cape--dabbrev-project () + (let* ((project (project-current)) + (buffers (when project + (project-buffers project)))) + (if project + (butlast buffers (- (length buffers) 4)) + (cape--buffers-major-mode)))) + +(use-package cape + :after corfu + :custom + (dabbrev-ignored-buffer-modes '(archive-mode image-mode eshell-mode)) + (cape-dabbrev-check-other-buffers #'cape--dabbrev-project) + :config + (add-hook 'completion-at-point-functions #'cape-dabbrev) + (add-hook 'completion-at-point-functions #'cape-file) + (add-hook 'completion-at-point-functions #'cape-elisp-block)) + + +(use-package corfu + :hook (elpaca-after-init . global-corfu-mode) + :bind (:map corfu-map + ("M-j" . corfu-next) + ("M-k" . corfu-previous) + ([remap previous-line] . nil) + ([remap next-line] . nil)) + :custom + (corfu-preselect 'prompt) + (corfu-auto nil) + (corfu-popupinfo-delay '(1.25 . 0.5)) + (corfu-auto-delay 0) + (corfu-auto-prefix 2) + (corfu-count 16) + (corfu-max-width 120) + (corfu-min-width 20) + (corfu-scroll-margin 4) + (corfu-on-exact-match nil) + (tab-always-indent 'complete) + (corfu-cycle t) + :config + (corfu-popupinfo-mode 1) + (corfu-history-mode 1)) + + +(use-package completion-preview + :ensure nil + :hook (elpaca-after-init . global-completion-preview-mode) + :bind (:map completion-preview-active-mode-map + ("TAB" . (lambda () + (interactive) + (completion-preview-complete) + (completion-at-point))) + + ("M-i" . (lambda () + (interactive) + (completion-preview-insert))) + ("M-n" . completion-preview-next-candidate) + ("M-p" . completion-preview-prev-candidate)) + :custom + (completion-preview-minimum-symbol-length 2)) + + + +;;; Movement + + +(use-package embark + :ensure t + + :bind + (("C-." . embark-act) + ("C-;" . embark-dwim) + ("C-h B" . embark-bindings)) + :config + (defun embark-which-key-indicator () + "An embark indicator that displays keymaps using which-key. +The which-key help message will show the type and value of the +current target followed by an ellipsis if there are further +targets." + (lambda (&optional keymap targets prefix) + (if (null keymap) + (which-key--hide-popup-ignore-command) + (which-key--show-keymap + (if (eq (plist-get (car targets) :type) 'embark-become) + "Become" + (format "Act on %s '%s'%s" + (plist-get (car targets) :type) + (embark--truncate-target (plist-get (car targets) :target)) + (if (cdr targets) "…" ""))) + (if prefix + (pcase (lookup-key keymap prefix 'accept-default) + ((and (pred keymapp) km) km) + (_ (key-binding prefix 'accept-default))) + keymap) + nil nil t (lambda (binding) + (not (string-suffix-p "-argument" (cdr binding)))))))) + + (setq embark-indicators + '(embark-which-key-indicator + embark-highlight-indicator + embark-isearch-highlight-indicator)) + + (defun embark-hide-which-key-indicator (fn &rest args) + "Hide the which-key indicator immediately when using the completing-read prompter." + (which-key--hide-popup-ignore-command) + (let ((embark-indicators + (remq #'embark-which-key-indicator embark-indicators))) + (apply fn args))) + + (advice-add #'embark-completing-read-prompter + :around #'embark-hide-which-key-indicator)) + + +(use-package multiple-cursors + :config + (global-set-key (kbd "C->") 'mc/mark-next-like-this) + (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) + (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)) + + + +;;; The file manager (Dired) + + +(use-package dired + :ensure nil + :commands (dired) + :hook + ((dired-mode . dired-hide-details-mode) + (dired-mode . hl-line-mode)) + :custom + (dired-recursive-copies 'always) + (dired-recursive-deletes 'always) + (delete-by-moving-to-trash t) + (dired-dwim-target t) + (dired-listing-switches "-hal --group-directories-first")) + + +(use-package dired-subtree + :ensure t + :after dired + :bind + ( :map dired-mode-map + ("<tab>" . dired-subtree-toggle) + ("TAB" . dired-subtree-toggle) + ("<backtab>" . dired-subtree-remove) + ("S-TAB" . dired-subtree-remove)) + :custom + (dired-subtree-use-backgrounds nil)) + + +(use-package trashed + :ensure t + :commands (trashed) + :custom + (trashed-action-confirmer 'y-or-n-p) + (trashed-use-header-line t) + (trashed-sort-key '("Date deleted" . t)) + (trashed-date-format "%Y-%m-%d %H:%M:%S")) + + + +;;; Eshell + + +(use-package eshell + :ensure nil + :hook + (eshell-exec . (lambda (p) (buffer-disable-undo))) + (eshell-kill . (lambda (p s) (buffer-enable-undo))) + (eshell-pre-command . eshell-append-history) + + :bind (("C-c o t" . spl3g/eshell-dwim) + ("C-c o s" . spl3g/select-eshell) + ("C-c o r" . spl3g/rename-current-eshell)) + + :custom + (eshell-history-size 500) + (eshell-history-append t) + (eshell-save-history-on-exit nil) + + :config + ;; (add-to-list 'eshell-modules-list 'eshell-tramp) + + ;; Save history on every command + (defun eshell-append-history () + "Call `eshell-write-history' with the `append' parameter set to `t'." + (when eshell-history-ring + (let ((newest-cmd-ring (make-ring 1))) + (ring-insert newest-cmd-ring (car (ring-elements eshell-history-ring))) + (let ((eshell-history-ring newest-cmd-ring)) + (eshell-write-history eshell-history-file-name t))))) + + + (defun spl3g/eshell-dwim () + (interactive) + (defvar current-prefix-arg) + (let* ((project (project-current)) + (eshell-func (if project + 'project-eshell + 'eshell)) + (buffer-name (if project + (format "*%s-eshell*" (project-name project)) + "*eshell*")) + (current-prefix-arg t)) + (if (not (get-buffer buffer-name)) + (let ((buf (funcall eshell-func))) + (switch-to-buffer (other-buffer buf)) + (switch-to-buffer-other-window buf)) + (switch-to-buffer-other-window buffer-name)))) + + (defun spl3g/select-eshell () + (interactive) + (let* ((eshell-buffers (seq-filter (lambda (buffer) + (eq (with-current-buffer buffer major-mode) + 'eshell-mode)) + (buffer-list))) + + (eshell-windows (remove nil (mapcar (lambda (buffer) + (let* ((window (get-buffer-window buffer)) + (name (buffer-name buffer))) + (when window + (cons name window)))) + eshell-buffers))) + + (eshell-names (seq-filter (lambda (buffer) (not (eq buffer (buffer-name (current-buffer))))) + (mapcar (lambda (buffer) (buffer-name buffer)) eshell-buffers))) + + (selected-buffer (if (length> eshell-buffers 1) + (completing-read "Select eshell buffer: " eshell-names) + (car eshell-buffers))) + (selected-window (if (length> eshell-windows 1) + (cdr (assoc (completing-read "Select window to place the buffer in: " eshell-windows) eshell-windows)) + (cdar eshell-windows)))) + (if selected-window + (progn + (select-window selected-window) + (switch-to-buffer selected-buffer)) + (switch-to-buffer-other-window selected-buffer)))) + + (defun spl3g/rename-current-eshell () + "Add NAME in <> to the current project eshell buffer" + (interactive) + (let* ((eshell-buffers (seq-filter (lambda (buffer) + (eq (with-current-buffer buffer major-mode) + 'eshell-mode)) + (buffer-list))) + (eshell-names (mapcar (lambda (buffer) (buffer-name buffer)) eshell-buffers)) + (eshell-windows (remove nil (mapcar (lambda (buffer) + (let* ((window (get-buffer-window buffer)) + (name (buffer-name buffer))) + (when window + (cons name window)))) + eshell-buffers))) + (selected-window (if (and (sequencep eshell-windows) (length> eshell-windows 1)) + (assoc (completing-read "Select window to place the buffer in: " eshell-windows) eshell-windows) + (car eshell-windows))) + (additional-name (when selected-window + (read-string "Additional name: "))) + (buffer-name (when selected-window + (car (split-string (car selected-window) "<")))) + (formatted-name (if (length> additional-name 0) + (format "%s<%s>" buffer-name additional-name) + buffer-name)) + ) + (if selected-window + (with-current-buffer (car selected-window) + (rename-buffer formatted-name)) + (message "No eshell buffers"))))) + + +(use-package eat + :hook + (eshell-load . eat-eshell-mode) + (eshell-load . eat-eshell-visual-command-mode) + :custom + (eat-enable-auto-line-mode t) + :custom-face + (ansi-color-bright-blue ((t (:inherit 'ansi-color-blue)))) + (ansi-color-bright-red ((t (:inherit 'ansi-color-red)))) + (ansi-color-bright-red ((t (:inherit 'ansi-color-red)))) + (ansi-color-bright-cyan ((t (:inherit 'ansi-color-cyan)))) + (ansi-color-bright-black ((t (:inherit 'ansi-color-black)))) + (ansi-color-bright-green ((t (:inherit 'ansi-color-green)))) + (ansi-color-bright-white ((t (:inherit 'ansi-color-white)))) + (ansi-color-bright-yellow ((t (:inherit 'ansi-color-yellow)))) + (ansi-color-bright-magenta ((t (:inherit 'ansi-color-magenta))))) + + +(use-package eshell-syntax-highlighting + :hook (eshell-mode . eshell-syntax-highlighting-mode)) + + + +;;; Programming things + + +(use-package tempel + :ensure t + ;; By default, tempel looks at the file "templates" in + ;; user-emacs-directory, but you can customize that with the + ;; tempel-path variable: + ;; :custom + ;; (tempel-path (concat user-emacs-directory "custom_template_file")) + :bind (("M-*" . tempel-insert) + ("M-+" . tempel-complete) + :map tempel-map + ("C-c RET" . tempel-done) + ("C-<down>" . tempel-next) + ("C-<up>" . tempel-previous) + ("M-<down>" . tempel-next) + ("M-<up>" . tempel-previous)) + :custom + (tempel-trigger-prefix "<") + :init + ;; Make a function that adds the tempel expansion function to the + ;; list of completion-at-point-functions (capf). + (defun tempel-setup-capf () + (add-hook 'completion-at-point-functions #'tempel-expand -1 'local)) + ;; Put tempel-expand on the list whenever you start programming or + ;; writing prose. + (add-hook 'prog-mode-hook 'tempel-setup-capf) + (add-hook 'text-mode-hook 'tempel-setup-capf)) + +(use-package tempel-collection + :ensure t + :after tempel) + +(use-package lsp-snippet-tempel + :ensure (:host github :repo "tpeacock19/lsp-snippet") + :config + (lsp-snippet-tempel-eglot-init)) + + +(use-package apheleia + :hook (prog-mode-hook . apheleia-mode) + :config + (push '(alejandra . ("alejandra")) apheleia-formatters) + (setf (alist-get 'nix-mode apheleia-mode-alist) '(alejandra))) + + +(use-package envrc + :mode ("\\.envrc\\.?[[:alpha:]]*\\'" . envrc-file-mode) + :hook (elpaca-after-init . envrc-global-mode) + :bind-keymap + ("C-c e" . envrc-command-map)) + + +(use-package scratch + :commands scratch) + + +(use-package transient) + +(use-package magit + :after transient + :bind (("C-c o g" . magit))) + + +(use-package treesit-auto + :hook (elpaca-after-init . global-treesit-auto-mode) + :custom + (treesit-auto-install 'prompt) + :config + (treesit-auto-add-to-auto-mode-alist 'all) + (delete 'html treesit-auto-langs)) + + +(keymap-global-set "C-c c c" 'compile) +(keymap-global-set "C-c c r" 'recompile) + + +(defun colorize-compilation-buffer () + (ansi-color-apply-on-region compilation-filter-start (point))) +(add-hook 'compilation-filter-hook 'colorize-compilation-buffer) + + + +;; LSP shit +(use-package eglot + :ensure nil + :bind (:map eglot-mode-map + ("C-c s a" . eglot-code-actions) + ("C-c s r" . eglot-rename) + ("C-c s h" . eldoc) + ("C-c s f" . eglot-format) + ("C-c s F" . eglot-format-buffer) + ("C-c s d" . xref-find-definitions-at-mouse) + ("C-c s R" . eglot-reconnect)) + :custom + (completion-category-overrides '((eglot (styles prescient)) + (eglot-capf (styles prescient)))) + :config + (advice-add 'eglot-completion-at-point :around #'cape-wrap-buster) + + (setq-default + eglot-workspace-configuration + `(:nixd ( :nixpkgs (:expr "import <nixpkgs> { }") + :formatting (:command ["nixpkgs-fmt"]) + :options ( :nixos (:expr "(builtins.getFlake \"/home/jerpo/nixfiles\").nixosConfigurations.ltrr-mini.options") + :home-manager (:expr "(builtins.getFlake \"/home/jerpo/nixfiles\").homeConfigurations.\"jerpo@ltrr-mini\".options")))))) + + +(use-package dumb-jump + :commands (dumb-jump-xref-activate) + :custom + (dumb-jump-force-searcher 'rg) + :init + (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)) + + +(use-package dape) + + + +;;; Languages +(use-package web-mode + :mode + ("\\.html\\'" + "\\.phtml\\'" + "\\.tpl\\.php\\'" + "\\.[agj]sp\\'" + "\\.as[cp]x\\'" + "\\.erb\\'" + "\\.mustache\\'" + "\\.djhtml\\'") + :hook + (eb-mode . (lambda () (electric-pair-local-mode -1))) + :custom + (web-mode-markup-indent-offset tab-width) + (web-mode-css-indent-offset tab-width) + (web-mode-code-indent-offset tab-width) + (web-mode-script-padding tab-width) + (web-mode-style-padding tab-width) + :init + + (define-derived-mode vue-mode web-mode "Vue") + (add-to-list 'auto-mode-alist '("\\.vue\\'" . vue-mode)) + (add-hook 'vue-mode-hook + (lambda () + (with-eval-after-load 'eglot + (defun vue-eglot-init-options () + "Set SDK path and default options." + (let ((tsdk-path (expand-file-name + "lib/node_modules/typescript/lib/" + (inheritenv (shell-command-to-string + (string-join '("nix-store --query --references $(which vue-language-server)" + "xargs -n1 nix-store -q --referrers" + "grep typescript" + "head -n1" + "tr -d '\n'") + " | ")))))) + `( :typescript (:tsdk ,tsdk-path) + :hybridMode :json-false))) + (setf (alist-get 'vue-mode eglot-server-programs) ;; nix-env -iA nixpkgs.nodePackages.volar + `("vue-language-server" "--stdio" :initializationOptions ,(vue-eglot-init-options)))))) + + (define-derived-mode svelte-mode web-mode "Svelte") + (add-to-list 'auto-mode-alist '("\\.svelte\\'" . svelte-mode)) + (with-eval-after-load 'eglot + (add-to-list 'eglot-server-programs `(svelte-mode "svelteserver" "--stdio")))) + +(use-package emmet-mode + :hook (web-mode . emmet-mode)) + + +(use-package nix-mode + :mode ("\\.nix\\'" "\\.nix.in\\'")) + + +(use-package typescript-ts-mode + :ensure nil + :mode ("\\.ts\\'") + :hook (typescript-ts-mode . (lambda () (setq-local forward-sexp-function nil))) + :custom + (typescript-ts-mode-indent-offset tab-width)) + + +(use-package go-ts-mode + :ensure nil + :custom + (go-ts-mode-indent-offset tab-width)) + +(use-package c-ts-mode + :ensure nil + :hook (c-ts-mode . (lambda () (apheleia-mode -1)))) + +(use-package c-mode + :ensure nil + :hook (c-mode . (lambda () (apheleia-mode -1))) + :mode ("\\.c\\'")) + + +(use-package markdown-mode + :mode ("\\.md\\'")) + + +(use-package conf-unix-mode + :ensure nil + :mode ("\\.env\\.?[[:alpha:]]*\\'")) + + +(use-package sql-indent + :hook (sql-mode . sqlind-minor-mode)) + +(setopt sql-connection-alist + '(("postgres-sirius" + (sql-product 'postgres) + (sql-user "college") + (sql-server "127.0.0.1") + (sql-database "coll") + (sql-port 5432)))) + +(setopt sql-sqlite-program "sqlite3") + + +(use-package elm-mode + :mode "\\.elm\\'") + + +(use-package zig-ts-mode + :mode "\\.zig\\'") + + +(use-package verb + :after org + :config (define-key org-mode-map (kbd "C-c C-r") verb-command-map)) + + + +;; Notetaking + + +(use-package org-mode + :ensure nil + :hook (org-mode . variable-pitch-mode) + :custom + (org-startup-indented t) + :mode "\\.org\\'" + :config + (set-face-attribute 'org-table nil :inherit 'fixed-pitch)) + + +(use-package writeroom-mode + :custom + (writeroom-global-effects nil) + (writeroom-maximize-window nil)) + + +(use-package denote + :commands (denote denote-create-note denote-journal-extras-new-entry)) + + + +;; Other + + +(use-package kubel + :commands (kubel) + :hook (kubel-mode . hl-line-mode) + :bind ((:map kubel-mode-map + ("N" . kubel-set-namespace) + ("P" . kubel-port-forward-pod) + ("n" . #'next-line) + ("p" . #'previous-line))) + :custom-face + (kubel-status-completed ((t (:inherit 'font-lock-keyword-face :weight bold)))) + (kubel-status-terminating ((t (:inherit 'font-lock-variable-use-face :weight bold))))) + +(provide 'init) +;;; init.el ends here. diff --git a/modules/homeModules/emacs/templates.eld b/modules/homeModules/emacs/templates.eld new file mode 100644 index 0000000..138888f --- /dev/null +++ b/modules/homeModules/emacs/templates.eld @@ -0,0 +1,18 @@ +nix-mode + +(opt "{ pkgs, config, lib, ... }:" + n + n "{" + n> "options = {" + n> (p "option name" name) ".enable = lib.mkEnableOption \"enable " (s name) "\";" + n " };" + n> "config = lib.mkIf config." (s name) ".enable {" + n> q + n " };" + n "}") + +python-ts-mode + +(view "class " (s name) "ViewSet(viewsets.ModelViewSet):" + n> "queryset = " (s name) ".objects.all()" + n> "serializer_class = " (s name) "Serializer") diff --git a/modules/homeModules/exwm.nix b/modules/homeModules/exwm.nix new file mode 100644 index 0000000..ccc7dbf --- /dev/null +++ b/modules/homeModules/exwm.nix @@ -0,0 +1,71 @@ +{ + inputs, + self, + ... +}: { + flake.homeModules.exwm = { + lib, + pkgs, + config, + ... + }: { + modules = [ + self.homeModules.picom + self.homeModules.dunst + ]; + + options.customs = { + exwm.enable = lib.mkEnableOption " enable exwm"; + }; + + config = lib.mkIf config.exwm.enable { + customs.picom.enable = true; + customs.dunst.enable = true; + + programs.emacs = { + extraPackages = epkgs: with epkgs; [exwm]; + extraConfig = '' + (setq exwm--my-scripts "${./attachments/hypr-scripts}") + ''; + }; + services = { + # Screenshotting. + flameshot.enable = true; + + # Screen locking. + screen-locker = { + enable = true; + lockCmd = "${pkgs.i3lock-fancy}/bin/i3lock-fancy -p -t ''"; + inactiveInterval = 20; + }; + }; + home.file.xinitrc = { + text = '' + # Disable access control for the current user. + xhost +SI:localuser:$USER + + # Make Java applications aware this is a non-reparenting window manager. + export _JAVA_AWT_WM_NONREPARENTING=1 + + # Set default cursor. + xsetroot -cursor_name left_ptr + + picom -b + + # Finally start Emacs + ${pkgs.dbus.dbus-launch} --exit-with-session emacs -mm --fullscreen --internal-border=0 --border-width=0 + ''; + target = ".xinitrc"; + }; + home.packages = with pkgs; [ + boomer + arandr + feh + gtk3 + i3lock-fancy + xclip + xorg.xev + ]; + }; + }; +} diff --git a/modules/homeModules/firefox.nix b/modules/homeModules/firefox.nix new file mode 100644 index 0000000..d92b50d --- /dev/null +++ b/modules/homeModules/firefox.nix @@ -0,0 +1,111 @@ +{inputs, ...}: { + flake.homeModules.firefox = { + pkgs, + config, + lib, + inputs, + ... + }: { + options.customs = { + firefox.enable = lib.mkEnableOption "enable firefox"; + }; + config = lib.mkIf config.firefox.enable { + programs.firefox = { + enable = true; + package = pkgs.firefox; + profiles.ShyFox = { + isDefault = true; + extensions = { + packages = with pkgs.nur.repos.rycee.firefox-addons; [ + bitwarden + ublock-origin + sponsorblock + return-youtube-dislikes + firefox-color + tampermonkey + duckduckgo-privacy-essentials + mal-sync + sidebery + ]; + + force = true; + # settings = { + # "{3c078156-979c-498b-8990-85f7987dd929}".settings = + # builtins.fromJSON (builtins.readFile "${inputs.shimmer.outPath}/sidebery.json"); + # }; + }; + + preConfig = builtins.readFile "${inputs.betterfox.outPath}/user.js"; + userChrome = builtins.readFile "${inputs.shimmer.outPath}/userChrome.css"; + userContent = builtins.readFile "${inputs.shimmer.outPath}/userContent.css"; + + settings = { + "shimmer.remove-winctr-buttons" = true; + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + "svg.context-properties.content.enabled" = true; + "browser.search.suggest.enabled" = true; + "captivedetect.canonicalURL" = "http://detectportal.firefox.com/canonical.html"; + "network.captive-portal-service.enabled" = true; + "network.connectivity-service.enabled" = true; + "extensions.autoDisableScopes" = 0; + }; + search = { + force = true; + engines = { + "Brave" = { + urls = [ + {template = "https://search.brave.com/search?q={searchTerms}";} + { + type = "application/x-suggestions+json"; + template = "https://search.brave.com/api/suggest?q={searchTerms}"; + } + ]; + + icon = "https://cdn.search.brave.com/serp/v2/_app/immutable/assets/safari-pinned-tab.539899c7.svg"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!br"]; + }; + "NixOS Packages" = { + urls = [{template = "https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query={searchTerms}";}]; + icon = "https://nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!ns"]; + }; + "NixOS Options" = { + urls = [{template = "https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query={searchTerms}";}]; + icon = "https://nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!no"]; + }; + "HomeManager" = { + urls = [{template = "https://home-manager-options.extranix.com/?query={searchTerms}&release=master";}]; + icon = "https://github.com/mipmip/home-manager-option-search/blob/main/images/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!hs"]; + }; + "NixWiki" = { + urls = [{template = "https://wiki.nixos.org/w/index.php?search={searchTerms}";}]; + icon = "https://nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!nw"]; + }; + "Kinopoisk" = { + urls = [{template = "https://www.kinopoisk.ru/index.php?kp_query={searchTerms}";}]; + icon = "https://www.kinopoisk.ru/favicon.ico"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!ks"]; + }; + "MDN Docs" = { + urls = [{template = "https://developer.mozilla.org/en-US/search?q={searchTerms}";}]; + icon = "https://developer.mozilla.org/favicon-48x48.bc390275e955dacb2e65.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!md"]; + }; + }; + default = "Brave"; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/fish.nix b/modules/homeModules/fish.nix new file mode 100644 index 0000000..1876da5 --- /dev/null +++ b/modules/homeModules/fish.nix @@ -0,0 +1,42 @@ +{inputs, ...}: { + flake.homeModules.fish = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + fish.enable = lib.mkEnableOption "enable fish"; + }; + config = lib.mkIf config.customs.fish.enable { + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; + + programs.nix-index.enableFishIntegration = true; + + programs.fish = { + enable = true; + plugins = [ + { + name = "pure"; + src = pkgs.fishPlugins.pure.src; + } + { + name = "autopair"; + src = pkgs.fishPlugins.autopair.src; + } + ]; + interactiveShellInit = '' + set fish_greeting + pokemon-colorscripts -r --no-title + ''; + + shellAliases = { + ls = "ls --hyperlink=auto --color=auto"; + }; + }; + }; + }; +} diff --git a/modules/homeModules/fuzzel.nix b/modules/homeModules/fuzzel.nix new file mode 100644 index 0000000..b8af295 --- /dev/null +++ b/modules/homeModules/fuzzel.nix @@ -0,0 +1,33 @@ +{inputs, ...}: { + flake.homeModules.fuzzel = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + fuzzel.enable = lib.mkEnableOption "enable fuzzel"; + }; + + config = lib.mkIf config.customs.fuzzel.enable { + programs.fuzzel = { + enable = true; + settings = { + colors = { + background = "1f1d2eff"; + text = "6e6a86ff"; + selection = "908caaff"; + selection-text = "1f1d2eff"; + }; + main = { + lines = 9; + terminal = "alacritty -e"; + vertical-pad = 0; + horizontal-pad = 0; + }; + border.width = 0; + }; + }; + }; + }; +} diff --git a/modules/homeModules/hyprland.nix b/modules/homeModules/hyprland.nix new file mode 100644 index 0000000..e6455e3 --- /dev/null +++ b/modules/homeModules/hyprland.nix @@ -0,0 +1,236 @@ +{ + inputs, + self, + ... +}: { + flake.homeModules.hyprland = { + pkgs, + lib, + config, + inputs, + ... + }: { + modules = [ + self.homeModules.waybar + self.homeModules.rofi + self.homeModules.mako + ]; + + options.customs = { + hyprland.enable = lib.mkEnableOption "enable hyprland"; + }; + + config = lib.mkIf config.customs.hyprland.enable { + waybar.enable = true; + rofi.enable = true; + mako.enable = true; + + home.packages = with pkgs; [ + swww + brightnessctl + grimblast + cliphist + polkit_gnome + wl-clipboard + libnotify + socat + ]; + + home.sessionVariables.XDG_CURRENT_DESKTOP = "Hyprland"; + + wayland.windowManager.hyprland = { + enable = true; + settings = { + "$scripts" = "${./attachments/hypr-scripts}"; + "$mainMod" = "SUPER"; + "$terminal" = "alacritty"; + + exec-once = [ + "emacs --daemon" + "swww-daemon" + "swww img ${config.wallpaper}" + "$scripts/bitwarden-float.sh" + ]; + + monitor = [ + "eDP-1,preferred,auto,1.6" + ",preferred,auto,1,mirror,eDP-1" + ]; + + input = { + kb_layout = "us,ru"; + kb_options = "grp:win_space_toggle"; + touchpad = { + natural_scroll = "yes"; + disable_while_typing = "no"; + }; + sensitivity = 0.1; + }; + + general = { + gaps_in = 5; + gaps_out = 15; + border_size = 3; + layout = "dwindle"; + allow_tearing = false; + }; + + misc = { + vfr = true; + }; + + decoration = { + rounding = 7; + blur = { + enabled = true; + size = 3; + passes = 1; + }; + }; + + xwayland.force_zero_scaling = true; + env = [ + "GDK_SCALE,2" + "XCURSOR_SIZE,32" + ]; + + animations = { + enabled = 1; + # bezier = "overshot,0.13,0.99,0.29,1.1,"; + animation = [ + "fade,1,4,default" + "workspaces,1,4,default,fade" + "windows,1,4,default,popin 95%" + "windowsMove,0" + ]; + }; + + dwindle = { + pseudotile = "yes"; + preserve_split = "yes"; + }; + + gesture = [ + "3, horizontal, workspace" + ]; + misc.force_default_wallpaper = 1; + + windowrule = [ + "bordersize 0, floating:0, onworkspace:w[tv1]" + "rounding 0, floating:0, onworkspace:w[tv1]" + "bordersize 0, floating:0, onworkspace:f[1]" + "rounding 0, floating:0, onworkspace:f[1]" + ]; + + workspace = [ + "w[tv1], gapsout:0, gapsin:0" + "f[1], gapsout:0, gapsin:0" + ]; + + windowrulev2 = [ + "float, class:^(org.telegram.desktop)$" + "pin, class:^(org.telegram.desktop)$" + "size 30% 845, class:^(org.telegram.desktop)$" + "move 100%-w-25 73, class:^(org.telegram.desktop)$" + # firefox + "float, title:(Sharing Indicator)" + "noborder, title:(Sharing Indicator)" + "rounding 0, title:(Sharing Indicator)" + "float, title:(Picture-in-Picture)" + "pin, title:(Picture-in-Picture)" + "move 100%-w-21 100%-w-21, title:^(Picture-in-Picture)$" + "noinitialfocus, title:^(Picture-in-Picture)$" + "float, title:^(Save File)$" + "pin, title:^(Save File)$" + # dragon-drop + "pin, class:^(dragon-drop)$" + # torrent + "float, title:^(Torrent Options)$" + "pin, title:^(Torrent Options)$" + # xwaylandvideobridge + "opacity 0.0 override 0.0 override,class:^(xwaylandvideobridge)$" + "noanim,class:^(xwaylandvideobridge)$" + "noinitialfocus,class:^(xwaylandvideobridge)$" + "maxsize 1 1,class:^(xwaylandvideobridge)$" + "noblur,class:^(xwaylandvideobridge)$" + ]; + + bind = + [ + "$mainMod, V, togglefloating, " + "$mainMod, P, pseudo," + "$mainMod, I, togglesplit," + "$mainMod, F, fullscreen, 0" + "$mainMod, M, fullscreen, 1" + "$mainMod SHIFT, Q, killactive, " + "$mainMod SHIFT, E, exit," + + # Apps + "$mainMod, D, exec, pkill rofi || rofi -show-icons -show drun" + "$mainMod, Q, exec, $terminal" + "$mainMod, B, exec, zen-beta" + "$mainMod, T, exec, Telegram" + "$mainMod, E, exec, emacsclient -c -a emacs" + "$mainMod CONTROL, E, exec, emacs" + "$mainMod, T, exec, $scripts/toggle-tg.sh" + "$mainMod SHIFT, Esc, exec, swww img ${config.wallpaper}" + ",XF86Favorites, exec, bash $scripts/toggle-vpn.sh" + + # Screenshooting + ", Print, exec, grimblast save screen" + "ALT, Print, exec, grimblast save active" + "SHIFT, Print, exec, grimblast save area" + "CONTROL, Print, exec, grimblast copy screen" + "ALT_CONTROL, Print, exec, grimblast copy active" + "CONTROL_SHIFT, Print, exec, grimblast copy area " + + # Windows + "$mainMod, J, movefocus, d" + "$mainMod, K, movefocus, u" + "$mainMod, H, movefocus, l" + "$mainMod, L, movefocus, r" + "SUPER_SHIFT,J,movewindow,d" + "SUPER_SHIFT,K,movewindow,u" + "SUPER_SHIFT,H,movewindow,l" + "SUPER_SHIFT,L,movewindow,r" + "$mainMod, mouse_down, workspace, e+1" + "$mainMod, mouse_up, workspace, e-1" + ] + ++ ( + # workspaces + # binds $mod + [shift +] {1..10} to [move to] workspace {1..10} + builtins.concatLists (builtins.genList ( + x: let + ws = let + c = (x + 1) / 10; + in + builtins.toString (x + 1 - (c * 10)); + in [ + "$mainMod, ${ws}, workspace, ${toString (x + 1)}" + "$mainMod SHIFT, ${ws}, movetoworkspacesilent, ${toString (x + 1)}" + ] + ) + 10) + ); + binde = [ + # Volume + ",0x1008FF11,exec,wpctl set-volume @DEFAULT_SINK@ 5%-" + ",0x1008FF13,exec,wpctl set-volume @DEFAULT_SINK@ 5%+" + ",0x1008FF12,exec,wpctl set-mute @DEFAULT_SINK@ toggle" + ",XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_SOURCE@ toggle" + ",XF86TouchpadToggle, exec, python3 $scripts/switch-sink.py" + + # Brightness + ",XF86MonBrightnessUp,exec,brightnessctl s +5%" + ",XF86MonBrightnessDown,exec,brightnessctl s 5%-" + ]; + + bindm = [ + "$mainMod, mouse:272, movewindow" + "$mainMod, mouse:273, resizewindow" + ]; + }; + }; + }; + }; +} diff --git a/modules/homeModules/mako.nix b/modules/homeModules/mako.nix new file mode 100644 index 0000000..d9f9ae2 --- /dev/null +++ b/modules/homeModules/mako.nix @@ -0,0 +1,24 @@ +{inputs, ...}: { + flake.homeModules.mako = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + mako.enable = lib.mkEnableOption "enable mako"; + }; + + config = lib.mkIf config.customs.mako.enable { + services.mako = { + enable = true; + settings = { + anchor = "bottom-right"; + default-timeout = 5000; + border-size = 3; + border-radius = 7; + }; + }; + }; + }; +} diff --git a/modules/homeModules/niri.nix b/modules/homeModules/niri.nix new file mode 100644 index 0000000..4317da7 --- /dev/null +++ b/modules/homeModules/niri.nix @@ -0,0 +1,264 @@ +{inputs, ...}: { + flake.homeModules.niri = { + pkgs, + config, + lib, + inputs, + ... + }: + with lib; let + cfg = config.niri.customs; + in { + imports = [ + ./waybar.nix + ./rofi.nix + ./mako.nix + inputs.niri.homeModules.niri + inputs.niri.homeModules.stylix + ]; + + options.customs = { + niri = { + enable = mkEnableOption "enable niri config"; + }; + }; + + config = mkIf cfg.enable { + waybar = { + enable = true; + windowManager = "niri"; + workspaceIcons = { + # "1" = "α"; + # "2" = "β"; + # "3" = "γ"; + # "4" = "δ"; + # "5" = "ε"; + # urgent = "λ"; + # default = "ω"; + "internet" = ""; + "discord" = ""; + "chat" = "<b></b>"; + + "active" = ""; + "default" = ""; + }; + }; + rofi.enable = true; + mako.enable = true; + + home.packages = with pkgs; [ + pkgs.xwayland-satellite + swww + brightnessctl + grimblast + polkit_gnome + wl-clipboard + libnotify + wl-mirror + playerctl + ]; + + stylix.targets.niri.enable = true; + programs.niri = { + enable = true; + + settings = { + input = { + keyboard.xkb = { + layout = "us,ru"; + options = "grp:win_space_toggle,compose:ralt,ctrl:nocaps"; + }; + touchpad = { + tap = true; + dwt = false; + dwtp = true; + natural-scroll = true; + }; + warp-mouse-to-focus.enable = true; + focus-follows-mouse = { + enable = true; + max-scroll-amount = "25%"; + }; + }; + + cursor = { + theme = "Bibata-Modern-Ice"; + size = 24; + }; + + layout = { + gaps = 16; + center-focused-column = "never"; + preset-column-widths = [ + {proportion = 0.33333;} + {proportion = 0.5;} + {proportion = 0.66667;} + ]; + border = { + enable = true; + }; + focus-ring.enable = false; + }; + + animations = { + workspace-switch.enable = false; + }; + + # workspaces = { + # internet = {}; + # code = {}; + # }; + + window-rules = [ + { + matches = [ + { + app-id = "steam"; + title = ''r#"^notificationtoasts_\d+_desktop$"#''; + } + ]; + default-floating-position = { + x = 20; + y = 10; + relative-to = "bottom-right"; + }; + } + ]; + + spawn-at-startup = [ + {argv = ["swww-daemon"];} + {argv = ["mako"];} + {argv = ["swww img ${config.wallpaper}"];} + ]; + + prefer-no-csd = true; + + binds = with config.lib.niri.actions; let + scripts = "${./attachments/hypr-scripts}"; + in { + "Mod+Q".action.spawn = "alacritty"; + "Mod+D".action.spawn = ["sh" "-c" "pkill rofi || rofi -show-icons -show drun"]; + "Mod+B".action.spawn = "zen-beta"; + "Mod+E".action.spawn = ["emacsclient" "-c" "-a" "emacs"]; + "Mod+T".action.spawn = "Telegram"; + + "XF86AudioRaiseVolume".action.spawn = ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05+"]; + "XF86AudioLowerVolume".action.spawn = ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05-"]; + "XF86AudioMute".action.spawn = ["wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"]; + "XF86AudioMicMute".action.spawn = ["wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"]; + + "XF86MonBrightnessUp".action.spawn = ["brightnessctl" "s" "+5%"]; + "XF86MonBrightnessDown".action.spawn = ["brightnessctl" "s" "5%-"]; + + "XF86Favorites".action.spawn = "${scripts}/toggle-vpn.sh"; + "XF86TouchpadToggle".action.spawn = "${scripts}/switch-sink.py"; + + "XF86AudioPlay".action.spawn = ["playerctl" "play-pause"]; + + "Mod+Shift+Slash".action = show-hotkey-overlay; + + "Mod+Alt+L".action.spawn = "swaylock"; + "Mod+Shift+E".action = quit; + "Mod+Shift+P".action = power-off-monitors; + "Mod+Shift+Q".action = close-window; + + "Mod+H".action = focus-column-left; + "Mod+J".action = focus-window-down; + "Mod+K".action = focus-window-up; + "Mod+L".action = focus-column-right; + + "Mod+Shift+H".action = move-column-left; + "Mod+Shift+J".action = move-window-down; + "Mod+Shift+K".action = move-window-up; + "Mod+Shift+L".action = move-column-right; + + "Mod+Home".action = focus-column-first; + "Mod+End".action = focus-column-last; + + "Mod+Ctrl+Home".action = move-column-to-first; + "Mod+Ctrl+End".action = move-column-to-last; + + "Mod+Ctrl+H".action = focus-monitor-left; + "Mod+Ctrl+J".action = focus-monitor-down; + "Mod+Ctrl+K".action = focus-monitor-up; + "Mod+Ctrl+L".action = focus-monitor-right; + + "Mod+Shift+Ctrl+H".action = move-column-to-monitor-left; + "Mod+Shift+Ctrl+J".action = move-column-to-monitor-down; + "Mod+Shift+Ctrl+K".action = move-column-to-monitor-up; + "Mod+Shift+Ctrl+L".action = move-column-to-monitor-right; + "Mod+P" = { + repeat = false; + action.spawn-sh = "wl-mirror $(niri msg --json focused-output | jq -r .name)"; + }; + + "Mod+U".action = focus-workspace-down; + "Mod+I".action = focus-workspace-up; + + "Mod+Ctrl+U".action = move-column-to-workspace-down; + "Mod+Ctrl+I".action = move-column-to-workspace-up; + + "Mod+Shift+U".action = move-workspace-down; + "Mod+Shift+I".action = move-workspace-down; + + "Mod+WheelScrollRight".action = focus-column-right; + "Mod+WheelScrollLeft".action = focus-column-left; + + "Mod+Ctrl+WheelScrollRight".action = move-column-right; + "Mod+Ctrl+WheelScrollLeft".action = move-column-left; + + "Mod+Shift+WheelScrollDown".action = focus-column-right; + "Mod+Shift+WheelScrollUp".action = focus-column-left; + + "Mod+Ctrl+Shift+WheelScrollDown".action = move-column-right; + "Mod+Ctrl+Shift+WheelScrollUp".action = move-column-left; + + "Mod+1".action.focus-workspace = 1; + "Mod+2".action.focus-workspace = 2; + "Mod+3".action.focus-workspace = 3; + "Mod+4".action.focus-workspace = 4; + "Mod+5".action.focus-workspace = 5; + "Mod+6".action.focus-workspace = 6; + "Mod+7".action.focus-workspace = 7; + "Mod+8".action.focus-workspace = 8; + "Mod+9".action.focus-workspace = 9; + + "Mod+Shift+1".action.move-column-to-workspace = 1; + "Mod+Shift+2".action.move-column-to-workspace = 2; + "Mod+Shift+3".action.move-column-to-workspace = 3; + "Mod+Shift+4".action.move-column-to-workspace = 4; + "Mod+Shift+5".action.move-column-to-workspace = 5; + "Mod+Shift+6".action.move-column-to-workspace = 6; + "Mod+Shift+7".action.move-column-to-workspace = 7; + "Mod+Shift+8".action.move-column-to-workspace = 8; + "Mod+Shift+9".action.move-column-to-workspace = 9; + + "Mod+Comma".action = consume-window-into-column; + "Mod+Period".action = expel-window-from-column; + "Mod+BracketLeft".action = consume-or-expel-window-left; + "Mod+BracketRight".action = consume-or-expel-window-right; + + "Mod+M".action = maximize-column; + "Mod+F".action = fullscreen-window; + "Mod+C".action = center-column; + + "Mod+R".action = switch-preset-column-width; + "Mod+Minus".action.set-column-width = "-10%"; + "Mod+Equal".action.set-column-width = "+10%"; + "Mod+Shift+Minus".action.set-window-height = "-10%"; + "Mod+Shift+Equal".action.set-window-height = "+10%"; + + "Mod+V".action = toggle-window-floating; + "Mod+Ctrl+V".action = switch-focus-between-floating-and-tiling; + + "Print".action.screenshot.show-pointer = true; + "Shift+Print".action.screenshot-screen.write-to-disk = true; + "Ctrl+Shift+Print".action.screenshot-screen.write-to-disk = false; + "Alt+Print".action.screenshot-window.write-to-disk = true; + "Ctrl+Alt+Print".action.screenshot-window.write-to-disk = false; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/nvim.nix b/modules/homeModules/nvim.nix new file mode 100644 index 0000000..cd93f2d --- /dev/null +++ b/modules/homeModules/nvim.nix @@ -0,0 +1,12 @@ +{inputs, ...}: { + flake.homeModules.nvim = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + nvim.enable = lib.mkEnableOption "enable nvim"; + }; + }; +} diff --git a/modules/homeModules/picom.nix b/modules/homeModules/picom.nix new file mode 100644 index 0000000..a7835eb --- /dev/null +++ b/modules/homeModules/picom.nix @@ -0,0 +1,57 @@ +{inputs, ...}: { + flake.homeModules.picom = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + picom.enable = lib.mkEnableOption "enable picom"; + }; + + config = lib.mkIf config.customs.picom.enable { + services.picom = { + enable = true; + settings = { + fading = true; + fade-delta = 3; + blur-background = false; + corner-radius = 8; + # blur = { + # method = "dual_kawase"; + # size = 12; + # deviation = false; + # strength = 2; + # kern = "3x3box"; + # }; + backend = "glx"; + vsync = true; + mark = { + wmwin-focused = true; + overdir-focused = true; + }; + detect = { + rounded-corners = true; + client-opacity = true; + transient = true; + }; + use-ewmh-active-win = true; + glx-no-stencil = true; + use-damage = true; + }; + wintypes = { + tooltip = { + fade = true; + shadow = true; + full-shadow = false; + blur = false; + focus = true; + }; + dock = { + shadow = false; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/rofi.nix b/modules/homeModules/rofi.nix new file mode 100644 index 0000000..735dc77 --- /dev/null +++ b/modules/homeModules/rofi.nix @@ -0,0 +1,50 @@ +{inputs, ...}: { + flake.homeModules.rofi = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + rofi.enable = lib.mkEnableOption "enable rofi"; + rofi.package = lib.mkPackageOption pkgs "rofi package" {default = ["rofi"];}; + }; + + config = lib.mkIf config.customs.rofi.enable { + programs.rofi = { + enable = true; + package = config.customs.rofi.package; + theme = with config.lib.stylix.colors.withHashtag; + builtins.toFile "theme.rasi" '' + * { + font: "FiraCode Nerd Font Medium 12"; + + bg0: ${base01}; + bg1: ${base02}; + fg0: ${base04}; + + accent-color: ${base03}; + urgent-color: #ffffff; + + background-color: transparent; + text-color: @fg0; + + margin: 0; + padding: 0; + spacing: 0; + } + + ${builtins.readFile ./attachments/rofi-theme.rasi}''; + cycle = true; + plugins = with pkgs; [ + rofi-emoji + rofi-calc + ]; + extraConfig = { + kb-row-up = "Up,Ctrl+p"; + kb-row-down = "Down,Ctrl+n"; + }; + }; + }; + }; +} diff --git a/modules/homeModules/stylix.nix b/modules/homeModules/stylix.nix new file mode 100644 index 0000000..1a28fe9 --- /dev/null +++ b/modules/homeModules/stylix.nix @@ -0,0 +1,80 @@ +{inputs, ...}: { + flake.homeModules.stylixConfig = { + pkgs, + config, + lib, + inputs, + ... + }: { + imports = [ + inputs.stylix.homeModules.stylix + ]; + + options.customs = { + stylixConfig = { + enable = lib.mkEnableOption "enable stylix"; + theme = lib.mkOption {type = lib.types.str;}; + }; + wallpaper = lib.mkOption {type = with lib.types; oneOf [str path package];}; + }; + config = lib.mkIf config.customs.stylixConfig.enable { + wallpaper = with config.lib.stylix.colors.withHashtag; + pkgs.runCommand "cat.png" {} '' + pastel=${pkgs.pastel}/bin/pastel + SHADOWS=$($pastel darken 0.1 '${base05}' | $pastel format hex) + TAIL=$($pastel lighten 0.1 '${base02}' | $pastel format hex) + HIGHLIGHTS=$($pastel lighten 0.1 '${base05}' | $pastel format hex) + + ${pkgs.imagemagick}/bin/convert ${./attachments/basecat.png} \ + -fill '${base00}' -opaque black \ + -fill '${base05}' -opaque white \ + -fill '${base08}' -opaque blue \ + -fill $SHADOWS -opaque gray \ + -fill '${base02}' -opaque orange \ + -fill $TAIL -opaque green \ + -fill $HIGHLIGHTS -opaque brown \ + $out''; + stylix = { + enable = true; + targets = { + rofi.enable = false; + waybar.enable = false; + firefox.profileNames = ["ShyFox"]; + }; + + polarity = "dark"; + + base16Scheme = "${pkgs.base16-schemes}/share/themes/${config.customs.stylixConfig.theme}.yaml"; + image = config.wallpaper; + cursor = { + package = pkgs.bibata-cursors; + name = "Bibata-Modern-Ice"; + size = 24; + }; + + fonts = { + sizes.terminal = 11; + serif = { + package = pkgs.noto-fonts; + name = "Noto Serif"; + }; + + sansSerif = { + package = pkgs.rubik; + name = "Rubik"; + }; + + monospace = { + package = pkgs.nerd-fonts.fira-code; + name = "FiraCode Nerd Font"; + }; + + emoji = { + package = pkgs.noto-fonts-color-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/sxhkd.nix b/modules/homeModules/sxhkd.nix new file mode 100644 index 0000000..2172599 --- /dev/null +++ b/modules/homeModules/sxhkd.nix @@ -0,0 +1,45 @@ +{inputs, ...}: { + flake.homeModules.sxhkd = { + pkgs, + config, + lib, + ... + }: { + options.customs = { + sxhkd.enable = lib.mkEnableOption "enable sxhkd"; + }; + + config = lib.mkIf config.customs.sxhkd.enable { + services.sxhkd = { + enable = true; + keybindings = { + "{_,shift} + Print" = "xfce4-screenshooter -{r,f}"; + "{_,shift} + control + Print" = "xfce4-screenshooter -{r,f} --save /dev/stdout | xclip -i -selection clipboard -t image/png"; + "super + apostrophe" = "betterlockscreen -l"; # Lockscreen + "super + grave" = "polybar -r"; # Restart polybar + "super + q" = "alacritty"; # Open terminal + "super + d" = "rofi -show-icons -show drun"; # Open app chooser + "super + shift + d" = "CM_LAUNCHER=rofi clipmenu"; + "super + b" = "zen-beta"; # Open browser + "super + e" = "emacsclient -c -a 'emacs'"; # Open emacs + "super + Escape" = "pkill -USR1 -x sxhkd"; # Restart sxhkd + "super + shift + {e,r}" = "bspc {quit,wm -r}"; # Quit/restart bspwm + "super + {control,shift} + q" = "bspc node -{k,c}"; # Close/kill window + "super + m" = "bspc desktop -l next"; # Maximise window + "super + {t,shift + t,v,f}" = "bspc node -t {tiled,pseudo_tiled,floating,fullscreen}"; # Set window state + "super + {_,shift + }{h,j,k,l}" = "bspc node -{f,s} {west,south,north,east}"; # Focus window in the given direction + "super + {Left,Down,Up,Right}" = "bspc node -v {-20 0,0 20,0 -20,20 0}"; # Move a floating window + "super + s : {h,j,k,l}" = '' STEP=20; SELECTION={1,2,3,4};\ + bspc node -z $(echo "left -$STEP 0,bottom 0 $STEP,top 0 -$STEP,right $STEP 0" | cut -d',' -f$SELECTION) ||\ + bspc node -z $(echo "right -$STEP 0,top 0 $STEP,bottom 0 -$STEP,left $STEP 0" | cut -d',' -f$SELECTION)''; # Better window resize + "super + bracket{left,right}" = "bspc desktop -f {prev,next}.local"; # Focus next/previos desktop + "super + {_,shift + }{1-9,0}" = "bspc {desktop -f,node -d} $(bspc query -D -m focused | awk 'NR=={1-9,0}')"; # Focus/send window to the given desktop on the focused monitor + "super + o" = "bspc node -m last -f"; # Send window to the last used monitor + "super + ctrl + {1-9}" = "bspc node -o 0.{1-9}"; # Preselect the window ratio + "super + ctrl + space" = "bspc node -p cancel"; # Cansel the preselected ratio + "super + n" = "fish ~/.nixfiles/home-manager/home/services/polybar/hide.fish"; + }; + }; + }; + }; +} diff --git a/modules/homeModules/tmux.nix b/modules/homeModules/tmux.nix new file mode 100644 index 0000000..97f85dc --- /dev/null +++ b/modules/homeModules/tmux.nix @@ -0,0 +1,50 @@ +{inputs, ...}: { + flake.homeModules.tmux = { + pkgs, + lib, + config, + ... + }: { + options.customs = { + tmux.enable = lib.mkEnableOption "enable tmux config"; + }; + + config = lib.mkIf config.customs.tmux.enable { + stylix.targets.tmux.enable = true; + home.packages = with pkgs; [ + fzf + ]; + programs.tmux = { + enable = true; + prefix = "C-x"; + baseIndex = 1; + historyLimit = 10000; + extraConfig = '' + set -g mode-keys vi + set -g default-terminal "''${TERM}" + set -sg terminal-overrides ",*:RGB" + + set -g pane-border-lines simple + + set -g escape-time 0 + set -g renumber-windows on + + set -g status-style bg=default,fg=black,bright + set -g status-left "" + set -g window-status-format " #W " + set -g window-status-current-format " #W " + + set -g window-status-bell-style "bg=red,nobold" + set -g window-status-current-style \ + "#{?window_zoomed_flag,bg=yellow,bg=green,nobold}" + + bind j next-window + bind k previous-window + ''; + plugins = with pkgs.tmuxPlugins; [ + tmux-fzf + ]; + }; + }; + }; +} diff --git a/modules/homeModules/waybar.nix b/modules/homeModules/waybar.nix new file mode 100644 index 0000000..b1f6dce --- /dev/null +++ b/modules/homeModules/waybar.nix @@ -0,0 +1,131 @@ +{inputs, ...}: { + flake.homeModules.waybar = { + pkgs, + lib, + config, + ... + }: + with lib; let + cfg = config.customs.waybar; + in { + options.customs = { + waybar = { + enable = mkEnableOption "enable waybar"; + windowManager = mkOption { + description = "WM string to use with /workspaces and /language"; + default = "hyprland"; + type = types.str; + }; + workspaceIcons = mkOption { + default = { + "1" = "α"; + "2" = "β"; + "3" = "γ"; + "4" = "δ"; + "5" = "ε"; + urgent = "λ"; + default = "ω"; + }; + }; + }; + }; + + config = mkIf cfg.enable { + programs.waybar = { + enable = true; + systemd.enable = true; + style = with config.lib.stylix.colors.withHashtag; + '' + @define-color base00 ${base00}; @define-color base01 ${base01}; @define-color base02 ${base02}; @define-color base03 ${base03}; + @define-color base04 ${base04}; @define-color base05 ${base05}; @define-color base06 ${base06}; @define-color base07 ${base07}; + + @define-color base08 ${base08}; @define-color base09 ${base09}; @define-color base0A ${base0A}; @define-color base0B ${base0B}; + @define-color base0C ${base0C}; @define-color base0D ${base0D}; @define-color base0E ${base0E}; @define-color base0F ${base0F}; + '' + + builtins.readFile ./attachments/waybar-style.css; + settings = { + bar = { + layer = "top"; + height = 30; + spacing = 8; + margin-down = 5; + modules-left = ["${cfg.windowManager}/workspaces"]; + modules-center = ["clock"]; + modules-right = ["network" "custom/vpn" "memory" "temperature" "backlight" "pulseaudio" "${cfg.windowManager}/language" "tray" "battery"]; + "${cfg.windowManager}/workspaces" = { + format = "{icon}"; + "format-icons" = cfg.workspaceIcons; + }; + "${cfg.windowManager}/language" = { + format = "{} <span font-family='Material Design Icons' rise='-1000' size='medium'></span>"; + format-ru = "ru"; + format-en = "en"; + }; + "tray" = { + spacing = 10; + }; + "clock" = { + format = "{:%H:%M }"; + tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>"; + format-alt = "{:%d %h %Y }"; + }; + "memory" = { + format = "{}% "; + }; + "temperature" = { + format = "{temperatureC}°C"; + }; + "backlight" = { + format = "{percent}% {icon}"; + format-icons = ["" "" ""]; + }; + "battery" = { + "states" = { + good = 95; + warning = 30; + critical = 15; + }; + format = "{capacity}% {icon}"; + format-charging = "{capacity}% "; + format-plugged = "{capacity}% "; + format-alt = "{icon}"; + format-icons = ["" "" "" "" "" "" "" "" "" ""]; + }; + "network" = { + interface = "wlp*"; + format-wifi = "{essid} ({signalStrength}%) "; + format-ethernet = "{ipaddr}/{cidr} "; + tooltip-format = "{ifname} via {gwaddr} "; + format-linked = "{ifname} (No IP) "; + format-disconnected = ""; + }; + "custom/vpn" = { + format = "{text}"; + exec = "${./attachments/hypr-scripts/toggle-vpn.sh} waybar"; + return-type = "json"; + }; + "pulseaudio" = { + format = "{volume}% {icon} {format_source}"; + format-bluetooth = "{volume}% <span font-family='Material Design Icons' rise='-2000' font-size='x-large'></span> {format_source}"; + format-bluetooth-muted = " {format_source}"; + format-muted = " {format_source}"; + format-source = "{volume}%"; + format-source-muted = ""; + + "format-icons" = { + headphone = ""; + hands-free = ""; + headset = ""; + phone = ""; + portable = ""; + car = ""; + muted-icon = ""; + default = ["" "" ""]; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/homeModules/zen-browser.nix b/modules/homeModules/zen-browser.nix new file mode 100644 index 0000000..ae073ab --- /dev/null +++ b/modules/homeModules/zen-browser.nix @@ -0,0 +1,151 @@ +{inputs, ...}: { + flake.homeModules.zen-browser = { + pkgs, + config, + lib, + inputs, + ... + }: { + imports = [ + inputs.zen-browser.homeModules.beta + ]; + + options.customs = { + zen-browser.enable = lib.mkEnableOption "enable zen-browser"; + }; + + config = lib.mkIf config.customs.zen-browser.enable { + stylix.targets.zen-browser.profileNames = ["ZZZ"]; + xdg.mimeApps = { + enable = true; + associations.added = { + "x-scheme-handler/http" = "zen-beta.desktop"; + "x-scheme-handler/https" = "zen-beta.desktop"; + "x-scheme-handler/chrome" = "zen-beta.desktop"; + "text/html" = "zen-beta.desktop"; + "application/x-extension-htm" = "zen-beta.desktop"; + "application/x-extension-html" = "zen-beta.desktop"; + "application/x-extension-shtml" = "zen-beta.desktop"; + "application/xhtml+xml" = "zen-beta.desktop"; + "application/x-extension-xhtml" = "zen-beta.desktop"; + "application/x-extension-xht" = "zen-beta.desktop"; + }; + + defaultApplications = { + "x-scheme-handler/http" = "zen-beta.desktop"; + "x-scheme-handler/https" = "zen-beta.desktop"; + "x-scheme-handler/chrome" = "zen-beta.desktop"; + "text/html" = "zen-beta.desktop"; + "application/x-extension-htm" = "zen-beta.desktop"; + "application/x-extension-html" = "zen-beta.desktop"; + "application/x-extension-shtml" = "zen-beta.desktop"; + "application/xhtml+xml" = "zen-beta.desktop"; + "application/x-extension-xhtml" = "zen-beta.desktop"; + "application/x-extension-xht" = "zen-beta.desktop"; + "application/pdf" = "zen-beta.desktop"; + }; + }; + + programs.zen-browser = { + enable = true; + policies = { + AutofillAddressEnabled = false; + AutofillCreditCardEnabled = false; + DisableAppUpdate = true; + DisableFeedbackCommands = true; + DisableFirefoxStudies = true; + DisableTelemetry = true; + DontCheckDefaultBrowser = true; + NoDefaultBookmarks = true; + OfferToSaveLogins = false; + Certificates = { + ImportEnterpriseRoots = true; + }; + }; + + profiles.ZZZ = { + isDefault = true; + extensions = { + packages = with pkgs.nur.repos.rycee.firefox-addons; [ + bitwarden + ublock-origin + sponsorblock + return-youtube-dislikes + firefox-color + tampermonkey + duckduckgo-privacy-essentials + mal-sync + sidebery + ]; + + force = true; + }; + + settings = { + "svg.context-properties.content.enabled" = true; + "browser.search.suggest.enabled" = true; + "extensions.autoDisableScopes" = 0; + "zen.view.grey-out-inactive-windows" = false; + "zen.view.experimental-no-window-controls" = true; + }; + + search = { + force = true; + engines = { + "Brave" = { + urls = [ + {template = "https://search.brave.com/search?q={searchTerms}";} + { + type = "application/x-suggestions+json"; + template = "https://search.brave.com/api/suggest?q={searchTerms}"; + } + ]; + + icon = "https://cdn.search.brave.com/serp/v2/_app/immutable/assets/safari-pinned-tab.539899c7.svg"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!br"]; + }; + "NixOS Packages" = { + urls = [{template = "https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query={searchTerms}";}]; + icon = "https://nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!ns"]; + }; + "NixOS Options" = { + urls = [{template = "https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query={searchTerms}";}]; + icon = "https://nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!no"]; + }; + "HomeManager" = { + urls = [{template = "https://home-manager-options.extranix.com/?query={searchTerms}&release=master";}]; + icon = "https://github.com/mipmip/home-manager-option-search/blob/main/images/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!hs"]; + }; + "NixWiki" = { + urls = [{template = "https://wiki.nixos.org/w/index.php?search={searchTerms}";}]; + icon = "https://nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!nw"]; + }; + "Kinopoisk" = { + urls = [{template = "https://www.kinopoisk.ru/index.php?kp_query={searchTerms}";}]; + icon = "https://www.kinopoisk.ru/favicon.ico"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!ks"]; + }; + "MDN Docs" = { + urls = [{template = "https://developer.mozilla.org/en-US/search?q={searchTerms}";}]; + icon = "https://developer.mozilla.org/favicon-48x48.bc390275e955dacb2e65.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = ["!md"]; + }; + }; + default = "Brave"; + }; + }; + }; + }; + }; +} |
