diff options
Diffstat (limited to '.emacs.d')
| -rw-r--r-- | .emacs.d/.gitignore | 13 | ||||
| -rw-r--r-- | .emacs.d/config.org | 1241 | ||||
| -rw-r--r-- | .emacs.d/custom.el | 39 | ||||
| -rw-r--r-- | .emacs.d/early-init.el | 11 | ||||
| -rw-r--r-- | .emacs.d/init.el | 914 | ||||
| -rw-r--r-- | .emacs.d/lang/clojure.el | 26 | ||||
| -rw-r--r-- | .emacs.d/lang/java.el | 38 | ||||
| -rw-r--r-- | .emacs.d/lang/lisp.el | 9 | ||||
| -rw-r--r-- | .emacs.d/lang/lua.el | 11 | ||||
| -rw-r--r-- | .emacs.d/pkg/consult-jdt.el | 105 | ||||
| -rw-r--r-- | .emacs.d/pkg/flymake-cppcheck.el | 84 |
11 files changed, 1245 insertions, 1246 deletions
diff --git a/.emacs.d/.gitignore b/.emacs.d/.gitignore new file mode 100644 index 0000000..44ac41e --- /dev/null +++ b/.emacs.d/.gitignore @@ -0,0 +1,13 @@ +#* +.cache +auto-save-list +autosaves +backups +eln-cache +elpa +eshell +history +lock +places +projects +recentf \ No newline at end of file diff --git a/.emacs.d/config.org b/.emacs.d/config.org deleted file mode 100644 index 070de5b..0000000 --- a/.emacs.d/config.org +++ /dev/null @@ -1,1241 +0,0 @@ -#+title: Emacs Config -#+author: Venomade - -* Contents :toc_2: -- [[#straight-package-manager][Straight Package Manager]] -- [[#configs][Configs]] - - [[#custom-functions][Custom Functions]] - - [[#fix-annoyances][Fix Annoyances]] - - [[#keybindings][Keybindings]] - - [[#setup-line-numbers][Setup Line Numbers]] -- [[#general][General]] - - [[#avy][Avy]] - - [[#colors][Colors]] - - [[#dired][Dired]] - - [[#eshell][EShell]] - - [[#git][Git]] - - [[#move-text][Move Text]] - - [[#ivy-counsel][Ivy (Counsel)]] - - [[#simple-modeline][Simple Modeline]] - - [[#smart-parentheses-pairing][Smart Parentheses Pairing]] - - [[#undo-tree][Undo Tree]] -- [[#org-mode][Org Mode]] - - [[#table-of-contents][Table of Contents]] - - [[#bullet-headers][Bullet Headers]] - - [[#org-agenda][Org Agenda]] - - [[#org-babel][Org Babel]] - - [[#org-tempo][Org Tempo]] - - [[#styling][Styling]] -- [[#programming][Programming]] - - [[#projects][Projects]] - - [[#lsp][LSP]] - - [[#sidebar][Sidebar]] - - [[#treesitter][TreeSitter]] - - [[#languages][Languages]] - - [[#company][Company]] - - [[#cape][Cape]] - - [[#codeium][Codeium]] - - [[#utilities][Utilities]] -- [[#user-interface][User Interface]] - - [[#add-nerd-icons][Add Nerd Icons]] - - [[#fonts][Fonts]] - - [[#theme][Theme]] - - [[#niceties][Niceties]] - - [[#zen-mode][Zen Mode]] - -* Straight Package Manager -I'm using the Straight package manager instead of use-package because it is only available in Emacs 29 and above. -#+begin_src emacs-lisp - (defvar bootstrap-version) - (let ((bootstrap-file - (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) - (bootstrap-version 6)) - (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)) - - (setq straight-use-package-by-default t) - (setq package-native-compile t) -#+end_src - -* Configs -** Custom Functions -*** Cursor follow on split -This is so that action can be taken as soon as a split takes place, to either close/move the window or perform an action inside of it. -#+begin_src emacs-lisp - (defun split-and-follow-horizontally() - (interactive) - (split-window-below) - (balance-windows) - (other-window 1)) - - (defun split-and-follow-vertically() - (interactive) - (split-window-right) - (balance-windows) - (other-window 1)) -#+end_src -*** Duplicate Line -Duplicates the current line to the line below. -#+begin_src emacs-lisp - (defun duplicate-line () - (interactive) - (let ((column (- (point) (point-at-bol))) - (line (let ((s (thing-at-point 'line t))) - (if s (string-remove-suffix "\n" s) "")))) - (move-end-of-line 1) - (newline) - (insert line) - (move-beginning-of-line 1) - (forward-char column))) - - (keymap-global-set "C-c y d" 'duplicate-line) -#+end_src -*** Open Line above and below -Vim's o and S-o implemented for Emacs bindings. -#+begin_src emacs-lisp - (defun vi-open-line-above () - (interactive) - (unless (bolp) - (beginning-of-line)) - (newline) - (forward-line -1) - (indent-according-to-mode)) - - (defun vi-open-line-below () - (interactive) - (unless (eolp) - (end-of-line)) - (newline-and-indent)) - - (keymap-global-set "C-c O" 'vi-open-line-below) - (keymap-global-set "C-c o" 'vi-open-line-above) -#+end_src -*** C-a to indentation -Have c-a move the cursor to the start after indentation unless already there. -#+begin_src emacs-lisp - (defun smart-beginning-of-line () - (interactive) - (let ((initial-point (point))) - (back-to-indentation) - (when (eq initial-point (point)) - (move-beginning-of-line 1)))) - - (defun setup-prog-mode-c-a () - (local-set-key (kbd "C-a") 'smart-beginning-of-line)) - - (add-hook 'prog-mode-hook 'setup-prog-mode-c-a) -#+end_src -*** Automatically Cull Whitespace -Remove trailing whitespaces when saving in prog-modes. -#+begin_src emacs-lisp - (defun prog-nuke-trailing-whitespace () - (when (derived-mode-p 'prog-mode) - (delete-trailing-whitespace))) - - (add-hook 'before-save-hook 'prog-nuke-trailing-whitespace) -#+end_src -*** Quick Grep -Quickly grep both my current project and the system include directory. -#+begin_src emacs-lisp - (defun grep-symbol-at-point () - (interactive) - (let ((symbol (thing-at-point 'symbol))) - (if symbol - (counsel-rg (concat symbol)) - (message "No symbol at point.")))) - - (defun grep-symbol-in-include-at-point () - (interactive) - (let ((symbol (thing-at-point 'symbol))) - (if symbol - (counsel-rg (concat symbol) "/usr/include/") - (message "No symbol at point.")))) - - (global-set-key (kbd "C-c g") 'grep-symbol-at-point) - (global-set-key (kbd "C-c G") 'grep-symbol-in-include-at-point) -#+end_src - -** Fix Annoyances -*** Add Scroll Marginn -This adds a scroll margin at the top and bottom of 10 lines to make it easier to scroll through the buffer. -#+begin_src emacs-lisp - (setq scroll-margin 10) -#+end_src -*** Disable Backups -Living on the edge. -#+begin_src emacs-lisp - (setq backup-directory-alist - `(("." . ,(concat user-emacs-directory "backups")))) - (setq auto-save-file-name-transforms - `(("." ,(concat user-emacs-directory "autosaves/") t))) - (setq lock-file-name-transforms - `(("." ,(concat user-emacs-directory "lock") t))) -#+end_src -*** Disable Bell -Only flash, no sound, it gets annoying. -#+begin_src emacs-lisp - (setq ring-bell-function 'ignore) -#+end_src -*** Hide Warnings -Fixing warnings is for nerds. This is basically necessary after more than 5 packages. -#+begin_src emacs-lisp - (setq warning-minimum-level :emergency) -#+end_src -*** Local Bin -Add the local bin directory to PATH. -#+begin_src emacs-lisp - (setenv "PATH" (concat (concat - (concat (expand-file-name "~/.local/bin") ":") - (getenv "PATH")))) - - (setq exec-path (append exec-path (list (expand-file-name "~/.local/bin")))) -#+end_src -*** Save Place -Go back to old position on file open. -#+begin_src emacs-lisp - (save-place-mode 1) -#+end_src -*** COMMENT System Clipboard -Use system clipboard in terminal-mode. (Currently commented out due to using graphical-mode) -#+begin_src emacs-lisp - ;; credit: yorickvP on Github - (setq wl-copy-process nil) - (defun wl-copy (text) - (setq wl-copy-process (make-process :name "wl-copy" - :buffer nil - :command '("wl-copy" "-f" "-n") - :connection-type 'pipe - :noquery t)) - (process-send-string wl-copy-process text) - (process-send-eof wl-copy-process)) - (defun wl-paste () - (if (and wl-copy-process (process-live-p wl-copy-process)) - nil ; should return nil if we're the current paste owner - (shell-command-to-string "wl-paste -n | tr -d \r"))) - (setq interprogram-cut-function 'wl-copy) - (setq interprogram-paste-function 'wl-paste) -#+end_src - -** Keybindings -*** Reload Emacs -Reload Emacs by sourcing the init.el file. -#+begin_src emacs-lisp - (keymap-global-set "C-c e c" (lambda () (interactive) (load-file "~/.emacs.d/init.el"))) -#+end_src -*** Open Common Files -Open the TODO, Bookmarks and Notes from synced Documents and the config file with simple shortcuts. -#+begin_src emacs-lisp - (keymap-global-set "C-c f c" (lambda () (interactive) (find-file "~/.emacs.d/config.org"))) - (keymap-global-set "C-c f t" (lambda () (interactive) (find-file "~/Documents/TODO.org"))) - (keymap-global-set "C-c f b" (lambda () (interactive) (find-file "~/Documents/Bookmarks.org"))) - (keymap-global-set "C-c f n" (lambda () (interactive) (find-file "~/Documents/Notes.org"))) - (keymap-global-set "C-c f i" (lambda () (interactive) (find-file "~/Documents/Ideas.org"))) -#+end_src -*** Switch and Revert Buffers -Add shortcuts to switch buffers and to revert buffer. -#+begin_src emacs-lisp - (keymap-global-set "C-x C-b" 'ibuffer) - (keymap-global-set "C-c b p" 'previous-buffer) - (keymap-global-set "C-c b n" 'next-buffer) - (keymap-global-set "C-c b r" 'revert-buffer) -#+end_src -*** Compile Mode -Add shortcuts to build in compile-mode. -#+begin_src emacs-lisp - (setq compilation-scroll-output t) - (keymap-global-set "C-c m c" 'compile) - (keymap-global-set "C-c m r" 'recompile) -#+end_src -*** Emacs -Add shortcuts to various Emacs functions. -#+begin_src emacs-lisp - (keymap-global-set "C-c e b" 'eval-buffer) - (keymap-global-set "C-c e r" 'eval-region) - (keymap-global-set "C-c e s" 'eshell) - (keymap-global-set "C-c e t" 'theme-toggle) -#+end_src -*** Regex and Copy from Above -Add shortcuts to entering a regex replace and copying a line from above. -#+begin_src emacs-lisp - (keymap-global-set "C-c r" 'replace-regexp) - (keymap-global-set "C-c y a" 'copy-from-above-command) -#+end_src -*** Reverse C-x o -Add a reversed C-x o to go to previous window. -#+begin_src emacs-lisp - (keymap-global-set "C-x O" 'previous-multiframe-window) -#+end_src -*** Window Management -Add shortcuts to scrolling and moving between windows. -#+begin_src emacs-lisp - (keymap-global-set "C-c v" 'scroll-other-window) - (keymap-global-set "C-c V" 'scroll-other-window-down) - - (keymap-global-set "C-c w n" 'other-window) - (keymap-global-set "C-c w f" 'other-window) - (keymap-global-set "C-c w p" (lambda () (interactive) (other-window -1))) - (keymap-global-set "C-c w b" (lambda () (interactive) (other-window -1))) -#+end_src - -** Setup Line Numbers -*** Always show line numbers -Show line numbers and highlight the current line. -#+begin_src emacs-lisp - (add-hook 'prog-mode-hook 'display-line-numbers-mode) - (global-visual-line-mode t) - (add-hook 'prog-mode-hook (lambda () (visual-line-mode -1))) - (setq-default truncate-lines t) - (global-hl-line-mode 1) -#+end_src -*** Generally use spaces instead of tabs -Generally, as in everywhere but Go. -#+begin_src emacs-lisp - (setq-default indent-tabs-mode nil) - (setq tab-width 2) - (setq tab-stop-list (number-sequence 2 100 2)) -#+end_src -*** Highlight Column -Highlight a column at 120 chars to respect GNOME style. -#+begin_src emacs-lisp - (setq-default display-fill-column-indicator-column 120) - (add-hook 'prog-mode-hook #'display-fill-column-indicator-mode) -#+end_src - -* General -** Avy -Keybind superfast cursor movement to "C-q". -#+begin_src emacs-lisp - (use-package avy - :config - (setq avy-keys '(?a ?r ?s ?t ?n ?e ?i ?o) - avy-all-windows nil) - (bind-key* "C-q" 'avy-goto-char)) -#+end_src - -** Colors -*** Highlight Todo -Highlight TODO items so they can be reviewed later. -#+begin_src emacs-lisp - (use-package hl-todo - :hook ((org-mode . hl-todo-mode) - (prog-mode . hl-todo-mode)) - - :config - (setq hl-todo-highlight-punctuation ":" - hl-todo-highlight-faces - `(("TODO" warning bold) - ("FIXME" error bold) - ("HACK" font-lock-constant-face bold) - ("REVIEW" font-lock-doc-face bold) - ("NOTE" success bold) - ("DEPRECATED" font-lock-doc-face bold)))) -#+end_src -*** Rainbow Delimiters -Makes different brackets and other delimeters levels different colors so they can be quickly distinguished. -#+begin_src emacs-lisp - (use-package rainbow-delimiters - :hook (prog-mode . rainbow-delimiters-mode)) -#+end_src - -** Dired -A powerful built-in file manager. -#+begin_src emacs-lisp - (setq dired-listing-switches "-lh") -#+end_src - -** EShell -A built in posix shell. -#+begin_src emacs-lisp - ;; Define custom faces for the prompt. These inherit from standard faces so they - ;; automatically adapt to your current theme. - (defface eshell-prompt-user-face - '((t (:inherit font-lock-keyword-face))) - "Face for the username in the eshell prompt." - :group 'eshell-prompt) - - (defface eshell-prompt-venv-face - '((t (:inherit font-lock-string-face))) - "Face for the virtualenv name in the eshell prompt." - :group 'eshell-prompt) - - (defface eshell-prompt-dir-face - '((t (:inherit dired-directory))) - "Face for the directory path in the eshell prompt." - :group 'eshell-prompt) - - (defface eshell-prompt-git-face - '((t (:inherit magit-tag))) - "Face for the git branch in the eshell prompt." - :group 'eshell-prompt) - - (defface eshell-prompt-git-dirty-face - '((t (:inherit eshell-prompt-git-face))) - "Face for the git dirty status in the eshell prompt." - :group 'eshell-prompt) - - (defface eshell-prompt-symbol-face - '((t (:inherit font-lock-builtin-face))) - "Face for the prompt symbol (e.g. λ) in the eshell prompt." - :group 'eshell-prompt) - - ;; A helper function to abbreviate long directory names. - (defun my-abbreviate-dir (dir) - "Abbreviate DIR to show only the first and the last two components. - For example, \"~/Projects/Learning/C/GeneticsProject/TsodingGenetics\" becomes - \"~/.../GeneticsProject/TsodingGenetics\"." - (let* ((abbrev (abbreviate-file-name dir)) - (components (split-string abbrev "/" t)) ; t omits empty strings - (num-components (length components))) - (if (>= num-components 4) - (concat (car components) "/.../" - (mapconcat #'identity (last components 2) "/")) - abbrev))) - - ;; These are the same helper functions for git information you had. - (defun my-prompt-git-branch () - "Return the current git branch or short commit hash, if available." - (when (and (executable-find "git") - (locate-dominating-file default-directory ".git")) - (with-temp-buffer - (let ((ret (call-process "git" nil t nil "symbolic-ref" "--short" "HEAD"))) - (if (zerop ret) - (string-trim (buffer-string)) - (when (zerop (call-process "git" nil t nil "rev-parse" "--short" "HEAD")) - (string-trim (buffer-string)))))))) - - (defun my-prompt-git-dirty () - "Return a dirty flag (✗ if dirty, ✓ if clean) for the git repository." - (when (my-prompt-git-branch) - (with-temp-buffer - (call-process "git" nil t nil "status" "--porcelain") - (if (> (buffer-size) 0) "✗" "✓")))) - - ;; Finally, build the prompt itself. - (defun eshell-prompt () - "Custom eshell prompt with theme-derived colors and shortened directory path." - (let* ((user (propertize (user-login-name) 'face 'eshell-prompt-user-face)) - (venv (when-let ((venv (getenv "VIRTUAL_ENV"))) - (concat (propertize "(" 'face 'eshell-prompt-venv-face) - (propertize (file-name-nondirectory venv) 'face 'eshell-prompt-venv-face) - (propertize ")" 'face 'eshell-prompt-venv-face)))) - (path (propertize (my-abbreviate-dir (eshell/pwd)) 'face 'eshell-prompt-dir-face)) - (git-branch (my-prompt-git-branch)) - (git-info (when git-branch - (concat " " (propertize "on" 'face 'font-lock-number-face) " " - (propertize git-branch 'face 'eshell-prompt-git-face) - (propertize (my-prompt-git-dirty) 'face 'eshell-prompt-git-dirty-face)))) - (prompt (concat user " " (propertize "in" 'face 'font-lock-number-face) " " - (if venv (concat venv " ") "") - path git-info "\n" - (propertize "λ" 'face 'eshell-prompt-symbol-face) " "))) - prompt)) - - ;; Tell eshell to use our prompt function. - (setq eshell-prompt-function 'eshell-prompt) - (setq eshell-prompt-regexp "^[^λ\n]*λ ") -#+end_src -** Git -Tools for the primary version control system. -*** Magit -A very extensive Git GUI for Emacs. -#+begin_src emacs-lisp - (use-package magit - :after nerd-icons - :custom - (magit-format-file-function #'magit-format-file-nerd-icons)) -#+end_src -*** Magit Todos -Show Todo list in Magit. -#+begin_src emacs-lisp - (use-package magit-todos - :after magit - :config (magit-todos-mode 1)) -#+end_src -*** Magit Forge -Work with Git Forges from within Emacs. -#+begin_src emacs-lisp - (use-package forge - :after magit - :config - (setq auth-sources '("~/.authinfo"))) -#+end_src - -** Move Text -Move text up and down with simple keybindings. -#+begin_src emacs-lisp - (use-package move-text - :config - (keymap-global-set "M-p" 'move-text-up) - (keymap-global-set "M-n" 'move-text-down)) -#+end_src - -** Ivy (Counsel) -*** Counsel -Adds better fuzzy completion to many Emacs commands. -#+begin_src emacs-lisp - (use-package counsel - :after ivy - :config - (counsel-mode 1) - (keymap-global-set "C-c f r" 'counsel-buffer-or-recentf) - (keymap-global-set "C-c f f" 'counsel-fzf) - (keymap-global-set "C-c f g" 'counsel-rg) - (keymap-global-set "C-c f l" 'counsel-locate) - (keymap-global-set "C-c s" 'swiper)) -#+end_src -*** Ivy -Adds fuzzy completion to basic Emacs commands. -#+begin_src emacs-lisp - (use-package ivy - :custom - (setq ivy-use-virtual-buffers t) - (setq ivy-count-format "(%d/%d) ") - (setq enable-recursive-minibuffers t) - :config - (ivy-mode 1)) -#+end_src -*** Ivy Rich -Adds Icons to all the new fuzzy completed Emacs commands. -#+begin_src emacs-lisp - (use-package ivy-rich - :after ivy - :init (ivy-rich-mode 1) - :custom - (ivy-virtual-abbreviate 'full - ivy-rich-switch-buffer-align-virtual-buffer t - ivy-rich-path-style 'abbrev)) -#+end_src - -** Simple Modeline -Make the modeline simple by hiding modes. -#+begin_src emacs-lisp - (setq-default mode-line-format (delq 'mode-line-modes mode-line-format) - display-time-24hr-format t - display-time-default-load-average nil) - (display-battery-mode 1) - (display-time-mode 1) -#+end_src - -** Smart Parentheses Pairing -Automatically deals with parentheses in pairs. -#+begin_src emacs-lisp - (use-package smartparens - :hook (prog-mode text-mode markdown-mode) - :config - (require 'smartparens-config) - (sp-use-paredit-bindings)) -#+end_src - -** Undo Tree -Makes undo history like a Git commit tree, very powerful. -#+begin_src emacs-lisp - (use-package undo-tree - :config - (setq undo-tree-history-directory-alist - `(("." . ,(concat user-emacs-directory "undo")))) - (global-undo-tree-mode 1)) -#+end_src - -* Org Mode -** Table of Contents -Automatically generate a table of contents for an Org file. -#+begin_src emacs-lisp - (use-package toc-org - :commands toc-org-enable - :init (add-hook 'org-mode-hook 'toc-org-enable) - :config (setq org-src-window-setup 'current-window)) - (add-hook 'org-mode-hook 'org-indent-mode) -#+end_src - -** Bullet Headers -Stylize Org Mode headers with Nerd Icons. -#+begin_src emacs-lisp - (use-package org-bullets - :config - (setq org-bullets-bullet-list '( - "•" - "•" - "◦" - "◦" - "◦"))) - (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))) -#+end_src - -** Org Agenda -Manage a Todo list, a Calendar, and other organization tools with Org. -#+begin_src emacs-lisp - (setq org-agenda-files '("~/Documents/Org/agenda.org")) - (setq org-fancy-priorities-list '("[A]" "[B]" "[C]") - org-priority-faces - '((?A :foreground "#ff6c6b" :weight bold) - (?B :foreground "#ffff91" :weight bold) - (?C :foreground "#aaffaa" :weight bold))) - (setq org-agenda-custom-commands - '(("v" "View Agenda" - ((tags "PRIORITY=\"A\"" - ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - (org-agenda-overriding-header "HIGH PRIORITY:"))) - (tags "PRIORITY=\"B\"" - ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - (org-agenda-overriding-header "Medium Priority:"))) - (tags "PRIORITY=\"C\"" - ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - (org-agenda-overriding-header "low priority:"))) - (agenda "") - (alltodo ""))))) -#+end_src - -** Org Babel -Setup literate progamming in Org Mode. -*** Config -Don't ask for conformation when evaluating source blocks. -#+begin_src emacs-lisp - (setq org-confirm-babel-evaluate nil) -#+end_src -*** Load Languages -#+begin_src emacs-lisp - (org-babel-do-load-languages - 'org-babel-load-languages - '((python . t) - (lua . t))) -#+end_src - -** Org Tempo -This provides shorthands for Org functions. -#+begin_src emacs-lisp - (require 'org-tempo) -#+end_src - -** Styling -Hide markers for bold, italic and other types of text styling. -#+begin_src emacs-lisp - (setq org-hide-emphasis-markers t) -#+end_src - -* Programming -** Projects -Manage Project folders from within Emacs. -*** Project.el -Use project.el and set shortcuts with prefix "C-c p". -#+begin_src emacs-lisp - (require 'project) - - (keymap-global-set "C-c p b" 'project-list-buffers) - (keymap-global-set "C-c p c" 'project-compile) - (keymap-global-set "C-c p e" 'project-dired) - (keymap-global-set "C-c p f" 'project-find-file) - (keymap-global-set "C-c f p" 'project-find-file) - (keymap-global-set "C-c p g" 'project-find-regexp) - (keymap-global-set "C-c p o" 'project-find-dir) - (keymap-global-set "C-c p p" 'project-switch-project) -#+end_src -*** Disproject -Magit like interface ontop of project.el. -#+begin_src emacs-lisp - (use-package disproject - ;; Replace `project-prefix-map' with `disproject-dispatch'. - :bind ( :map ctl-x-map - ("p" . disproject-dispatch))) -#+end_src -*** Run Project -Run the current project. -#+begin_src emacs-lisp - (require 'project) - - (defvar-local project-binary-name nil) - (defvar-local project-binary-args nil) - (defvar-local project-debugger "gf2") - - (defun get-project-binary-info () - (let* ((project (project-current t)) - (project-root (project-root project)) - (binary-name (or project-binary-name - (downcase - (file-name-nondirectory (directory-file-name project-root))))) - (binary-path (expand-file-name binary-name project-root)) - (args (or project-binary-args ""))) - (list binary-path args))) - - (defun run-project-binary () - (interactive) - (let* ((binary-info (get-project-binary-info)) - (binary-path (nth 0 binary-info)) - (args (nth 1 binary-info)) - (original-compile-command compile-command)) - (if (file-executable-p binary-path) - (progn - (setq compile-command (concat binary-path " " args)) - (unwind-protect - (compile compile-command) - (setq compile-command original-compile-command))) - (error "Binary '%s' not found or not executable in project root" binary-path)))) - - (defun debug-project-binary () - (interactive) - (let* ((binary-info (get-project-binary-info)) - (binary-path (nth 0 binary-info)) - (args (nth 1 binary-info)) - (debugger (or project-debugger "gdb")) - (debug-command (concat debugger " --args " binary-path " " args)) - (original-compile-command compile-command)) - (if (file-executable-p binary-path) - (progn - (setq compile-command debug-command) - (unwind-protect - (compile compile-command) - (setq compile-command original-compile-command))) - (error "Binary '%s' not found or not executable in project root" binary-path)))) - - ;; Mark 'project-binary-name' and 'project-binary-args' as safe for dir-locals. - (put 'project-binary-name 'safe-local-variable #'stringp) - (put 'project-binary-args 'safe-local-variable #'stringp) - - (keymap-global-set "C-c p r" 'run-project-binary) - (keymap-global-set "C-c p d" 'debug-project-binary) -#+end_src - -** LSP -*** LSP Mode -Use language servers to provide info and completion. -#+begin_src emacs-lisp - (use-package lsp-mode - :init - (setq lsp-completion-provider :none - lsp-keymap-prefix "C-c l" - lsp-headerline-breadcrumb-enable nil - lsp-modeline-code-actions-enable nil) - :commands lsp lsp-deferred - :config - (lsp-enable-snippet t)) - - (keymap-global-set "C-c l d" 'lsp-describe-thing-at-point) -#+end_src - -*** LSP Mode - Undo Tree compatibility -#+begin_src emacs-lisp - (with-eval-after-load 'lsp-mode - (defun my/lsp--should-ignore-file (filename) - (or (string-match-p "\\.emacs[-_.]backups?/" filename) - (string-match-p "\\.emacs[-_.]undo/" filename) - (string-match-p "/\\.emacs\\.d/undo/" filename) - (string-match-p "/\\.emacs\\.d/backups/" filename) - (string-match-p "/#.*#$" filename) - (string-match-p "/.*~$" filename) - (string-match-p "/.*\\.~undo-tree~$" filename))) - - (advice-add 'lsp--on-did-open :before - (lambda (&rest args) - (let ((file (lsp--uri-to-path (gethash "uri" (cl-first args))))) - (when (my/lsp--should-ignore-file file) - (cl-return-from lsp--on-did-open)))) - '((name . ignore-emacs-backup-open))) - - (advice-add 'lsp--on-did-save :before - (lambda (&rest args) - (let ((file (lsp--uri-to-path (gethash "uri" (cl-first args))))) - (when (my/lsp--should-ignore-file file) - (cl-return-from lsp--on-did-save)))) - '((name . ignore-emacs-backup-save)))) -#+end_src - -*** YASnippet -Autocomplete Snippets to write common code patterns faster. -#+begin_src emacs-lisp - (use-package yasnippet - :config - (setq yas-snippet-dirs '("~/Documents/snippets")) - (yas-global-mode 1) - (keymap-global-set "M-<tab>" 'yas-next-field-or-maybe-expand) - (keymap-global-set "C-'" 'yas-expand)) - - (straight-use-package - '(yasnippet-capf :type git :host github :repo "elken/yasnippet-capf")) - - (use-package yasnippet-treesitter-shim - :straight (:host github :repo "fbrosda/yasnippet-treesitter-shim" - :files ("snippets/*")) - :no-require t - :config - (add-to-list 'yas-snippet-dirs - (straight--build-dir "yasnippet-treesitter-shim"))) -#+end_src - -*** DevDocs -Search documentation from within Emacs. -#+begin_src emacs-lisp - (use-package devdocs - :config - (keymap-global-set "C-c d" 'devdocs-lookup)) -#+end_src - -** Sidebar -Project file sidebar for project wide visual grepping. -#+begin_src emacs-lisp - (use-package dired-sidebar - :init - (setq dired-sidebar-theme 'icons - dired-sidebar-use-term-integration t - dired-sidebar-width 30 - dired-sidebar-no-delete-other-windows t - dired-sidebar-should-follow-file t)) - - (defun open-project-sidebar () - "Toggle `dired-sidebar' at the project root." - (interactive) - (let ((default-directory (project-root (project-current t)))) - (dired-sidebar-toggle-sidebar))) - - (keymap-global-set "C-c p s" 'open-project-sidebar) - - (defun dired-sidebar-header-line () - "Set a minimal header line for dired-sidebar buffers." - (setq header-line-format - (propertize - (concat " " (file-name-nondirectory - (directory-file-name default-directory))) - 'face 'bold))) - - (add-hook 'dired-sidebar-mode-hook #'dired-sidebar-header-line) - - (defun dired-sidebar-clean-top-line () - "Hide the top directory line in `dired-sidebar` buffers." - (save-excursion - (goto-char (point-min)) - (when (looking-at "^ \\(/.*\\):.*$") - (let ((inhibit-read-only t)) - (delete-region (point) (progn (forward-line 1) (point))))))) - - (add-hook 'dired-sidebar-mode-hook #'dired-sidebar-clean-top-line) - - (add-hook 'dired-sidebar-mode-hook - (lambda () - (setq mode-line-format nil))) ;; disable modeline in sidebar -#+end_src - -** TreeSitter -Use advanced highlighting by default. -#+begin_src emacs-lisp - (require 'treesit) - (use-package treesit-auto - :config - (global-treesit-auto-mode)) - (setq major-mode-remap-alist (treesit-auto--build-major-mode-remap-alist)) -#+end_src - -** Languages -*** C -The Classic. -#+begin_src emacs-lisp - (add-hook 'c-mode-hook #'lsp) - (add-hook 'c-ts-mode-hook #'lsp) - - ;; Use GNU Style in LSP-Mode for C - (with-eval-after-load 'lsp-clangd - (setq lsp-clients-clangd-args '("--header-insertion-decorators=0" "--fallback-style=GNU"))) - - ;; Automatically write header guards - (defun insert-header-guards () - (when (and (buffer-file-name) - (string-match "\\.h\\'" (buffer-file-name))) - (let* ((filename (file-name-nondirectory (buffer-file-name))) - (guard (upcase (replace-regexp-in-string "[^a-zA-Z0-9]" "_" filename)))) - (when (zerop (buffer-size)) ; Only insert if the file is empty - (insert (format "#ifndef %s\n#define %s\n\n\n$0\n\n#endif // %s\n" - guard guard guard)) - (goto-char (point-min)) - (search-forward "$0") - (delete-char -3))))) - - (add-hook 'find-file-hook 'insert-header-guards) -#+end_src -*** Go -A simple C-like language with a GC. -#+begin_src emacs-lisp - (use-package go-mode - :config - (setenv "PATH" (concat (concat - (concat (expand-file-name "/usr/local/go/bin") ":") - (getenv "PATH")))) - (setenv "PATH" (concat (concat - (concat (expand-file-name "~/.go/bin") ":") - (getenv "PATH")))) - - (setq exec-path (append exec-path (list (expand-file-name "/usr/local/go/bin")))) - (setq exec-path (append exec-path (list (expand-file-name "~/.go/bin")))) - (add-hook 'go-mode-hook - (lambda () - (setq tab-width 4))) - :hook - (go-mode . lsp)) -#+end_src -*** Haskell -Functionally Scottish. -#+begin_src emacs-lisp - (use-package haskell-mode - :config - (setenv "PATH" (concat (concat - (concat (expand-file-name "~/.ghcup/bin") ":") - (getenv "PATH")))) - - (setq exec-path (append exec-path (list (expand-file-name "~/.ghcup/bin"))))) - - (use-package lsp-haskell - :hook - (haskell-mode . lsp)) -#+end_src -*** LISP -Programming for Programmers. -#+begin_src emacs-lisp - (use-package sly - :config - (setq inferior-lisp-program "ros -Q run" - browse-url-browser-function '(("hyperspec" . eww-browse-url) ("." . browse-url-default-browser))) - (add-hook 'sly-mrepl-mode-hook 'smartparens-mode) - (add-hook 'sly-mrepl-mode-hook 'company-mode) - (add-hook 'lisp-mode-hook - (lambda () - (define-key lisp-mode-map (kbd "C-c d") 'sly-documentation)))) -#+end_src -*** Lua -A simple Python-like language with many implementations. -#+begin_src emacs-lisp - (straight-use-package - '(lua-mode :type git :host github :repo "immerrr/lua-mode")) - (add-hook 'lua-mode-hook #'lsp) - - (setq lua-indent-nested-block-content-align nil) - (setq lua-indent-close-paren-align nil) - - (defun lua-at-most-one-indent (old-function &rest arguments) - (let ((old-res (apply old-function arguments))) - (if (> old-res lua-indent-level) lua-indent-level old-res))) - - (advice-add #'lua-calculate-indentation-block-modifier - :around #'lua-at-most-one-indent) - - (setq lua-indent-level 2) - (setq lua-electric-flag nil) - (defun lua-abbrev-mode-off () (abbrev-mode 0)) - (add-hook 'lua-mode-hook 'lua-abbrev-mode-off) - (setq save-abbrevs nil) ;; is this still needed? -#+end_src -*** OCaml -Installed with OPAM -#+begin_src emacs-lisp - (setenv "PATH" (concat (concat - (concat (expand-file-name "~/.opam/default/bin") ":") - (getenv "PATH")))) - - (setq exec-path (append exec-path (list (expand-file-name "~/.opam/default/bin")))) - - (use-package tuareg - :hook - (tuareg-mode . lsp)) - - (add-to-list 'load-path "/home/venomade/.opam/default/share/emacs/site-lisp") - (require 'ocp-indent) - (require 'dune) - (require 'utop) -#+end_src -*** Typescript -#+begin_src emacs-lisp - (setenv "PATH" (concat (concat - (concat (expand-file-name "~/.bun/bin") ":") - (getenv "PATH")))) - - (setq exec-path (append exec-path (list (expand-file-name "~/.bun/bin")))) - - (add-hook 'typescript-ts-mode-hook 'lsp) - (add-hook 'tsx-ts-mode-hook 'lsp) - - (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode)) - (add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode)) - (add-to-list 'auto-mode-alist '("\\.json\\'" . json-ts-mode)) - - ;; Tailwind - (use-package lsp-tailwindcss - :straight '(lsp-tailwindcss :type git :host github :repo "merrickluo/lsp-tailwindcss") - :init (setq lsp-tailwindcss-add-on-mode t) - :config - (dolist (tw-major-mode - '(css-mode - css-ts-mode - typescript-mode - typescript-ts-mode - tsx-ts-mode - js2-mode - js-ts-mode)) - (add-to-list 'lsp-tailwindcss-major-modes tw-major-mode))) -#+end_src -*** Zig -A systems language with emphasis on metaprogramming. -#+begin_src emacs-lisp - (use-package zig-mode - :hook (zig-mode . lsp)) -#+end_src - -** Company -A powerful auto-completion utility. -#+begin_src emacs-lisp - (use-package company - :config - (define-key company-active-map (kbd "RET") nil) - (define-key company-active-map (kbd "<return>") nil) - (define-key company-active-map (kbd "C-m") nil) - - ;; TAB indents or selects a completion - (define-key company-active-map (kbd "TAB") #'company-complete-selection) - (define-key company-active-map (kbd "<tab>") #'company-complete-selection) - - ;; Use C-p and C-n to navigate the completion list - (define-key company-active-map (kbd "C-p") #'company-select-previous) - (define-key company-active-map (kbd "C-n") #'company-select-next) - - ;; Restore normal tab behavior outside company-mode completions - (define-key company-mode-map (kbd "TAB") #'indent-for-tab-command) - (define-key company-mode-map (kbd "<tab>") #'indent-for-tab-command) - - ;; Disable Autocomplete - (setq company-idle-delay 0) - - ;; Disable Case Sensitivity - (setq completion-ignore-case t) - - ;; Bind M-/ to company-complete - (define-key global-map (kbd "M-/") 'company-complete) - (define-key global-map (kbd "M-?") 'dabbrev-expand) - :hook - (prog-mode . company-mode)) - - (use-package company-quickhelp - :config - (company-quickhelp-mode 1) - (setq company-quickhelp-delay 0.5) - (setq company-quickhelp-color-background (face-attribute 'company-tooltip :background)) - (add-hook 'enable-theme-functions - (lambda (_) - (setq company-quickhelp-color-background (face-attribute 'company-tooltip :background))))) - -#+end_src - -** Cape -Add non-lsp completions to the capf. -#+begin_src emacs-lisp - (use-package cape - :ensure t - :config - (keymap-global-set "C-c c" 'cape-prefix-map) - (setq dabbrev-case-fold-search t) - ;;(add-hook 'completion-at-point-functions #'cape-dabbrev) ;; TODO: Check if this is slowing down comments? - (add-hook 'completion-at-point-functions #'cape-file) - (add-hook 'completion-at-point-functions #'cape-elisp-block) - (add-hook 'completion-at-point-functions #'yasnippet-capf)) -#+end_src - -** Codeium -#+begin_src emacs-lisp - (straight-use-package - '(codeium :type git :host github :repo "Exafunction/codeium.el")) - - (setq codeium-api-enabled - (lambda (api) - (memq api '(GetCompletions Heartbeat CancelRequest GetAuthToken RegisterUser auth-redirect AcceptCompletion)))) - - (defun my-codeium/document/text () - (buffer-substring-no-properties (max (- (point) 3000) (point-min)) (min (+ (point) 1000) (point-max)))) - (defun my-codeium/document/cursor_offset () - (codeium-utf8-byte-length - (buffer-substring-no-properties (max (- (point) 3000) (point-min)) (point)))) - (setq codeium/document/text 'my-codeium/document/text) - (setq codeium/document/cursor_offset 'my-codeium/document/cursor_offset) - - (defun my/codeium/completion () - "Decouple codeium from other completions" - (interactive) - (cape-interactive #'codeium-completion-at-point)) - - (keymap-global-set "C-c a" 'my/codeium/completion) -#+end_src - -** Utilities -*** Flycheck -Syntax checking for Emacs. -#+begin_src emacs-lisp - (use-package flycheck - :defer t - :init (global-flycheck-mode 1) - :config - (setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc)) - (setq-default flycheck-cppcheck-args "--enable=all") - (flycheck-add-next-checker 'c/c++-gcc 'c/c++-cppcheck 'append) - (setq flycheck-indication-mode nil) - (set-face-attribute 'flycheck-warning nil :underline nil)) ;; Disable Warning Underline (NOT WORKING) - - (add-to-list 'display-buffer-alist - '("\\*Flycheck errors\\*" - (display-buffer-reuse-window - display-buffer-in-side-window) - (side . bottom) - (window-height . 0.2))) ;; Set flycheck error list to only take up the bottom 20% of the window -#+end_src - -* User Interface -** Add Nerd Icons -Use Icons from Nerd Font to add a little modern spice to Emacs. -#+begin_src emacs-lisp - (use-package nerd-icons - :if (display-graphic-p)) - - (use-package nerd-icons-dired - :hook - (dired-mode . nerd-icons-dired-mode)) - - (use-package nerd-icons-ivy-rich - :init (nerd-icons-ivy-rich-mode 1)) - - (setq welcome-dashboard-use-nerd-icons t) -#+end_src - -** Fonts -*** Set Font -Set font for both Monospace and Proportional text. -#+begin_src emacs-lisp - (defvar fontconf - '((font . "Aporetic Sans Mono") - (size . 11))) - - (set-face-attribute 'variable-pitch nil - :font (cdr (assoc 'font fontconf)) - :height (* (cdr (assoc 'size fontconf)) 10) - :weight 'regular) - - (set-face-attribute 'fixed-pitch nil - :font (cdr (assoc 'font fontconf)) - :height (* (cdr (assoc 'size fontconf)) 10) - :weight 'regular) - - (set-face-attribute 'default nil - :font (cdr (assoc 'font fontconf)) - :height (* (cdr (assoc 'size fontconf)) 10) - :weight 'regular) - - - (add-to-list 'default-frame-alist - `(font . ,(concat (cdr (assoc 'font fontconf)) "-" (number-to-string (cdr (assoc 'size fontconf)))))) - - (set-face-attribute 'font-lock-comment-face nil - :slant 'italic) - - (set-face-attribute 'font-lock-keyword-face nil - :slant 'italic) - - ;;(set-frame-font "-misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1" t t) -#+end_src -*** Ligatures -Make ligature symbols out of common function symbols. -#+begin_src emacs-lisp - (dolist (char/ligature-re - `((?- . ,(rx (or (or "-->" "-<<" "->>" "-|" "-~" "-<" "->") (+ "-")))) - (?/ . ,(rx (or (or "/==" "/=" "/>" "/**" "/*") (+ "/")))) - (?* . ,(rx (or (or "*>" "*/") (+ "*")))) - (?< . ,(rx (or (or "<<=" "<<-" "<|||" "<==>" "<!--" "<=>" "<||" "<|>" "<-<" - "<==" "<=<" "<-|" "<~>" "<=|" "<~~" "<$>" "<+>" "</>" - "<*>" "<->" "<=" "<|" "<:" "<>" "<$" "<-" "<~" "<+" - "</" "<*") - (+ "<")))) - (?: . ,(rx (or (or ":?>" "::=" ":>" ":<" ":?" ":=") (+ ":")))) - (?= . ,(rx (or (or "=>>" "==>" "=/=" "=!=" "=>" "=:=") (+ "=")))) - (?! . ,(rx (or (or "!==" "!=") (+ "!")))) - (?> . ,(rx (or (or ">>-" ">>=" ">=>" ">]" ">:" ">-" ">=") (+ ">")))) - (?& . ,(rx (+ "&"))) - (?| . ,(rx (or (or "|->" "|||>" "||>" "|=>" "||-" "||=" "|-" "|>" - "|]" "|}" "|=") - (+ "|")))) - (?. . ,(rx (or (or ".?" ".=" ".-" "..<") (+ ".")))) - (?+ . ,(rx (or "+>" (+ "+")))) - (?\[ . ,(rx (or "[<" "[|"))) - (?\{ . ,(rx "{|")) - (?\? . ,(rx (or (or "?." "?=" "?:") (+ "?")))) - (?# . ,(rx (or (or "#_(" "#[" "#{" "#=" "#!" "#:" "#_" "#?" "#(") - (+ "#")))) - (?\; . ,(rx (+ ";"))) - (?_ . ,(rx (or "_|_" "__"))) - (?~ . ,(rx (or "~~>" "~~" "~>" "~-" "~@"))) - (?$ . ,(rx "$>")) - (?^ . ,(rx "^=")) - (?\] . ,(rx "]#")))) - (let ((char (car char/ligature-re)) - (ligature-re (cdr char/ligature-re))) - (set-char-table-range composition-function-table char - `([,ligature-re 0 font-shape-gstring])))) -#+end_src -*** Font Zooming -Bind both scroling and +/- to zooming. -#+begin_src emacs-lisp - (global-set-key (kbd "C-=") 'text-scale-increase) - (global-set-key (kbd "C--") 'text-scale-decrease) - (global-set-key (kbd "<C-wheel-up>") 'text-scale-increase) - (global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease) -#+end_src - -** Theme -Set the theme to a nice dark one. -#+begin_src emacs-lisp - (use-package kaolin-themes - :config - (set-window-margins nil 0)) - - (add-hook 'emacs-startup-hook - (lambda () - (load-theme 'kaolin-light t))) - - (defun theme-toggle () - "Toggle between two Emacs themes: doom-one and doom-dracula." - (interactive) - (let ((theme-a 'kaolin-light) - (theme-b 'kaolin-dark)) - (cond - ((member theme-a custom-enabled-themes) - (disable-theme theme-a) - (load-theme theme-b t)) - ((member theme-b custom-enabled-themes) - (disable-theme theme-b) - (load-theme theme-a t)) - (t - (load-theme theme-a t))))) -#+end_src - -** Niceties -*** Disable Extra GUI Features -Disable GUI features to simplify frames. -#+begin_src emacs-lisp - (menu-bar-mode -1) - (tool-bar-mode -1) - (scroll-bar-mode -1) - (setq inhibit-startup-screen t) -#+end_src -*** No Scroll Jump -Scroll line by line instead of jumping multiple. -#+begin_src emacs-lisp - (setq scroll-conservatively 100) - (setq scroll-step 1) -#+end_src -*** Small Fringes -Reduce fringe size to 1px. -#+begin_src emacs-lisp - (set-fringe-mode 1) -#+end_src - -** Zen Mode -Center the edtior with Olivetti for distraction-free editing. -#+begin_src emacs-lisp - (use-package olivetti - :config - (keymap-global-set "C-c z" 'olivetti-mode)) -#+end_src diff --git a/.emacs.d/custom.el b/.emacs.d/custom.el new file mode 100644 index 0000000..1bca6e5 --- /dev/null +++ b/.emacs.d/custom.el @@ -0,0 +1,39 @@ + +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(custom-safe-themes + '("a59d0dbcbdfc57a14bc3fa28cb5a8367bc7ede82d848f517b4979b4a03c09da9" + "3538194fff1b928df280dc08f041518a8d51ac3ff704c5e46d1517f5c4d8a0e0" + default)) + '(package-selected-packages nil) + '(package-vc-selected-packages + '((eglot-booster :url "https://github.com/jdtsmith/eglot-booster.git"))) + '(safe-local-variable-directories '("/Users/venomade/Projects/Learning/C/GeneticsProject/"))) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(org-block ((t (:inherit fixed-pitch)))) + '(org-code ((t (:inherit (shadow fixed-pitch))))) + '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch))))) + '(org-document-title ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans" :height 2.0 :underline nil)))) + '(org-indent ((t (:inherit (org-hide fixed-pitch))))) + '(org-level-1 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans" :height 1.75)))) + '(org-level-2 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans" :height 1.5)))) + '(org-level-3 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans" :height 1.25)))) + '(org-level-4 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans" :height 1.1)))) + '(org-level-5 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans")))) + '(org-level-6 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans")))) + '(org-level-7 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans")))) + '(org-level-8 ((t (:inherit default :weight bold :foreground "#cdd6f4" :font "Google Sans")))) + '(org-link ((t (:foreground "royal blue" :underline t)))) + '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch))))) + '(org-property-value ((t (:inherit fixed-pitch)))) + '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch))))) + '(org-table ((t (:inherit fixed-pitch)))) + '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8)))) + '(org-verbatim ((t (:inherit (shadow fixed-pitch)))))) diff --git a/.emacs.d/early-init.el b/.emacs.d/early-init.el index b80a729..8ba547e 100644 --- a/.emacs.d/early-init.el +++ b/.emacs.d/early-init.el @@ -1,4 +1,9 @@ -(setq gc-cons-threshold 100000000) -(setq read-process-output-max (* 1024 1024)) +;; GC Perfomance Tweaks from DOOM Emacs +(setq gc-cons-threshold most-positive-fixnum + gc-cons-percentage 1.0) +(add-hook 'emacs-startup-hook + (lambda () + (setq gc-cons-threshold (* 128 1024 1024) ;; 128MB + gc-cons-percentage 1.0))) + (setenv "LSP_USE_PLISTS" "true") -(setq-default lsp-use-plists t) diff --git a/.emacs.d/init.el b/.emacs.d/init.el index e11d303..25db606 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -1,5 +1,915 @@ +;;; init.el --- Venomade's Emacs Config -*- lexical-binding: t; -*- + +;;; Commentary: +;;; +;;; This is my Emacs config which I rewrote from the ground up in October 2025. +;;; It is built around these rules: +;;; - Performance as a Focus +;;; - Don't do with a package what should be done without +;;; - Don't replicate functionality of built-in packages +;;; - When using a package, take advantage of most of it's features + +;;; Code: + +;; Package Setup +(require 'package) +(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) +(package-initialize) + +(if (native-comp-available-p) + (setq package-native-compile t)) + +;; Core Functionality +(setq mac-command-modifier nil) ; disable super on mac + +; (add-to-list 'default-frame-alist '(undecorated . t)) ; disable titlebar + +(setq custom-file (expand-file-name "custom.el" user-emacs-directory)) +(when (file-exists-p custom-file) + (load custom-file)) + +(use-package gcmh ; Improved Garbage Collection + :ensure t + :hook (after-init . gcmh-mode) + :config + (setq gcmh-high-cons-threshold (* 128 1024 1024) ; 128MB + gcmh-idle-delay 10 + gcmh-verbose nil)) + +(use-package exec-path-from-shell ; FIXME: Doesn't work with Daemonex + :ensure t + :config + (setq exec-path-from-shell-shell-name "/bin/zsh" + exec-path-from-shell-arguments nil) + (when (memq window-system '(mac ns x)) + (exec-path-from-shell-initialize))) + +(let* ((backup-dir (expand-file-name "backups/" user-emacs-directory)) + (autosave-dir (expand-file-name "autosaves/" user-emacs-directory)) + (lock-dir (expand-file-name "lock/" user-emacs-directory))) + (make-directory backup-dir t) + (make-directory autosave-dir t) + (make-directory lock-dir t) + + (setq backup-directory-alist `((".*" . ,(directory-file-name backup-dir))) + auto-save-file-name-transforms `((".*" ,(directory-file-name autosave-dir) t)) + lock-file-name-transforms `((".*" ,(directory-file-name lock-dir) t)))) + +(add-to-list 'display-buffer-alist + '("\\`\\*\\(Warnings\\|Compile-Log\\)\\*\\'" + (display-buffer-no-window) + (allow-no-window . t))) + +(progn + (setq trash-directory "~/.Trash") + (defun system-move-file-to-trash (file) + "Use \"trash\" to move FILE to the system trash." + (cl-assert (executable-find "trash") nil "'trash' must be installed. Needs \"brew install trash\"") + (call-process "trash" nil 0 nil "-F" file))) + +;; User Interface +(setq frame-resize-pixelwise t + display-line-numbers-width-start t + display-line-numbers-width 4 + display-line-numbers-grow-only t + ring-bell-function 'ignore + ns-confirm-quit t) + +(setq-default truncate-lines t) + +; Replace the $ signs for truncation with spaces +(set-display-table-slot standard-display-table 'truncation 32) + +(tool-bar-mode -1) +(scroll-bar-mode -1) +(menu-bar-mode -1) + +(add-hook 'emacs-startup-hook #'global-display-line-numbers-mode) + +(add-hook 'after-make-frame-functions + (lambda (f) + (select-frame-set-input-focus f))) + +; (use-package kaolin-themes +; :ensure t +; :config +; ; (add-hook 'emacs-startup-hook +; ; (lambda () +; ; (load-theme 'kaolin-dark t))) +; (load-theme 'kaolin-dark t) + +; (defun theme-toggle () +; "Toggle between two Emacs themes." +; (interactive) +; (let ((theme-a 'kaolin-dark) +; (theme-b 'kaolin-light)) +; (cond +; ((member theme-a custom-enabled-themes) +; (disable-theme theme-a) +; (load-theme theme-b t)) +; ((member theme-b custom-enabled-themes) +; (disable-theme theme-b) +; (load-theme theme-a t)) +; (t +; (load-theme theme-a t)))))) + +; TODO: Redo to be less hacky +; (defun set-mode-line-box () +; (set-face-attribute +; 'mode-line-active nil +; :box '(:line-width 1 :color "#B4BEFE" :style nil))) + +; (with-eval-after-load 'spacious-padding +; (add-hook 'spacious-padding-mode-hook #'set-mode-line-box)) + +(use-package catppuccin-theme + :ensure t + :config + (setq catppuccin-flavor 'mocha) + ; (add-hook 'emacs-startup-hook + ; (lambda () + ; (load-theme 'kaolin-dark t))) + (load-theme 'catppuccin t) + ; (set-mode-line-box) + + (defun theme-toggle () + "Toggle between two Emacs themes." + (interactive) + (let ((theme-a 'kaolin-dark) + (theme-b 'kaolin-light)) + (cond + ((eq catppuccin-flavor 'latte) + (disable-theme 'catppuccin) + (setq catppuccin-flavor 'mocha) + (load-theme 'catppuccin t)) + ; (set-mode-line-box)) + ((eq catppuccin-flavor 'mocha) + (disable-theme 'catppuccin) + (setq catppuccin-flavor 'latte) + (load-theme 'catppuccin t)) + ; (set-mode-line-box)) + (t + (load-theme theme-a t)))))) + +(use-package ns-auto-titlebar + :ensure t + :config + (when (eq system-type 'darwin) (ns-auto-titlebar-mode))) + +(use-package hide-mode-line + :ensure t) + +; TEMPORARILY DISABLED WHILE FIGURING OUT STIPPLES +; ------------------------ +;(use-package indent-bars +; :ensure t +; :hook (prog-mode . indent-bars-mode) +; :config +; (setq indent-bars-width-frac 0.15 +; indent-bars-starting-column 0 +; indent-bars-prefer-character t +; indent-bars-color '(font-lock-comment-face :face-bg nil :blend 0.425) +; indent-bars-color-by-depth nil)) +; +;(face-attribute 'default :stipple nil t) + +(use-package olivetti + :ensure t + :after hide-mode-line + :config + (keymap-global-set "C-c z" 'olivetti-mode) + (which-key-add-key-based-replacements "C-c z" "zen-mode") + (setq olivetti-minimum-body-width 100) + + (defun zen-toggle-minor-modes () + "Toggle minor modes with `olivetti-mode`." + (if olivetti-mode + (progn + (hide-mode-line-mode 1) + (display-line-numbers-mode 0)) + (progn + (setq olivetti-body-width 100) ; HACK: Fixes default being set below minimum + (hide-mode-line-mode 0) + (unless (eq major-mode 'fundamental-mode) + (display-line-numbers-mode 1))))) + + (add-hook 'olivetti-mode-hook #'zen-toggle-minor-modes)) + +(let ((no-numbers-modes '(fundamental-mode-hook))) + (dolist (hk no-numbers-modes) + (add-hook hk (lambda () (display-line-numbers-mode 0))))) + +(use-package doom-modeline + :ensure t + :hook (after-init . doom-modeline-mode) + :config + (setq doom-modeline-height 0 ; minimum + doom-modeline-bar-width 0 ; disabled + doom-modeline-project-detection 'project ; use project.el + doom-modeline-buffer-state-icon nil + doom-modeline-highlight-modified-buffer-name nil + doom-modeline-percent-position nil + line-number-mode nil + doom-modeline-buffer-encoding nil + doom-modeline-time-live-icon nil + doom-modeline-time-icon nil + display-time-default-load-average nil + display-time-format "%a %d %b | %R" + helm-ag-show-status-function nil)) ;HACK: Doom Modeline asks for this but I don't use helm + ;(display-battery-mode 1) + ;(display-time-mode 1)) + +(use-package spacious-padding + :ensure t + :hook (after-init . spacious-padding-mode) + :config + (setq spacious-padding-widths + '( :internal-border-width 8 + :header-line-width 4 + :mode-line-width 6 + :custom-button-width 3 + :tab-width 4 + :right-divider-width 30 + :scroll-bar-width 8 + :fringe-width 0)) + (setq spacious-padding-subtle-frame-lines + '( :mode-line-active spacious-padding-line-active + :mode-line-inactive spacious-padding-line-inactive + :header-line-active spacious-padding-line-active + :header-line-inactive spacious-padding-line-inactive))) + +(use-package nerd-icons + :ensure t + :if (display-graphic-p)) + +(use-package nerd-icons-dired + :ensure t + :after nerd-icons + :hook + (dired-mode . nerd-icons-dired-mode)) + +(use-package nerd-icons-ibuffer + :ensure t + :after nerd-icons + :hook (ibuffer-mode . nerd-icons-ibuffer-mode)) + +(use-package rainbow-delimiters + :ensure t + :hook (prog-mode . rainbow-delimiters-mode)) + +(use-package hl-todo + :ensure t + :hook ((org-mode . hl-todo-mode) + (prog-mode . hl-todo-mode)) + :config + (add-to-list 'hl-todo-keyword-faces '("ERROR" . "#8c5353"))) + +(let* ((quit-messages + `(; from Doom 1 + ,(format "I wouldn't leave if I were you. %s is much worse." + (if (featurep 'windows-nt) "DOS" "UNIX")) + "Ya know, next time you come in here I'm gonna toast ya." + "Go ahead and leave. See if I care." + "Are you sure you want to quit this great editor?" + ; from Doom Emacs + "(setq nothing t everything 'permitted)" + "Emacs will remember that." + "Emacs, Emacs never changes." + "Hey! Hey, M-x listen!" + "Wake up, Mr. Stallman. Wake up and smell the ashes." + "You are *not* prepared!" + "Please don't go. The drones need you. They look up to you."))) + (progn + (defun random-quit-message () + "Return a randomly chosen quit message from `quit-messages'." + (nth (random (length quit-messages)) quit-messages)) + + (defun message-confirm-kill-emacs (&rest _) + "Prompt the user with a random message before quitting. +Returns t to allow kill if the user answers yes; nil otherwise." + (let* ((msg (random-quit-message)) + (prompt (format "%s Really quit Emacs? " msg))) + (yes-or-no-p (propertize prompt 'face '(italic default))))) + + (setq confirm-kill-emacs #'message-confirm-kill-emacs))) + +(use-package goggles + :ensure t + :hook ((prog-mode text-mode) . goggles-mode) + :config + (setq-default goggles-pulse t)) + +(add-hook 'emacs-startup-hook #'which-key-mode) + +;; Text Editing +(setq-default indent-tabs-mode nil + tab-width 2 + tab-stop-list (number-sequence 2 100 2) + c-basic-offset 2) + +(keymap-global-set "C-c r" 'replace-regexp) + +(cl-labels + ((vi-open-line-above () + "Open line above the current line." + (interactive) + (unless (bolp) (beginning-of-line)) + (newline) + (forward-line -1) + (indent-according-to-mode)) + (vi-open-line-below () + "Open line below the current line." + (interactive) + (unless (eolp) (end-of-line)) + (newline-and-indent))) + (define-key (current-global-map) (kbd "C-c o") #'vi-open-line-above) + (define-key (current-global-map) (kbd "C-c O") #'vi-open-line-below) + (which-key-add-key-based-replacements "C-c o" "open-line-above") + (which-key-add-key-based-replacements "C-c O" "open-line-below")) + +(use-package move-text + :ensure t + :config + (keymap-global-set "M-p" 'move-text-up) + (keymap-global-set "M-n" 'move-text-down) + (defun indent-region-advice (&rest ignored) + (let ((deactivate deactivate-mark)) + (if (region-active-p) + (indent-region (region-beginning) (region-end)) + (indent-region (line-beginning-position) (line-end-position))) + (setq deactivate-mark deactivate))) + + (advice-add 'move-text-up :after 'indent-region-advice) + (advice-add 'move-text-down :after 'indent-region-advice)) + +(progn + (defun smart-beginning-of-line () + "Move the cursor to the beginning of text on the line." + (interactive) + (let ((initial-point (point))) + (back-to-indentation) + (when (eq initial-point (point)) + (move-beginning-of-line 1)))) + (defun setup-prog-mode-c-a () + (local-set-key (kbd "C-a") 'smart-beginning-of-line)) + (add-hook 'prog-mode-hook 'setup-prog-mode-c-a) + (add-hook 'conf-mode-hook 'setup-prog-mode-c-a)) + +(progn + (defun prog-nuke-trailing-whitespace () + "Removes trailing whitespace at the end of the line." + (when (or (derived-mode-p 'prog-mode) (derived-mode-p 'conf-mode)) + (delete-trailing-whitespace))) + (add-hook 'before-save-hook 'prog-nuke-trailing-whitespace)) + +(use-package smartparens + :ensure t + :hook (prog-mode text-mode markdown-mode) + :config + (require 'smartparens-config) + (sp-use-paredit-bindings)) + +(use-package undo-tree + :ensure t + :init + (global-undo-tree-mode 1) + :config + (setq undo-tree-auto-save-history t + undo-tree-history-directory-alist '(("." . "~/.emacs.d/.cache")))) + +(use-package gptel + :ensure t + :config + (setq + gptel-model 'qwen2.5-coder:7b-instruct-q4_K_M + gptel-backend (gptel-make-ollama "Ollama" + :host "localhost:11434" + :stream t + :models '(qwen2.5-coder:7b-instruct-q4_K_M))) + (keymap-global-set "C-c g" 'gptel-menu) + (which-key-add-key-based-replacements "C-c g" "gptel")) + +(use-package delsel + :hook (after-init . delete-selection-mode)) + +(use-package accent + :ensure t + :bind* (("C-'" . accent-menu)) + :config + (setq accent-diacritics '((a (á ã â à)) ; só para Português + (e (é ê)) + (i (í)) + (o (ó õ ô)) + (u (ú)) + (c (ç)) + (A (Á Ã Â À)) + (E (É Ê)) + (I (Í)) + (O (Ó Õ Ô)) + (U (Ú))))) + +;; Emacsing +(setq scroll-margin 10 ; Doesn't work with smooth-scrolling + scroll-conservatively 100 + scroll-step 1) + +(setopt use-short-answers t) + +(use-package dired + :commands (dired) + :hook + ((dired-mode . dired-hide-details-mode) + (dired-mode . hl-line-mode)) + :config + (setq dired-recursive-copies 'always + dired-recursive-deletes 'always + ; delete-by-moving-to-trash t ; FIXME: Currently Broken, need to find why + dired-dwim-target t + dired-listing-switches "-lah")) + +(use-package dired-subtree + :ensure t + :after dired + :bind + (:map dired-mode-map + ("TAB" . dired-subtree-toggle) + ("<backtab>" . dired-subtree-remove)) + :config + (setq dired-subtree-use-backgrounds nil)) + +(add-hook 'emacs-startup-hook #'save-place-mode) + +(progn + (dolist (spec + '((eshell-prompt-user-face font-lock-keyword-face "Face for the username in the eshell prompt.") + (eshell-prompt-venv-face font-lock-string-face "Face for the virtualenv name in the eshell prompt.") + (eshell-prompt-dir-face dired-directory "Face for the directory path in the eshell prompt.") + (eshell-prompt-git-face magit-tag "Face for the git branch in the eshell prompt.") + (eshell-prompt-git-dirty-face eshell-prompt-git-face "Face for the git dirty status in the eshell prompt.") + (eshell-prompt-symbol-face font-lock-builtin-face "Face for the prompt symbol in the eshell prompt."))) + (cl-destructuring-bind (name inherit doc) spec + (defface name + `((t (:inherit ,inherit))) + doc + :group 'eshell-prompt))) + + (defun eshell-abbreviate-dir (dir) + "Abbreviate directory to show only the first and the last two components." + (let* ((abbrev (abbreviate-file-name dir)) + (components (split-string abbrev "/" t)) + (num-components (length components))) + (if (>= num-components 4) + (concat (car components) "/.../" + (mapconcat #'identity (last components 2) "/")) + abbrev))) + + (defun eshell-prompt-git-branch () + "Return the current git branch or short commit hash, if available." + (when (and (executable-find "git") + (locate-dominating-file default-directory ".git")) + (with-temp-buffer + (let ((ret (call-process "git" nil t nil "symbolic-ref" "--short" "HEAD"))) + (if (zerop ret) + (string-trim (buffer-string)) + (when (zerop (call-process "git" nil t nil "rev-parse" "--short" "HEAD")) + (string-trim (buffer-string)))))))) + + (defun eshell-prompt-git-dirty () + "Return a dirty flag (✗ if dirty, ✓ if clean) for the git repository." + (when (eshell-prompt-git-branch) + (with-temp-buffer + (call-process "git" nil t nil "status" "--porcelain") + (if (> (buffer-size) 0) "✗" "✓")))) + + (defun eshell-prompt () + "Custom eshell prompt." + (let* ((user (propertize (user-login-name) 'face 'eshell-prompt-user-face)) + (venv (when-let ((venv (getenv "VIRTUAL_ENV"))) + (concat (propertize "(" 'face 'eshell-prompt-venv-face) + (propertize (file-name-nondirectory venv) 'face 'eshell-prompt-venv-face) + (propertize ")" 'face 'eshell-prompt-venv-face)))) + (path (propertize (eshell-abbreviate-dir (eshell/pwd)) 'face 'eshell-prompt-dir-face)) + (git-branch (eshell-prompt-git-branch)) + (git-info (when git-branch + (concat " " (propertize "on" 'face 'font-lock-number-face) " " + (propertize git-branch 'face 'eshell-prompt-git-face) + (propertize (eshell-prompt-git-dirty) 'face 'eshell-prompt-git-dirty-face)))) + (prompt (concat user " " (propertize "in" 'face 'font-lock-number-face) " " + (if venv (concat venv " ") "") + path git-info "\n" + (propertize "λ" 'face 'eshell-prompt-symbol-face) " "))) + prompt)) + + (setq eshell-prompt-function 'eshell-prompt + eshell-prompt-regexp "^[^λ\n]*λ ")) + +(use-package disproject + :ensure t + :after project + :bind (:map ctl-x-map + ("p" . disproject-dispatch))) + +(use-package ibuffer-project + :ensure t + :after project + :config + (add-hook + 'ibuffer-hook + (lambda () + (setq ibuffer-filter-groups (ibuffer-project-generate-filter-groups)) + (unless (eq ibuffer-sorting-mode 'project-file-relative) + (ibuffer-do-sort-by-project-file-relative)))) + (keymap-global-set "C-x C-b" 'ibuffer)) + +(progn + (add-hook 'emacs-startup-hook #'recentf-mode) + (keymap-global-set "C-x C-r" 'recentf-open) + (which-key-add-key-based-replacements "C-x C-r" "Recent Files") + (put 'compile-command 'safe-local-variable #'stringp)) + +(use-package savehist + :hook (after-init . savehist-mode)) + +(add-to-list 'Info-directory-list "/Users/venomade/Documents/Info/") + +;; Org Mode +(setq org-src-window-setup 'current-window + org-confirm-babel-evaluate nil + org-hide-emphasis-markers t) + +(font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) + +; (use-package org-bullets +; :ensure t +; :config +; (setq org-bullets-bullet-list +; '("◉" "○" "◎" "◈" "◆" "▶")) +; (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))) + +(use-package org-superstar + :ensure t + :hook (org-mode . org-superstar-mode) + :custom + (org-superstar-remove-leading-stars nil) + (org-superstar-headline-bullets-list + '("◉" "○" "◎" "◈" "◆" "▶"))) + +(let* ((variable-tuple + (cond ((x-list-fonts "Google Sans") '(:font "Google Sans")) + ((x-family-fonts "Sans Serif") '(:family "Sans Serif")) + (nil (warn "Cannot find a Sans Serif Font. Install Google Sans.")))) + (base-font-color (face-foreground 'default nil 'default)) + (headline `(:inherit default :weight bold :foreground ,base-font-color))) + + (custom-theme-set-faces + 'user + `(org-level-8 ((t (,@headline ,@variable-tuple)))) + `(org-level-7 ((t (,@headline ,@variable-tuple)))) + `(org-level-6 ((t (,@headline ,@variable-tuple)))) + `(org-level-5 ((t (,@headline ,@variable-tuple)))) + `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1)))) + `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.2)))) + `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.3)))) + `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.4)))) + `(org-document-title ((t (,@headline ,@variable-tuple :height 1.6 :underline nil)))))) + +(add-hook 'org-mode-hook 'variable-pitch-mode) +(add-hook 'org-mode-hook 'visual-line-mode) +(add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1))) + +(custom-theme-set-faces + 'user + '(org-block ((t (:inherit fixed-pitch)))) + '(org-code ((t (:inherit (shadow fixed-pitch))))) + '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch))))) + '(org-indent ((t (:inherit (org-hide fixed-pitch))))) + '(org-link ((t (:foreground "royal blue" :underline t)))) + '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch))))) + '(org-property-value ((t (:inherit fixed-pitch))) t) + '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch))))) + '(org-table ((t (:inherit fixed-pitch)))) + '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8)))) + '(org-verbatim ((t (:inherit (shadow fixed-pitch)))))) + +(require 'org-tempo) + +(use-package pdf-tools + :ensure t + :config + (pdf-tools-install) + (add-hook 'pdf-view-mode-hook (lambda () (display-line-numbers-mode -1)))) + +; Open Org Mode links in current window +(setq org-link-frame-setup + '((file . find-file) + (wl . wl-other-frame) + (vm . vm-visit-folder-other-frame) + (gnus . gnus))) + +(use-package denote + :ensure t + :hook (dired-mode . denote-dired-mode) + :bind + (("C-c n n" . denote) + ("C-c n r" . denote-rename-file) + ("C-c n l f" . denote-link) + ("C-c n b" . denote-backlinks) + ("C-c n g" . denote-grep)) + :config + (setq denote-directory (expand-file-name "~/Documents/Denotes/") + denote-known-keywords '("politics" "history" "united kingdom")) + (denote-rename-buffer-mode 1)) + +(use-package consult-denote + :ensure t + :bind + (("C-c n f" . consult-denote-find) + ("C-c n g" . consult-denote-grep)) + :config + (consult-denote-mode 1)) + +; TODO: Denote Explore https://lucidmanager.org/productivity/denote-explore/ + +(use-package denote-menu + :ensure t + :bind + (("C-c n d" . list-denotes)) + :config + (add-hook 'denote-menu-mode-hook (lambda () (display-line-numbers-mode -1)))) + +(use-package denote-org + :ensure t + :bind + (("C-c n l h" . denote-org-link-to-heading))) + +;; Completion +(use-package orderless + :ensure t + :config + (setq completion-styles '(orderless basic) + completion-category-defaults nil + completion-category-overrides '((file (styles . (partial-completion)))))) + +(use-package yasnippet + :ensure t + :hook (prog-mode . yas-minor-mode) + :bind + (("C-c y n" . yas-new-snippet) + ("C-c y v" . yas-visit-snippet-file) + ("C-c y i" . yas-insert-snippet)) + :config + (yas-reload-all)) + +(use-package yasnippet-snippets + :after yasnippet + :ensure t) + +(use-package cape + :ensure t) + +(defun eglot-capf-with-yasnippet () + (setq-local completion-at-point-functions + (list + (cape-capf-super + #'eglot-completion-at-point + #'yasnippet-capf)))) +(with-eval-after-load 'eglot + (add-hook 'eglot-managed-mode-hook #'eglot-capf-with-yasnippet)) + +(use-package corfu + :ensure t + :hook (after-init . global-corfu-mode) + :bind (:map corfu-map ("<tab>" . corfu-complete) + ("RET" . nil)) + :config + (setq corfu-cycle t + corfu-auto t + corfu-auto-delay 0.2 + corfu-preview-current nil + corfu-quit-at-boundary t + corfu-quit-no-match t + corfu-scroll-margin 5 + corfu-tab-always-indent 'complete + corfu-preview-current nil + corfu-min-width 20 + corfu-popupinfo-delay '(1.25 . 0.5)) + (corfu-popupinfo-mode 1) + (with-eval-after-load 'savehist + (corfu-history-mode 1) + (add-to-list 'savehist-additional-variables 'corfu-history))) + +(use-package nerd-icons-corfu + :ensure t + :after nerd-icons corfu + :config + (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) + +(use-package vertico + :ensure t + :hook (after-init . vertico-mode) + :bind (:map vertico-map + ("DEL" . vertico-directory-delete-char))) + +(use-package consult + :ensure t + :bind (("M-g g" . consult-goto-line) + ("M-g M-g" . consult-goto-line) + ("C-c s" . consult-line)) + + :config + (which-key-add-key-based-replacements "C-c s" "search-lines")) + +(use-package affe + :ensure t + :after consult + :bind (("C-c f f" . affe-find) + ("C-c f g" . affe-grep)) + :init + (which-key-add-key-based-replacements "C-c f" "find-file") + (which-key-add-key-based-replacements "C-c f f" "find-fuzzy") + (which-key-add-key-based-replacements "C-c f g" "find-greppy")) + +(use-package marginalia + :ensure t + :after vertico + :config (marginalia-mode 1)) + +(use-package nerd-icons-completion + :ensure t + :after vertico marginalia + :hook + (marginalia-mode . nerd-icons-completion-marginalia-setup) + (after-init . nerd-icons-completion-mode)) + +;; Version Control (setq vc-follow-symlinks t) -(org-babel-load-file + +(use-package magit + :ensure t + :after nerd-icons + :custom + (magit-format-file-function #'magit-format-file-nerd-icons)) + +(use-package magit-todos + :ensure t + :after magit hl-todo + :config + (add-hook 'magit-log-wash-summary-hook + #'hl-todo-search-and-highlight t) + (add-hook 'magit-revision-wash-message-hook + #'hl-todo-search-and-highlight t) + (magit-todos-mode 1)) + +;; Programming +(use-package eglot + :ensure t + :after cape + :config + (setq eglot-report-progress nil) + (advice-add 'eglot-completion-at-point :around #'cape-wrap-buster) + (add-hook 'c-mode-hook #'eglot-ensure)) + +(use-package eglot-booster + :vc (:url "https://github.com/jdtsmith/eglot-booster.git") + :ensure t + :after eglot + :config + (setq eglot-booster-io-only t) + (eglot-booster-mode)) + +(use-package consult-eglot + :ensure t + :after eglot) + +(progn + (use-package eldoc-box + :ensure t) + + (defun markdown-follow-help-or-link-at-point-advice (orig-fun &rest args) + "Prefer to use the help-echo property as `browse-url' target." + (let* ((event-win (posn-window (event-start last-input-event))) + (help-echo (with-selected-frame (window-frame event-win) + (with-current-buffer (window-buffer event-win) + (get-text-property (point) 'help-echo)))) + (help-is-url (url-type (url-generic-parse-url help-echo)))) + (message "if %s (browse-url %S)" help-is-url help-echo) + (if help-is-url + (browse-url help-echo) + (apply orig-fun args)))) + + (advice-add 'markdown-follow-link-at-point :around #'markdown-follow-help-or-link-at-point-advice)) + +(transient-define-prefix eglot-transient () + "Transient menu for Eglot." + [["Server" + ("c" "Reconnect" eglot-reconnect) + ("q" "Shutdown" eglot-shutdown) + ("I" "Server Info" eglot-show-workspace-configuration)] + ["Navigation" + ("g" "Go to Definition" xref-find-definitions) + ("d" "Describe Thing at Point" eldoc-box-help-at-point) + ("D" "Go to Declaration" eglot-find-declaration) + ("i" "Go to Implementation" eglot-find-implementation) + ("f" "Find References" xref-find-references) + ("t" "Type Definition" eglot-find-typeDefinition) + ("s" "Search Symbols" + (lambda () + (interactive) + (if (eq major-mode 'java-mode) + (call-interactively 'consult-eglot-jdt-symbols) + (call-interactively 'consult-eglot-symbols))))] + ["Code Actions" + ("a" "Code Actions" eglot-code-actions) + ("q" "Quick Fix" eglot-code-action-quickfix) + ("=" "Format Buffer" eglot-format-buffer) + ("o" "Organize Imports" eglot-code-action-organize-imports) + ("r" "Rename Symbol" eglot-rename)] + ["Diagnostics" + ("l" "List Diagnostics" flycheck-list-errors) + ("L" "Project Diagnostics" flymake-show-project-diagnostics)]] + (interactive) + (transient-setup 'eglot-transient)) + +(define-key eglot-mode-map (kbd "C-c l") #'eglot-transient) + +(use-package flycheck + :ensure t + :config + (global-flycheck-mode 1)) + +(use-package flycheck-eglot + :ensure t + :after (flycheck eglot) + :custom (flycheck-eglot-exclusive nil) + :config + (global-flycheck-eglot-mode 1)) + +(setq-default flycheck-disabled-checkers '(c/c++-clang)) + +(progn + (setq compilation-scroll-output t) + (keymap-global-set "C-c m c" 'compile) + (keymap-global-set "C-c m r" 'recompile) + (which-key-add-key-based-replacements "C-c m" "make")) + +(require 'ansi-color) +(defun colorize-compilation-buffer () + (ansi-color-apply-on-region compilation-filter-start (point))) +(add-hook 'compilation-filter-hook 'colorize-compilation-buffer) + +(global-prettify-symbols-mode 1) + +;; Languages + +; (load-file +; (expand-file-name +; "lang/java.el" +; user-emacs-directory)) + +(load-file (expand-file-name - "config.org" + "lang/lua.el" user-emacs-directory)) + +; (load-file +; (expand-file-name +; "lang/lisp.el" +; user-emacs-directory)) + +; (load-file +; (expand-file-name +; "lang/clojure.el" +; user-emacs-directory)) + +;; Font +; Putting at the end to test if it fixes this: +; https://github.com/d12frosted/homebrew-emacs-plus/issues/898 + +(let* ((fontconf '((fixed-font . "Google Sans Code") + (variable-font . "Google Sans") + (size . 12))) + (fixed-font (cdr (assoc 'fixed-font fontconf))) + (variable-font (cdr (assoc 'variable-font fontconf))) + (pt-size (cdr (assoc 'size fontconf))) + (height (* pt-size 10)) + (frame-font (concat fixed-font "-" (number-to-string pt-size)))) + ; Fixed-width faces + (dolist (face '(default fixed-pitch)) + (set-face-attribute face nil + :font fixed-font + :height height + :weight 'regular)) + ; Variable-pitch face + (set-face-attribute 'variable-pitch nil + :font variable-font + :height height + :weight 'regular) + + ; Syntax styling + (set-face-attribute 'font-lock-comment-face nil :slant 'italic) + (set-face-attribute 'font-lock-keyword-face nil :slant 'italic) + + ; Frame font + (add-to-list 'default-frame-alist `(font . ,frame-font))) diff --git a/.emacs.d/lang/clojure.el b/.emacs.d/lang/clojure.el new file mode 100644 index 0000000..804fcc7 --- /dev/null +++ b/.emacs.d/lang/clojure.el @@ -0,0 +1,26 @@ +(use-package cider + :ensure t) + +(add-hook 'cider-repl-mode-hook (lambda () (display-line-numbers-mode -1))) +(add-hook 'cider-repl-mode-hook #'smartparens-mode) +(add-hook 'clojure-mode #'eglot-ensure t) + +(setq-default cider-eldoc-display-for-symbol-at-point nil) + +(defun mu-cider-disable-eldoc () + "Let LSP handle ElDoc instead of CIDER." + (remove-hook 'eldoc-documentation-functions #'cider-eldoc t)) + +(add-hook 'cider-mode-hook #'mu-cider-disable-eldoc) + +(defun mu-cider-disable-eldoc () + "Let LSP handle ElDoc instead of CIDER." + (remove-hook 'eldoc-documentation-functions #'cider-eldoc t)) + +(add-hook 'cider-mode-hook #'mu-cider-disable-eldoc) + +(defun mu-cider-disable-completion () + "Let LSP handle completion instead of CIDER." + (remove-hook 'completion-at-point-functions #'cider-complete-at-point t)) + +(add-hook 'cider-mode-hook #'mu-cider-disable-completion) diff --git a/.emacs.d/lang/java.el b/.emacs.d/lang/java.el new file mode 100644 index 0000000..5d41a0c --- /dev/null +++ b/.emacs.d/lang/java.el @@ -0,0 +1,38 @@ +;; Emacs Configuration for Java + +; JDT URI fix for JDTLS from https://www.reddit.com/r/emacs/comments/1ibkh2h/comment/m9slw00/ +(with-eval-after-load 'eglot + (add-to-list 'eglot-server-programs + `((java-mode java-ts-mode) . + ("jdtls" + :initializationOptions + (:extendedClientCapabilities (:classFileContentsSupport t)))))) + +(defun jdt-file-name-handler (operation &rest args) + "Support Eclipse jdtls `jdt://' uri scheme." + (let* ((uri (car args)) + (cache-dir "/tmp/.eglot") + (source-file + (expand-file-name + (file-name-concat + cache-dir + (save-match-data + (when (string-match "jdt://contents/\\(.*?\\)/\\(.*\\)\.class\\?" uri) + (format "%s.java" (replace-regexp-in-string "/" "." (match-string 2 uri) t t)))))))) + (unless (file-readable-p source-file) + (let ((content (jsonrpc-request (eglot-current-server) :java/classFileContents (list :uri uri))) + (metadata-file (format "%s.%s.metadata" + (file-name-directory source-file) + (file-name-base source-file)))) + (unless (file-directory-p cache-dir) (make-directory cache-dir t)) + (with-temp-file source-file (insert content)) + (with-temp-file metadata-file (insert uri)))) + source-file)) +(add-to-list 'file-name-handler-alist '("\\`jdt://" . jdt-file-name-handler)) + +(add-hook 'java-mode-hook #'eglot-ensure t) + +(load-file + (expand-file-name + "pkg/consult-jdt.el" + user-emacs-directory)) diff --git a/.emacs.d/lang/lisp.el b/.emacs.d/lang/lisp.el new file mode 100644 index 0000000..b0aebd3 --- /dev/null +++ b/.emacs.d/lang/lisp.el @@ -0,0 +1,9 @@ +(use-package sly + :ensure t + :config + (setq inferior-lisp-program "ros -L sbcl -Q run" + browse-url-browser-function '(("hyperspec" . eww-browse-url) ("." . browse-url-default-browser))) + (add-hook 'sly-mrepl-mode-hook 'smartparens-mode) + (add-hook 'lisp-mode-hook + (lambda () + (define-key lisp-mode-map (kbd "C-c d") 'sly-documentation)))) diff --git a/.emacs.d/lang/lua.el b/.emacs.d/lang/lua.el new file mode 100644 index 0000000..dfc1b19 --- /dev/null +++ b/.emacs.d/lang/lua.el @@ -0,0 +1,11 @@ +;; Emacs Configuration for Lua + +(use-package lua-mode + :ensure t + :config + (add-hook 'lua-mode-hook #'eglot-ensure t) + (setq lua-indent-level 2 + lua-documentation-url "https://www.lua.org/manual/5.4/manual.html")) + +; TODO Try fix this only for lua-mode as that is where the bug is +(setq eglot-ignored-server-capabilities '(:documentOnTypeFormattingProvider)) diff --git a/.emacs.d/pkg/consult-jdt.el b/.emacs.d/pkg/consult-jdt.el new file mode 100644 index 0000000..6959f72 --- /dev/null +++ b/.emacs.d/pkg/consult-jdt.el @@ -0,0 +1,105 @@ +(require 'consult) +(require 'eglot) +(require 'jsonrpc) +(require 'subr-x) + +(defvar eglot-jdt--symbolkind-map + '((1 . "File") (2 . "Module") (3 . "Namespace") (4 . "Package") + (5 . "Class") (6 . "Method") (7 . "Property") (8 . "Field") + (9 . "Constructor") (10 . "Enum") (11 . "Interface") (12 . "Function") + (13 . "Variable") (14 . "Constant") (15 . "String") (16 . "Number") + (17 . "Boolean") (18 . "Array") (19 . "Object") (20 . "Key") + (21 . "Null") (22 . "EnumMember") (23 . "Struct") (24 . "Event") + (25 . "Operator") (26 . "TypeParameter")) + "Mapping of LSP SymbolKind integers to human-readable names.") + +(defun eglot-jdt--get (obj key) + "Robustly retrieve KEY from LSP OBJ (plist/alist)." + (let* ((kname (substring (symbol-name key) 1)) + (sym-key (intern kname))) + (or (plist-get obj key) + (alist-get key obj) + (alist-get sym-key obj) + (alist-get kname obj)))) + +(defun eglot-jdt--fetch-symbols (&optional query) + "Synchronously fetch workspace symbols for QUERY from Eglot/JDTLS." + (unless (eglot-managed-p) + (user-error "Eglot is not managing this buffer")) + (let* ((server (eglot-current-server)) + (symbols (jsonrpc-request server :workspace/symbol `(:query ,(or query ""))))) + (when (vectorp symbols) + (setq symbols (append symbols nil))) + symbols)) + +;; Helper to pad strings +(defun eglot-jdt--pad-right (str width) + "Pad STR on the right with spaces to WIDTH." + (let ((len (length str))) + (if (< len width) + (concat str (make-string (- width len) ?\s)) + str))) + +;; Main formatting function with faces +(defun eglot-jdt--format-symbols-table (symbols) + "Format SYMBOLS into a table with faces for Consult, showing Kind first." + (let* ((rows (mapcar (lambda (sym) + (let ((kind-num (eglot-jdt--get sym :kind))) + (list (or (alist-get kind-num eglot-jdt--symbolkind-map) + (format "Kind %s" kind-num)) + (eglot-jdt--get sym :name) + (or (eglot-jdt--get sym :containerName) "<no-package>") + (let ((location (eglot-jdt--get sym :location))) + (eglot-jdt--get location :uri))))) + symbols)) + ;; compute max width for each column + (max-kind (apply #'max (mapcar (lambda (r) (length (nth 0 r))) rows))) + (max-name (apply #'max (mapcar (lambda (r) (length (nth 1 r))) rows))) + (max-package (apply #'max (mapcar (lambda (r) (length (nth 2 r))) rows))) + ;; faces + (divider-face 'shadow) ;; low opacity / dim for dividers + (kind-face 'font-lock-function-name-face) + (name-face 'font-lock-variable-name-face) + (package-face 'font-lock-keyword-face)) + ;; create table rows with faces + (mapcar (lambda (r) + (let* ((kind (propertize (eglot-jdt--pad-right (nth 0 r) max-kind) 'face kind-face)) + (name (propertize (eglot-jdt--pad-right (nth 1 r) max-name) 'face name-face)) + (package (propertize (eglot-jdt--pad-right (nth 2 r) max-package) 'face package-face)) + (divider (propertize "|" 'face divider-face))) + (cons (format "%s %s %s %s %s" + kind divider name divider package) + (nth 3 r)))) + rows))) + +(defun eglot-jdt--open-uri (uri) + "Open a URI returned by the language server, handling jdt:// URIs." + (if (and uri (string-prefix-p "jdt://" uri)) + (find-file (expand-file-name uri)) ; your jdt-file-name-handler takes care of this + (find-file (eglot-uri-to-path uri)))) + +(defun eglot-jdt--sort-by-query (symbols query) + "Sort SYMBOLS by how closely their names match QUERY." + (let ((query (or query ""))) + (sort symbols + (lambda (a b) + (< (string-distance (eglot-jdt--get a :name) query) + (string-distance (eglot-jdt--get b :name) query)))))) + +(defun consult-eglot-jdt-symbols (&optional query) + "Consult interface for Java workspace symbols via Eglot/JDTLS. +Sorts results based on closeness to QUERY." + (interactive "sSymbol query (blank for all): ") + (let* ((symbols (eglot-jdt--fetch-symbols query)) + (sorted-symbols (eglot-jdt--sort-by-query symbols query)) + (candidates (eglot-jdt--format-symbols-table sorted-symbols)) + (selection (consult--read + (mapcar #'car candidates) + :prompt "Symbol: " + :sort nil + :require-match t + :category 'symbol))) + (when selection + (let ((uri (cdr (assoc selection candidates)))) + (when uri + (eglot-jdt--open-uri uri)))))) diff --git a/.emacs.d/pkg/flymake-cppcheck.el b/.emacs.d/pkg/flymake-cppcheck.el new file mode 100644 index 0000000..92a78de --- /dev/null +++ b/.emacs.d/pkg/flymake-cppcheck.el @@ -0,0 +1,84 @@ +;;; flymake-cppcheck.el --- Flymake work with Cppcheck for C/C++ + +;; Copyright 2014 Akiha Senda + +;; Author: Akiha Senda <senda.akiha@gmail.com> +;; URL: https://github.com/senda-akiha/flymake-cppcheck/ +;; Created: 13 January 2014 +;; Version: 1.0.0 +;; Keywords: flymake, cppcheck, C, C++ +;; Package-Requires: ((flymake-easy "0.9")) + +;; This file is not part of GNU Emacs. +;; However, it is distributed under the same license. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Please check the GitHub +;; (https://github.com/senda-akiha/flymake-cppcheck/) +;; for more information. + +;;; Code: + +(require 'flymake-easy) + +(defconst flymake-cppcheck-err-line-patterns + '(("\\(.*\\)::\\([[:digit:]]+\\)::\\(.*\\)\r?\n" + 1 2 nil 3))) + +(defconst flymake-cppcheck-template "{file}::{line}::{message}" + "Output format template.") + +(defcustom flymake-cppcheck-enable "error" + "By default only error messages are shown. +Through the --enable command more checks can be enabled." + :type 'string + :group 'flymake-cppcheck) + +(defcustom flymake-cppcheck-command (or (executable-find "cppcheck") "") + "The name of the cppcheck executable." + :type 'string + :group 'flymake-cppcheck) + +(defcustom flymake-cppcheck-location 'inplace + "Where to create the temporary copy: one of 'tempdir or 'inplace (default)." + :type `(choice + (const :tag "In place" inplace) + (const :tag "Temporary location" tempdir)) + :group 'flymake-cppcheck) + +(defun flymake-cppcheck-build-command-line (filename) + "Construct a command that flymake can use to check C/C++ source." + (list flymake-cppcheck-command "--quiet" + (concat "--template=" flymake-cppcheck-template) + (if (string-match "error" flymake-cppcheck-enable) + "" (concat "--enable=" flymake-cppcheck-enable)) + filename)) + +;;;###autoload +(defun flymake-cppcheck-load () + "Configure flymake mode to check the current buffer's C/C++ source." + (interactive) + (flymake-easy-load 'flymake-cppcheck-build-command-line + flymake-cppcheck-err-line-patterns + flymake-cppcheck-location + "cpp")) + +(provide 'flymake-cppcheck) + +;;; flymake-cppcheck.el ends here |
