;; Initialize straight package manager (defvar bootstrap-version) (let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" (or (bound-and-true-p straight-base-dir) user-emacs-directory))) (bootstrap-version 7)) (unless (file-exists-p bootstrap-file) (with-current-buffer (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) (goto-char (point-max)) (eval-print-last-sexp))) (load bootstrap-file nil 'nomessage)) (straight-use-package 'use-package) (setq straight-use-package-by-default t) ;; Disable frequency of GC. This helps performance both during init ;; and after init. Value is in bytes so this is 100MB, as suggested in ;; . (setq gc-cons-threshold (* 100 1024 1024)) ;; If you have something on the system clipboard, and then kill ;; something in Emacs, then by default whatever you had on the system ;; clipboard is gone and there is no way to get it back. Setting the ;; following option makes it so that when you kill something in Emacs, ;; whatever was previously on the system clipboard is pushed into the ;; kill ring. This way, you can paste it with `yank-pop'. (setq save-interprogram-paste-before-kill t) (straight-register-package 'org) (straight-register-package 'org-contrib) (use-package monokai-theme :config (load-theme 'monokai t)) (use-package blackout :demand t) (use-package nerd-icons) (use-package projectile :defer 1 :bind-keymap* (("C-c p" . projectile-command-map)) :config ;; Use Vertico (via `completing-read') for Projectile instead of ;; IDO. (setq projectile-completion-system 'default) ;; When switching projects, give the option to choose what to do. ;; This is a way better interface than having to remember ahead of ;; time to use a prefix argument on `projectile-switch-project' ;; (because, and please be honest here, when was the last time you ;; actually remembered to do that?). (setq projectile-switch-project-action 'projectile-commander) (def-projectile-commander-method ?\C-m "Find file in project." (call-interactively #'find-file)) (projectile-mode +1) :blackout t) (use-package dashboard :config (setq dashboard-center-content t dashboard-display-icons-p t dashboard-icon-type 'nerd-icons dashboard-set-file-icons t dashboard-projects-backend 'projectile) (setq dashboard-items '((recents . 5) (bookmarks . 5) (projects . 5) (agenda . 5) (registers . 5))) (dashboard-setup-startup-hook)) (use-package ctrlf :init (ctrlf-mode +1)) (use-package which-key :demand t :config (which-key-mode +1) :blackout t) (use-package nerd-icons-dired :hook (dired-mode . nerd-icons-dired-mode)) (use-package nix-mode :mode "\\.nix\\'") (use-package magit :commands (magit-status magit-get-current-branch)) (use-package diff-hl) (global-diff-hl-mode) (diff-hl-flydiff-mode) (use-package markdown-mode :mode ("README\\.md\\'" . gfm-mode) :init (setq markdown-command "multimarkdown")) ;; using an older version of auctex since newer versions changed how config ;; works and I can't figure it out (use-package tex-site :straight auctex) (use-package tex :straight nil :config (setq TeX-auto-save t) (setq TeX-parse-self t) (setq TeX-save-query nil) (setq TeX-PDF-mode t) (setq TeX-source-correlate-mode t) (setq TeX-source-correlate-start-server t) (add-to-list 'TeX-expand-list'("%sn" (lambda () server-name))) (add-to-list 'TeX-view-program-list '("Zathura" ("zathura %o" (mode-io-correlate " --synctex-forward %n:0:\"%b\" -x \"emacsclient --socket-name=%sn +%{line} %{input}\"")) "zathura")) (setcar (cdr (assoc 'output-pdf TeX-view-program-selection)) "Zathura")) (use-package latex :straight nil :mode ("\\.tex\\'" . latex-mode) :hook (LaTeX-mode . LaTeX-math-mode) (LaTeX-mode . TeX-source-correlate-mode)) (use-package font-latex :straight nil :init (setq font-latex-fontify-script nil) (setq font-latex-fontify-sectioning 'color)) (use-package org :bind* ("C-c l" . #'org-store-link) ("C-c a" . #'org-agenda) ("C-c c" . #'org-capture)) (use-package vertico :demand t :config (vertico-mode +1) ;; Ignore case... otherwise the behavior is really weird and ;; confusing. (setq read-file-name-completion-ignore-case t read-buffer-completion-ignore-case t completion-ignore-case t) ;; Don't re-sort buffer candidates. The recency order is correct. (vertico-multiform-mode +1) (setq vertico-multiform-categories '((buffer (vertico-sort-function . copy-sequence))))) (use-package prescient :config ;; Remember usage statistics across Emacs sessions. (prescient-persist-mode +1) ;; The default settings seem a little forgetful to me. Let's try ;; this out. (setq prescient-history-length 1000) ;; Common sense. (setq prescient-sort-full-matches-first t)) (use-package vertico-prescient :demand t :after vertico :config (vertico-prescient-mode +1)) (use-package apheleia :init (apheleia-global-mode +1)) (use-package company :defer 0.5 :bind (:filter company-mode ;; Remap the standard Emacs keybindings for invoking ;; completion to instead use Company. You might think this ;; could be put in the `:bind*' declaration below, but it ;; seems that `bind-key*' does not work with remappings. ([remap completion-at-point] . #'company-manual-begin) ([remap complete-symbol] . #'company-manual-begin) ;; The following are keybindings that take effect whenever ;; the completions menu is visible, even if the user has not ;; explicitly interacted with Company. :map company-active-map ;; Make TAB always complete the current selection, instead of ;; only completing a common prefix. ("" . #'company-complete-selection) ("TAB" . #'company-complete-selection) ;; When was the last time you used the C-s binding for ;; searching candidates? It conflicts with buffer search, ;; anyway. Same for the scroll commands. ("C-s" . nil) ([remap scroll-down-command] . nil) ([remap scroll-up-command] . nil) ;; The following are keybindings that only take effect if the ;; user has explicitly interacted with Company. Note that ;; `:map' from above is "sticky", and applies also below: see ;; https://github.com/jwiegley/use-package/issues/334#issuecomment-349473819. :filter (company-explicit-action-p) ;; Make RET trigger a completion if and only if the user has ;; explicitly interacted with Company, instead of always ;; doing so. ("" . #'company-complete-selection) ("RET" . #'company-complete-selection) ;; We then make and abort the completions menu ;; unless the user has interacted explicitly. Note that we ;; use `company-select-previous' instead of ;; `company-select-previous-or-abort'. I think the former ;; makes more sense since the general idea of this `company' ;; configuration is to decide whether or not to steal ;; keypresses based on whether the user has explicitly ;; interacted with `company', not based on the number of ;; candidates. ;; ;; Note that M-p and M-n work regardless of whether explicit ;; interaction has happened yet, and note also that M-TAB ;; when the completions menu is open counts as an ;; interaction. ("" . #'company-select-previous) ("" . #'company-select-next)) :bind* (:filter company-mode ;; The default keybinding for `completion-at-point' and ;; `complete-symbol' is M-TAB or equivalently C-M-i. We ;; already remapped those bindings to `company-manual-begin' ;; above. Here we make sure that they definitely invoke ;; `company-manual-begin' even if a minor mode binds M-TAB ;; directly. ("M-TAB" . #'company-manual-begin)) :config ;; Make completions display twice as soon. (setq company-idle-delay 0.15) ;; Make completions display when you have only typed one character, ;; instead of three. (setq company-minimum-prefix-length 1) ;; Always display the entire suggestion list onscreen, placing it ;; above the cursor if necessary. (setq company-tooltip-minimum company-tooltip-limit) ;; Always display suggestions in the tooltip, even if there is only ;; one. Also, don't display metadata in the echo area. (This ;; conflicts with ElDoc.) (setq company-frontends '(company-pseudo-tooltip-frontend)) ;; Show quick-reference numbers in the tooltip. (Select a completion ;; with M-1 through M-0.) (setq company-show-quick-access t) ;; Prevent non-matching input (which will dismiss the completions ;; menu), but only if the user interacts explicitly with Company. (setq company-require-match #'company-explicit-action-p) ;; Only search the current buffer to get suggestions for ;; `company-dabbrev' (a backend that creates suggestions from text ;; found in your buffers). This prevents Company from causing lag ;; once you have a lot of buffers open. (setq company-dabbrev-other-buffers nil) ;; Make the `company-dabbrev' backend fully case-sensitive, to ;; improve the UX when working with domain-specific words that have ;; particular casing. (setq company-dabbrev-ignore-case nil) (setq company-dabbrev-downcase nil) ;; When candidates in the autocompletion tooltip have additional ;; metadata, like a type signature, align that information to the ;; right-hand side. This usually makes it look neater. (setq company-tooltip-align-annotations t) (global-company-mode +1) :blackout t) (use-package company-prescient :demand t :after company :config (company-prescient-mode +1)) (use-package lsp-mode :init ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") (setq lsp-keymap-prefix "C-m") :hook (lsp-mode . lsp-enable-which-key-integration) :commands lsp :config ;; As per . (setq read-process-output-max (* 1024 1024)) ;; Disable LSP reformatting your code as you type. We use Apheleia ;; for that instead. (setq lsp-enable-on-type-formatting nil)) (use-package lsp-pyright :hook (python-mode . (lambda () (require 'lsp-pyright) (lsp)))) ; or lsp-deferred (use-package emacs :straight nil :init ;; Add prompt indicator to `completing-read-multiple'. ;; We display [CRM], e.g., [CRM,] if the separator is a comma. (defun crm-indicator (args) (cons (format "[CRM%s] %s" (replace-regexp-in-string "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" crm-separator) (car args)) (cdr args))) (advice-add #'completing-read-multiple :filter-args #'crm-indicator) ;; Do not allow the cursor in the minibuffer prompt (setq minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) ;; Support opening new minibuffers from inside existing minibuffers. (setq enable-recursive-minibuffers t) ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current ;; mode. Vertico commands are hidden in normal buffers. This setting is ;; useful beyond Vertico. (setq read-extended-command-predicate #'command-completion-default-include-p)) (setq-default fill-column 80) (setq ring-bell-function 'ignore) (setq mode-line-position (list "(%l,%c)")) ;; https://dougie.io/emacs/indentation/#tldr-the-full-configuration ; START TABS CONFIG ;; Create a variable for our preferred tab width (setq custom-tab-width 2) ;; Two callable functions for enabling/disabling tabs in Emacs (defun disable-tabs () (setq indent-tabs-mode nil)) (defun enable-tabs () (local-set-key (kbd "TAB") 'tab-to-tab-stop) (setq indent-tabs-mode t) (setq-default tab-width custom-tab-width)) ;; Hooks to Enable Tabs (add-hook 'prog-mode-hook 'enable-tabs) ;; Hooks to Disable Tabs (add-hook 'lisp-mode-hook 'disable-tabs) (add-hook 'emacs-lisp-mode-hook 'disable-tabs) ;; Language-Specific Tweaks (setq-default python-indent-offset custom-tab-width) ;; Python (setq-default js-indent-level custom-tab-width) ;; Javascript ;; Making electric-indent behave sanely (setq-default electric-indent-inhibit t) ;; Make the backspace properly erase the tab instead of ;; removing 1 space at a time. (setq backward-delete-char-untabify-method 'hungry) ;; WARNING: This will change your life ;; (OPTIONAL) Visualize tabs as a pipe character - "|" ;; This will also show trailing characters as they are useful to spot. (setq whitespace-style '(face tabs tab-mark trailing)) (custom-set-faces '(whitespace-tab ((t (:foreground "#636363"))))) (setq whitespace-display-mappings '((tab-mark 9 [124 9] [92 9]))) ; 124 is the ascii ID for '\|' (global-whitespace-mode) ; Enable whitespace mode everywhere ; END TABS CONFIG (setq display-line-numbers-type 'relative) (blink-cursor-mode 0) (global-hl-line-mode 1) (setq scroll-preserve-screen-position t) (setq scroll-conservatively 1) (setq scroll-margin 5) (defun gcm-scroll-down () (interactive) (scroll-up 1)) (defun gcm-scroll-up () (interactive) (scroll-down 1)) (global-set-key [(control down)] 'gcm-scroll-down) (global-set-key [(control up)] 'gcm-scroll-up) ;; Turn off some unneeded UI elements (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (add-hook 'text-mode-hook 'auto-fill-mode) (add-hook 'text-mode-hook 'visual-line-mode) (add-hook 'text-mode-hook 'flyspell-mode) (add-hook 'text-mode-hook 'display-line-numbers-mode) (add-hook 'prog-mode-hook 'display-line-numbers-mode) (add-to-list 'default-frame-alist '(font . "Mononoki-14"))