;;;; Appearance (defun apply-appearance-first-frame () (message "Set first frame appearance") ;; Set theme (load-theme 'my-theme +1)) (defun apply-appearance-per-frame () (message "Set per frame appearance") ;; Hide scroll bar (toggle-scroll-bar -1) ;; Use JBMono (set-frame-font "-JB-JetBrainsMonoNL Nerd Font-normal-normal-normal-*-18-*-*-*-m-0-iso10646-1" nil t)) (apply-appearance-first-frame) (apply-appearance-per-frame) (setq seen-first-frame nil) (add-hook 'after-make-frame-functions (lambda (frame) (with-selected-frame frame (apply-appearance-per-frame) (if (not seen-first-frame) (progn (setq seen-first-frame 1) (apply-appearance-first-frame)))))) ;; Hide ribbon, menu bar (menu-bar-mode -1) (tool-bar-mode -1) ;; Show colum number in status bar (column-number-mode +1) ;; Relative line numbers (setq-default display-line-numbers 'visual) ;; Highlight current line (global-hl-line-mode +1) ;; Replace yes/no prompts with y/n prompts (fset #'yes-or-no-p #'y-or-n-p) ;; Fix jumpy scrolling (setq mouse-wheel-scroll-amount '(3 ((shift) . 1)) mouse-wheel-progressive-speed nil mouse-wheel-follow-mouse +1 scroll-step 1) ;; C-n C-p scroll step ;; Disable annoying bell sound (setq ring-bell-function 'ignore) ;; Highlight matching parens faster (setq show-paren-delay 0) (setq tab-width 2) (defun disable-tabs () (setq tab-width 2) (indent-tabs-mode -1)) (defun enable-tabs () (setq tab-width 2) (indent-tabs-mode +1)) (add-hook 'prog-mode-hook 'enable-tabs) (add-hook 'lisp-mode-hook 'disable-tabs) (add-hook 'emacs-lisp-mode-hook 'disable-tabs) (let ((savedir (concat (file-name-as-directory (getenv "XDG_DATA_HOME")) "emacs/autosave/"))) (make-directory savedir t) (setq backup-directory-alist `(("." . ,savedir))) (setq auto-save-list-file-prefix (concat savedir ".saves-")) (setq auto-save-file-name-transforms `((".*" ,savedir t))) (setq tramp-auto-save-directory savedir)) (setq backup-by-copying t delete-old-versions t version-control t kept-new-versions 2 kept-old-versions 2) ;; Packages (require 'use-package) ;; Evil (Vim Emulation) (use-package evil :init (setq evil-want-C-u-scroll t evil-mode-beyond-eol t evil-mode-fine-undo t evil-undo-system 'undo-redo evil-want-keybinding nil) :config (add-hook 'evil-local-mode-hook (lambda () (setq-local interprogram-cut-function nil) (setq-local interprogram-paste-function nil))) (evil-mode +1)) (use-package better-jumper :after evil :config (setq better-jumper-context 'window better-jumper-new-window-behavior 'copy better-jumper-max-length 1000 better-jumper-use-evil-jump-advice t) (define-key evil-motion-state-map (kbd "C-o") #'better-jumper-jump-backward) (define-key evil-motion-state-map (kbd "C-i") #'better-jumper-jump-forward) (define-key evil-normal-state-map (kbd "SPC j") #'better-jumper-set-jump) (better-jumper-mode)) (use-package evil-collection :after evil :config (evil-collection-init '(magit ibuffer))) (use-package crux) ;; Avy (jump to char) (use-package avy :bind (("C-;" . avy-goto-char) ("C-:" . avy-goto-word-1) ("M-g g" . avy-goto-line))) (use-package undo-tree :after evil :config (setq undo-tree-auto-save-history nil) (advice-add #'evil-undo :override #'undo-tree-undo) (advice-add #'evil-redo :override #'undo-tree-redo) (define-key evil-normal-state-map (kbd "SPC u v") #'undo-tree-visualize) (global-undo-tree-mode)) ;; Magit (git frontend) (use-package magit) ;; Rainbow-Mode (show hex strings in color) (use-package rainbow-mode) ;; Vertico (completion helper) (use-package vertico :config (keymap-set vertico-map "M-j" #'vertico-next) (keymap-set vertico-map "M-k" #'vertico-previous) (keymap-set vertico-map "M-`" #'vertico-exit) (vertico-mode)) (use-package vertico-indexed :after vertico :init (setq vertico-indexed-start 1) :config (dotimes (i 9) (keymap-set vertico-map (format "M-%d" (+ i 1)) `(lambda () (interactive) (setq vertico--index ,i) (vertico-exit)))) (vertico-indexed-mode)) ;; Editorconfig support (use-package editorconfig :config (editorconfig-mode 1)) ;; Direnv support (nix shell, gitconfig, etc...) (use-package direnv :config (direnv-mode)) ;; Remove trailing whitespace (use-package ws-butler :config (add-hook 'prog-mode-hook #'ws-butler-mode)) ;; Markdown (use-package markdown-mode :init (setq markdown-fontify-code-blocks-natively t)) ;; Justfile (use-package just-mode) ;; String casing functions (use-package string-inflection) ;; Treesitter (use-package treesit :config (customize-set-variable 'treesit-font-lock-level 4) (setq major-mode-remap-alist '((c-mode . c-ts-mode) (csharp-mode . csharp-ts-mode) (cmake-mode . cmake-ts-mode) (c++-mode . c++-ts-mode) (css-mode . css-ts-mode) (java-mode . java-ts-mode) (json-mode . json-ts-mode) (python-mode . python-ts-mode)))) ;; Highlight operations (use-package evil-goggles :after evil :init (setq evil-goggles-duration 0.15) :config (evil-goggles-mode +1)) ;; Project (use-package projectile :config (define-key prog-mode-map (kbd "C-c p") 'projectile-command-map) (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map) (projectile-mode +1)) ;; File tree (+ related integrations) (use-package treemacs :init (setq treemacs-tag-follow-delay 0.5) :config (treemacs-resize-icons 15) (treemacs-follow-mode +1) (treemacs-tag-follow-mode +1) (treemacs-project-follow-mode +1)) (use-package treemacs-evil :after (treemacs evil)) (use-package treemacs-projectile :after (treemacs projectile)) (use-package treemacs-magit :after (treemacs magit)) ;; Explanations for keybindings (use-package which-key :config (which-key-mode +1)) ;; On the fly syntax checking (use-package flycheck :after evil :config (define-key evil-normal-state-map (kbd "SPC e") #'flycheck-list-errors)) ;; Completions (use-package company :init (setq company-minimum-prefix-length 1 company-idle-delay 0 company-selection-wrap-around t company-tooltip-align-annotations t company-tooltip-flip-when-above t company-tooltip-margin 0 company-show-quick-access 'left ;; fix lowercase completions in raw text company-dabbrev-downcase nil) :config (setq company-transformers '(delete-consecutive-dups company-sort-prefer-same-case-prefix company-sort-by-backend-importance company-sort-by-occurrence)) (define-key company-active-map (kbd "") nil) (define-key company-active-map (kbd "RET") nil) (define-key company-active-map (kbd "M-`") #'company-complete-selection) (define-key company-active-map (kbd "M-n") #'company-select-next) (define-key company-active-map (kbd "M-p") #'company-select-previous) (define-key company-active-map (kbd "M-j") #'company-select-next) (define-key company-active-map (kbd "M-k") #'company-select-previous) (global-company-mode +1)) ;; Fuzzy forawrd search in completions (use-package fussy :config (setq completion-styles '(fussy basic))) ;; Lsp (use-package lsp-mode :init (setq lsp-headerline-breadcrumb-enable nil lsp-signature-auto-activate nil lsp-signature-doc-lines 0) :config (add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration) (add-hook 'evil-insert-state-entry-hook #'lsp-signature-activate) (add-hook 'evil-insert-state-exit-hook #'lsp-signature-stop) (define-key evil-normal-state-map (kbd "SPC l r") #'lsp-rename) (define-key evil-normal-state-map (kbd "SPC l a") #'lsp-execute-code-action) (define-key evil-normal-state-map (kbd "SPC l = =") #'lsp-format-buffer) (define-key evil-normal-state-map (kbd "SPC l = r") #'lsp-format-region) (define-key evil-normal-state-map (kbd "SPC l s q") #'lsp-workspace-shutdown) (define-key evil-normal-state-map (kbd "SPC l s r") #'lsp-workspace-restart) (define-key evil-normal-state-map (kbd "SPC l i") #'lsp-describe-thing-at-point)) (use-package lsp-ui :after lsp-mode :init (setq lsp-ui-doc-enable nil lsp-ui-sideline-enable nil) :config (define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions) (define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references) (define-key evil-normal-state-map (kbd "SPC l d") #'lsp-ui-peek-find-definitions) (define-key evil-normal-state-map (kbd "SPC l u") #'lsp-ui-peek-find-references) ;; Controls inside references popup (define-key lsp-ui-peek-mode-map (kbd "j") #'lsp-ui-peek--select-next) (define-key lsp-ui-peek-mode-map (kbd "k") #'lsp-ui-peek--select-prev) (define-key lsp-ui-peek-mode-map (kbd "J") #'lsp-ui-peek--select-next-file) (define-key lsp-ui-peek-mode-map (kbd "K") #'lsp-ui-peek--select-prev-file) (define-key lsp-ui-peek-mode-map (kbd "o") #'lsp-ui-peek--goto-xref)) (use-package lsp-treemacs :after (lsp-mode treemacs)) ;; Java lsp (use-package lsp-java :after lsp-mode :hook (java-ts-mode . lsp-deferred) :config (setq lsp-java-server-install-dir (getenv "JDTLS_PATH")) (defun lsp-java--ls-command () (list "jdt-language-server" ;; this is called "configuration" for come reasn, its acually a cache "-configuration" (concat (file-name-as-directory (getenv "XDG_CACHE_HOME")) "jdtls") "-data" "../.jdtls"))) ;; Nix support (use-package nix-mode :mode "\\.nix\\'" :hook (nix-mode . disable-tabs)) ;; QML Support (setq qml-ts-mode-indent-offset 2) (use-package qml-ts-mode :config (add-hook 'qml-ts-mode-hook (lambda () (setq-local electric-indent-chars '(?\n ?\( ?\) ?{ ?} ?\[ ?\] ?\; ?,))))) (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-ts-mode)) (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode)) (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-ts-mode)) (add-to-list 'auto-mode-alist '("\\.toml\\'" . toml-ts-mode)) (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-ts-mode)) (add-hook 'rust-ts-mode-hook #'lsp-deferred) (add-hook 'c++-ts-mode-hook #'lsp-deferred) (add-hook 'typescript-ts-mode-hook #'lsp-deferred) ;; Fix indent (add-hook 'rust-ts-mode-hook (lambda () (setq-local electric-indent-chars '(?\n ?\( ?\) ?{ ?} ?\[ ?\] ?\; ?,)))) (setq gc-cons-threshold (* 1024 1024 100) read-process-output-max (* 1024 1024)) ;; Misc keybinds ;; hy3 retardation (use-package frames-only-mode :config (frames-only-mode)) (defun hyprctl (&rest args) (apply #'start-process (append '("hyprctl" "hyprctl-buf" "hyprctl" "dispatch") args))) (advice-add #'evil-window-split :override (lambda (&optional count file) (hyprctl "hy3:makegroup" "v, ephemeral") (make-frame-command))) (advice-add #'evil-window-vsplit :override (lambda (&optional count file) (hyprctl "hy3:makegroup" "h, ephemeral") (make-frame-command))) (define-key evil-normal-state-map (kbd "C-w a") (lambda () (interactive) (hyprctl "hy3:makegroup" "tab, ephemeral") (make-frame-command))) (define-key evil-normal-state-map (kbd "C-w r") #'make-frame-command) (advice-add #'evil-window-left :override (lambda (&optional count file) (hyprctl "hy3:movefocus" "l"))) (advice-add #'evil-window-right :override (lambda (&optional count file) (hyprctl "hy3:movefocus" "r"))) (advice-add #'evil-window-up :override (lambda (&optional count file) (hyprctl "hy3:movefocus" "u"))) (advice-add #'evil-window-down :override (lambda (&optional count file) (hyprctl "hy3:movefocus" "d"))) ;;; Overrides ;; stop lsp-mode from yoloing code actions when only one is present (defun lsp--select-action (actions) "Select an action to execute from ACTIONS." (cond ((seq-empty-p actions) (signal 'lsp-no-code-actions nil)) ;;((and (eq (seq-length actions) 1) lsp-auto-execute-action) ;;(lsp-seq-first actions)) (t (let ((completion-ignore-case t)) (lsp--completing-read "Select code action: " (seq-into actions 'list) (-compose (lsp--create-unique-string-fn) #'lsp:code-action-title) nil t)))))