Compare commits

..

10 Commits

Author SHA1 Message Date
ab350551ee Add /snap/bin to PATH for WSL
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 16:03:53 -04:00
213d7e30f2 Fix modus-themes: let MELPA install it, revert to modus-vivendi
Removing :ensure nil so use-package fetches from MELPA — the built-in
version was missing or too old on this Emacs install.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:50:33 -04:00
a5a11c94d2 Try modus-vivendi-tinted for better hl-line contrast
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:48:54 -04:00
5ccac480e7 Switch to modus-vivendi theme
catppuccin fails to load in terminal mode (WSL) causing the blue
default background. modus-vivendi is built-in so it always loads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:45:51 -04:00
38ba1d95e3 Revert to catppuccin mocha theme
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:44:07 -04:00
d04e0725bd Switch to absolute line numbers
Relative numbers are mainly useful with Vim-style jump motions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:42:38 -04:00
668df75efb Start Emacs daemon on shell init for instant emacsclient
Daemon starts in the background when a new shell opens so 'e' always
connects to an existing server rather than launching a new instance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:37:57 -04:00
7a82a6b8f8 Switch theme from catppuccin to modus-vivendi
modus-vivendi is built into Emacs 29+ so it loads reliably without
a MELPA install — better for WSL where package errors were occurring.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:35:44 -04:00
9ac5b2beff Add Emacs config with install scripts for laptop and work
Shared: init.el / early-init.el with Vertico stack, Corfu, Eglot,
treesit-auto, Catppuccin Mocha, doom-modeline, Magit, avy, harpoon,
embark, wgrep, expand-region, envrc, org-mode, and drop-in lang loader.

Lang configs split by stow target:
- shared: elisp, org
- laptop: C/C++, Rust, Go, LaTeX (AUCTeX + latexmk + Zathura)
- work:   C#, JS/TS/HTML/CSS/React (apheleia+prettier), Copilot

install-personal.sh: Fedora — gcc/clang, rustup, Go, texlive, zathura
install-work.sh: Ubuntu 24.04 WSL — dotnet-sdk-10.0, Node 22 via nvm, ts-ls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:12:32 -04:00
b0ed92c0cf removing editors 2026-04-29 14:32:21 -04:00
30 changed files with 457 additions and 1772 deletions

66
install-personal.sh Executable file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Personal workstation dev dependencies — Fedora
# Languages: C, C++, Rust, Go, Emacs Lisp, LaTeX
set -euo pipefail
# --- Core tools ---
sudo dnf install -y \
emacs \
git \
ripgrep \
fd-find \
stow
# --- C / C++ ---
sudo dnf install -y \
gcc \
gcc-c++ \
clang \
clang-tools-extra \
cmake \
ninja-build
# --- Rust (latest stable via rustup) ---
if ! command -v rustup &>/dev/null; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
fi
# shellcheck source=/dev/null
source "$HOME/.cargo/env"
rustup update stable
rustup component add rust-analyzer rust-src clippy rustfmt
# --- Go (latest stable — go.dev does not use LTS; update GO_VERSION as needed) ---
GO_VERSION="1.24.2"
INSTALLED=$(go version 2>/dev/null | awk '{print $3}' || true)
if [[ "$INSTALLED" != "go${GO_VERSION}" ]]; then
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf /tmp/go.tar.gz
rm /tmp/go.tar.gz
fi
export PATH="/usr/local/go/bin:$PATH"
# gopls language server
go install golang.org/x/tools/gopls@latest
# --- LaTeX ---
# texlive-scheme-medium covers most common packages including latexmk
# liturg is a liturgical typesetting package (plainchant, etc.)
sudo dnf install -y \
texlive-scheme-medium \
texlive-liturg \
zathura \
zathura-pdf-mupdf \
aspell \
aspell-en
# Inverse search: Zathura → Emacs via Ctrl+click
# Add to ~/.config/zathura/zathurarc if not already present:
# set synctex-editor-command "emacsclient +%{line} %{input}"
ZATHURA_RC="$HOME/.config/zathura/zathurarc"
if ! grep -q "synctex-editor-command" "$ZATHURA_RC" 2>/dev/null; then
mkdir -p "$(dirname "$ZATHURA_RC")"
echo 'set synctex-editor-command "emacsclient +%{line} %{input}"' >> "$ZATHURA_RC"
fi
echo "Personal dev dependencies installed."

50
install-work.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Work workstation dev dependencies — Ubuntu 24.04 LTS (WSL)
# Languages: C#, JavaScript, TypeScript, Node.js, HTML, CSS, React
set -euo pipefail
sudo apt-get update -q
# --- Core tools ---
# curl may not be present in a minimal WSL image
sudo apt-get install -y \
emacs \
git \
ripgrep \
fd-find \
stow \
curl
# Ubuntu names the fd binary 'fdfind'; add a user-local symlink so tooling finds it as 'fd'
if command -v fdfind &>/dev/null && ! command -v fd &>/dev/null; then
mkdir -p "$HOME/.local/bin"
ln -sf "$(command -v fdfind)" "$HOME/.local/bin/fd"
fi
# --- .NET 10 (in Ubuntu 24.04 main repo — no extra source needed) ---
sudo apt-get install -y dotnet-sdk-10.0
# C# language server (NuGet global tool)
dotnet tool install --global csharp-ls 2>/dev/null \
|| dotnet tool update --global csharp-ls
# --- Node.js 22 LTS via nvm (Ubuntu 24.04 repos ship 20.x; nvm adds no apt sources) ---
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
if [[ ! -d "$NVM_DIR" ]]; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
fi
# shellcheck source=/dev/null
source "$NVM_DIR/nvm.sh"
nvm install 22
nvm alias default 22
nvm use default
# --- JS / TS / HTML / CSS language servers and formatters ---
npm install -g \
typescript \
typescript-language-server \
vscode-langservers-extracted \
prettier \
eslint
echo "Work dev dependencies installed."

View File

@@ -1,87 +0,0 @@
;;; dev-settings.el --- Laptop development environment
;;; DAP Mode
(use-package dap-mode
:defer t
:commands (dap-mode dap-debug)
:config
(require 'dap-gdb-lldb)
(require 'dap-cpptools))
;;; C / C++
(use-package c-ts-mode
:ensure nil
:mode (("\\.c\\'" . c-ts-mode)
("\\.h\\'" . c-ts-mode)
("\\.cpp\\'" . c++-ts-mode)
("\\.hpp\\'" . c++-ts-mode)
("\\.cc\\'" . c++-ts-mode)
("\\.cxx\\'" . c++-ts-mode))
:hook ((c-ts-mode . eglot-ensure)
(c++-ts-mode . eglot-ensure))
:config
(setq c-ts-mode-indent-offset 4))
;;; Go
(use-package go-ts-mode
:ensure nil
:mode "\\.go\\'"
:hook (go-ts-mode . eglot-ensure)
:config
(setq go-ts-mode-indent-offset 4))
(with-eval-after-load 'dap-mode
(require 'dap-dlv-go))
;;; Rust
(use-package rust-ts-mode
:ensure nil
:mode "\\.rs\\'"
:hook (rust-ts-mode . eglot-ensure)
:config
(setq rust-ts-mode-indent-offset 4))
;; rust-analyzer is installed via: rustup component add rust-analyzer
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(rust-ts-mode . ("rust-analyzer"))))
;;; Common Lisp
(use-package slime
:defer t
:commands slime
:config
(setq inferior-lisp-program "sbcl")
(setq slime-contribs '(slime-fancy slime-company))
(setq slime-lisp-implementations
'((sbcl ("sbcl") :coding-system utf-8-unix)
(ccl ("ccl") :coding-system utf-8-unix))))
(use-package slime-company
:defer t
:after (slime company)
:config
(setq slime-company-completion 'fuzzy))
;;; DAP Keybindings
(with-eval-after-load 'dap-mode
(keymap-set dap-mode-map "C-c d d" #'dap-debug)
(keymap-set dap-mode-map "C-c d b" #'dap-breakpoint-toggle)
(keymap-set dap-mode-map "C-c d c" #'dap-continue)
(keymap-set dap-mode-map "C-c d n" #'dap-next)
(keymap-set dap-mode-map "C-c d i" #'dap-step-in)
(keymap-set dap-mode-map "C-c d o" #'dap-step-out)
(keymap-set dap-mode-map "C-c d r" #'dap-restart-frame)
(keymap-set dap-mode-map "C-c d q" #'dap-disconnect)
(keymap-set dap-mode-map "C-c d e" #'dap-eval)
(keymap-set dap-mode-map "C-c d l" #'dap-ui-locals)
(keymap-set dap-mode-map "C-c d s" #'dap-ui-sessions))
(provide 'dev-settings)
;;; dev-settings.el ends here

View File

@@ -1,34 +0,0 @@
;;; latex-settings.el --- AUCTeX / LaTeX configuration
(use-package auctex
:defer t
:init
(setq TeX-auto-save t ; cache style info in auto/ for faster opens
TeX-parse-self t ; parse document on open for completions
TeX-PDF-mode t ; compile to PDF by default
TeX-source-correlate-mode t ; SyncTeX: link editor positions to PDF
TeX-source-correlate-start-server t)
:hook
((LaTeX-mode . LaTeX-math-mode)
(LaTeX-mode . flyspell-mode)
(LaTeX-mode . reftex-mode))
:config
(setq reftex-plug-into-AUCTeX t)
;; Use zathura as the PDF viewer (SyncTeX: click in PDF jumps to source line)
(add-to-list 'TeX-view-program-selection '(output-pdf "Zathura"))
;; LatexMk handles multiple pdflatex passes, bibliography, index automatically
(add-to-list 'TeX-command-list
'("LatexMk" "latexmk -pdf -interaction=nonstopmode %s"
TeX-run-TeX nil t :help "Run latexmk"))
(setq TeX-command-default "LatexMk")
(defun rh/latex-build-pdf ()
"Compile the current LaTeX buffer to PDF using latexmk."
(interactive)
(TeX-command "LatexMk" #'TeX-master-file))
(with-eval-after-load 'latex
(define-key LaTeX-mode-map (kbd "C-c C-b") #'rh/latex-build-pdf)))
(provide 'latex-settings)
;;; latex-settings.el ends here

View File

@@ -0,0 +1,11 @@
;;; lisp/langs/c-cpp.el --- C and C++ -*- lexical-binding: t -*-
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((c-mode c-ts-mode c++-mode c++-ts-mode)
. ("clangd" "--background-index" "--clang-tidy"))))
(dolist (hook '(c-mode-hook c-ts-mode-hook c++-mode-hook c++-ts-mode-hook))
(add-hook hook #'eglot-ensure))
(use-package cmake-mode)

View File

@@ -0,0 +1,14 @@
;;; lisp/langs/golang.el --- Go -*- lexical-binding: t -*-
(use-package go-mode)
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((go-mode go-ts-mode) . ("gopls"))))
(defun my/go-format-on-save ()
(add-hook 'before-save-hook #'eglot-format-buffer nil t))
(dolist (hook '(go-mode-hook go-ts-mode-hook))
(add-hook hook #'eglot-ensure)
(add-hook hook #'my/go-format-on-save))

View File

@@ -0,0 +1,30 @@
;;; lisp/langs/latex.el --- LaTeX via AUCTeX -*- lexical-binding: t -*-
(use-package tex
:ensure auctex
:custom
(TeX-auto-save t)
(TeX-parse-self t)
(TeX-master nil) ; ask per-project, supports multi-file docs
(TeX-PDF-mode t)
(TeX-source-correlate-mode t)
(TeX-source-correlate-method 'synctex)
:config
;; latexmk handles multi-pass builds (bibtex, makeindex, etc.) automatically
(add-to-list 'TeX-command-list
'("LatexMk" "latexmk -pdf -interaction=nonstopmode %s"
TeX-run-command nil t :help "Run latexmk"))
(setq TeX-command-default "LatexMk")
;; Forward search: C-c C-v jumps PDF to current source position
;; Inverse search: Ctrl+click in Zathura calls emacsclient (requires server-start)
(add-to-list 'TeX-view-program-list
'("Zathura"
("zathura"
(mode-io-correlate " --synctex-forward %n:0:%b") " %o")
"zathura"))
(setq TeX-view-program-selection '((output-pdf "Zathura"))))
(add-hook 'LaTeX-mode-hook #'LaTeX-math-mode)
(add-hook 'LaTeX-mode-hook #'turn-on-reftex)
(add-hook 'LaTeX-mode-hook #'flyspell-mode)
(setq reftex-plug-into-AUCTeX t)

View File

@@ -0,0 +1,10 @@
;;; lisp/langs/rust.el --- Rust -*- lexical-binding: t -*-
(use-package rust-mode)
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((rust-mode rust-ts-mode) . ("rust-analyzer"))))
(dolist (hook '(rust-mode-hook rust-ts-mode-hook))
(add-hook hook #'eglot-ensure))

View File

@@ -1,77 +0,0 @@
;;; common-dev-settings.el --- Dev tooling shared across all hosts
;;; Completion
(use-package company
:defer 1
:config
(global-company-mode)
(setq company-idle-delay 0.2
company-minimum-prefix-length 2
company-show-numbers t
company-tooltip-align-annotations t))
;;; LSP
(use-package eglot
:ensure nil
:defer t
:commands (eglot eglot-ensure)
:config
(setq eglot-autoshutdown t
eglot-send-changes-idle-time 0.5)
(setq eldoc-echo-area-use-multiline-p nil)
(add-to-list 'eglot-stay-out-of 'eldoc))
;;; Tree-sitter mode management
;; Grammar sources and installation are host-specific; see dev-settings.el.
(use-package treesit-auto
:custom
(treesit-auto-install 'prompt)
:config
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
;;; Utilities
(use-package helpful
:defer t
:commands (helpful-callable helpful-variable helpful-key))
(use-package smartparens
:defer 1
:hook (prog-mode . smartparens-mode)
:config
(require 'smartparens-config))
(use-package yasnippet
:defer 2
:config
(yas-global-mode 1))
(use-package yasnippet-snippets
:defer t
:after yasnippet)
;;; Emacs Lisp
(add-hook 'emacs-lisp-mode-hook #'eldoc-mode)
(add-hook 'emacs-lisp-mode-hook #'company-mode)
;;; LSP Keybindings
(with-eval-after-load 'eglot
(keymap-set eglot-mode-map "C-c l d" #'xref-find-definitions)
(keymap-set eglot-mode-map "C-c l r" #'xref-find-references)
(keymap-set eglot-mode-map "C-c l i" #'eglot-find-implementation)
(keymap-set eglot-mode-map "C-c l t" #'eglot-find-typeDefinition)
(keymap-set eglot-mode-map "C-c l h" #'eldoc-doc-buffer)
(keymap-set eglot-mode-map "C-c l s" #'eldoc)
(keymap-set eglot-mode-map "C-c l a" #'eglot-code-actions)
(keymap-set eglot-mode-map "C-c l n" #'eglot-rename)
(keymap-set eglot-mode-map "C-c l e" #'flymake-show-buffer-diagnostics)
(keymap-set eglot-mode-map "C-c l f" #'eglot-format-buffer))
(provide 'common-dev-settings)
;;; common-dev-settings.el ends here

View File

@@ -0,0 +1,7 @@
;;; early-init.el -*- lexical-binding: t -*-
;; Defer GC during startup; restore to a reasonable limit after
(setq gc-cons-threshold (* 128 1024 1024))
(add-hook 'emacs-startup-hook
(lambda () (setq gc-cons-threshold (* 16 1024 1024))))

View File

@@ -1,159 +1,197 @@
;; init.el ;;; init.el --- Emacs configuration -*- lexical-binding: t -*-
(defun rh/load-user-file (file) ;;; Package management
"Load FILE from `user-emacs-directory' when it exists."
(let ((path (expand-file-name file user-emacs-directory)))
(when (file-exists-p path)
(load path nil 'nomessage))))
;;; Startup/UI ---------------------------------------------------------------
(setq inhibit-startup-message t
visible-bell t)
(scroll-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)
(menu-bar-mode -1)
;;; Editing Defaults ---------------------------------------------------------
(global-display-line-numbers-mode 1)
(setq display-line-numbers-type 'relative)
(setq make-backup-files nil
auto-save-default nil
create-lockfiles nil)
(setq vc-follow-symlinks t
find-file-visit-truename t)
;;; Package Manager ----------------------------------------------------------
(require 'package) (require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize) (package-initialize)
(unless package-archive-contents (unless package-archive-contents
(package-refresh-contents)) (package-refresh-contents))
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package) (require 'use-package)
(setq use-package-always-ensure t) (setq use-package-always-ensure t)
(setq custom-file (expand-file-name "custom.el" user-emacs-directory)) ;;; Sane defaults
;;; Style/Theme -------------------------------------------------------------- (setq-default
inhibit-startup-message t
visible-bell t
make-backup-files nil
auto-save-default nil
create-lockfiles nil
vc-follow-symlinks t
find-file-visit-truename t
fill-column 80
tab-width 4
indent-tabs-mode nil
truncate-lines t
sentence-end-double-space nil)
(use-package catppuccin-theme (menu-bar-mode -1)
:init (tool-bar-mode -1)
(setq catppuccin-flavor 'mocha) (scroll-bar-mode -1)
(tooltip-mode -1)
(setq display-line-numbers-type t)
(global-display-line-numbers-mode 1)
(column-number-mode 1)
(global-hl-line-mode 1)
(show-paren-mode 1)
(electric-pair-mode 1)
(delete-selection-mode 1)
(setq global-auto-revert-non-file-buffers t)
(global-auto-revert-mode 1)
(setq scroll-margin 4
scroll-conservatively 101)
(setq uniquify-buffer-name-style 'forward)
;;; Font — matches ghostty / tmux setup
(set-face-attribute 'default nil
:family "Hack Nerd Font Mono"
:height 110)
;;; Theme
(use-package modus-themes
:config :config
(load-theme 'catppuccin t)) (load-theme 'modus-vivendi t))
;; Icons are only useful in GUI Emacs. ;;; Discoverability
(use-package all-the-icons
:if (display-graphic-p)) (use-package which-key
:config
(setq which-key-idle-delay 0.5)
(which-key-mode))
;;; Minibuffer — Vertico + Orderless + Marginalia + Consult
(use-package vertico
:config (vertico-mode))
(use-package orderless
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))
(use-package marginalia
:config (marginalia-mode))
(use-package consult
:bind (("C-x b" . consult-buffer)
("M-y" . consult-yank-pop)
("M-g M-g" . consult-goto-line)
("M-g i" . consult-imenu)
("M-s l" . consult-line)
("M-s r" . consult-ripgrep)))
;; Contextual actions on any minibuffer candidate or thing at point
(use-package embark
:bind (("C-." . embark-act)
("C-;" . embark-dwim))
:custom (embark-indicators '(embark-minimal-indicator)))
(use-package embark-consult
:hook (embark-collect-mode . consult-preview-at-point-mode))
;; Edit consult-ripgrep / grep results as a buffer; save to apply across files
(use-package wgrep
:custom (wgrep-auto-save-buffer t))
;;; In-buffer completion — Corfu + Cape
(use-package corfu
:custom
(corfu-auto t)
(corfu-auto-delay 0.2)
(corfu-auto-prefix 2)
(corfu-quit-no-match 'separator)
:config
(global-corfu-mode))
(use-package cape
:init
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-dabbrev))
;;; Visual aids
;; Color nested delimiters in programming buffers.
(use-package rainbow-delimiters (use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode)) :hook (prog-mode . rainbow-delimiters-mode))
;; nerd-icons supplies glyphs for doom-modeline; Hack Nerd Font Mono already
;; includes them, so M-x nerd-icons-install-fonts is only needed on first use
;; if you see boxes instead of icons.
(use-package nerd-icons)
(use-package doom-modeline (use-package doom-modeline
:init :hook (after-init . doom-modeline-mode)
(doom-modeline-mode 1) :custom
:config (doom-modeline-height 28)
(setq doom-modeline-height 15)) (doom-modeline-bar-width 4)
(doom-modeline-icon t)
(doom-modeline-major-mode-icon t)
(doom-modeline-buffer-file-name-style 'truncate-upto-project)
(doom-modeline-vcs-max-length 24))
;;; Completion/Search/Navigation --------------------------------------------- ;;; Tree-sitter — auto-switch to *-ts-mode when grammars are available
(use-package vertico (use-package treesit-auto
:init :custom (treesit-auto-install 'prompt)
(vertico-mode)) :config (global-treesit-auto-mode))
(use-package consult ;;; LSP — Eglot (built-in since Emacs 29)
:bind (("C-x b" . consult-buffer)
("C-s" . consult-line)
("M-y" . consult-yank-pop)))
(use-package orderless (use-package eglot
:config :ensure nil
(setq completion-styles '(orderless basic) :custom
completion-category-defaults nil)) (eglot-autoshutdown t)
(eglot-confirm-server-initiated-edits nil)
(eglot-events-buffer-size 0))
(use-package marginalia ;;; Navigation
:init
(marginalia-mode))
(use-package embark ;; Jump to any visible character — type a few chars of the target, pick the label
:bind (("C-." . embark-act) (use-package avy
("M-." . embark-dwim))) :bind (("M-j" . avy-goto-char-timer)
("C-c j" . avy-goto-line)))
(use-package embark-consult ;; Pin files to numbered slots per project; jump to them instantly
:after (embark consult)) (use-package harpoon
:bind (("C-c h a" . harpoon-add-file)
("C-c h h" . harpoon-toggle-file)
("C-c h 1" . harpoon-go-to-1)
("C-c h 2" . harpoon-go-to-2)
("C-c h 3" . harpoon-go-to-3)
("C-c h 4" . harpoon-go-to-4)))
(use-package which-key ;; Expand selection by semantic units: word → symbol → string → block → …
:init (use-package expand-region
(which-key-mode) :bind ("C-=" . er/expand-region))
:config
(setq which-key-idle-delay 1))
;;; Key Bindings ------------------------------------------------------------- ;;; Git
;; Make ESC quit prompts.
(global-set-key (kbd "<escape>") #'keyboard-escape-quit)
;; windmove: S-Arrow to move between windows (built-in since Emacs 27).
(windmove-default-keybindings)
;;; Projects -----------------------------------------------------------------
(use-package projectile
:init
(when (file-directory-p "~/src")
(setq projectile-project-search-path '("~/src")))
(setq projectile-switch-project-action #'projectile-dired)
:config
(projectile-mode 1)
:bind-keymap
("C-c p" . projectile-command-map))
(use-package consult-projectile
:bind (("C-c h" . consult-projectile)))
;;; Git ----------------------------------------------------------------------
(use-package magit (use-package magit
:commands (magit-status magit-get-current-branch) :bind ("C-x g" . magit-status))
:bind (("C-x g" . magit-status)
("C-x M-g" . magit-dispatch)
("C-c M-g" . magit-file-dispatch))
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
(magit-diff-refine-hunk t)
(magit-auto-revert-mode nil)
(magit-process-find-password-functions '(magit-process-password-auth-source)))
;;; Org ---------------------------------------------------------------------- ;;; Direnv — respect .envrc per buffer (extends your shell direnv hook into Emacs)
(defun rh/org-mode-setup () (use-package envrc
(org-indent-mode) :hook (after-init . envrc-global-mode))
(visual-line-mode 1))
(use-package org ;;; Server — enables emacsclient ('e' alias) and AUCTeX inverse search
:hook (org-mode . rh/org-mode-setup)
:config
(setq org-agenda-files
(if (file-directory-p "~/org")
(directory-files-recursively "~/org" "\\.org$")
nil)))
(rh/load-user-file "org-bindings.el") (use-package server
(rh/load-user-file "common-dev-settings.el") :ensure nil
(rh/load-user-file "dev-settings.el") :config (unless (server-running-p) (server-start)))
(rh/load-user-file "latex-settings.el")
(rh/load-user-file "custom.el") ;;; Drop-in language configs (stow'd from laptop/ or work/)
(let ((lang-dir (expand-file-name "lisp/langs" user-emacs-directory)))
(when (file-directory-p lang-dir)
(dolist (f (directory-files lang-dir t "\\.el$"))
(load f nil t))))

View File

@@ -0,0 +1,7 @@
;;; lisp/langs/elisp.el --- Emacs Lisp -*- lexical-binding: t -*-
;; Inline macro expansion — C-c e to expand, q to collapse
(use-package macrostep
:bind (:map emacs-lisp-mode-map ("C-c e" . macrostep-expand)))
(add-hook 'emacs-lisp-mode-hook #'flymake-mode)

View File

@@ -0,0 +1,26 @@
;;; lisp/langs/org.el --- Org mode -*- lexical-binding: t -*-
(use-package org
:ensure nil
:custom
(org-directory "~/org")
(org-startup-indented t)
(org-startup-folded 'content)
(org-hide-emphasis-markers t)
(org-pretty-entities t)
(org-return-follows-link t)
(org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "WAITING(w)" "|" "DONE(d)" "CANCELLED(c)")))
:bind (("C-c a" . org-agenda)
("C-c c" . org-capture)
("C-c l" . org-store-link)))
;; Modern, clean visual style for org buffers and agenda
(use-package org-modern
:hook ((org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda)))
;; Reveal emphasis markers and links when cursor is on them
(use-package org-appear
:hook (org-mode . org-appear-mode)
:custom (org-appear-autolinks t))

View File

@@ -1,35 +0,0 @@
;;; org-bindings.el --- Standard Emacs keybindings for Org mode
(with-eval-after-load 'org
;; Org agenda and capture
(global-set-key (kbd "C-c o a") 'org-agenda)
(global-set-key (kbd "C-c o c") 'org-capture)
;; Link commands
(define-key org-mode-map (kbd "C-c o l") 'org-store-link)
(define-key org-mode-map (kbd "C-c o i") 'org-insert-link)
;; TODO and scheduling
(define-key org-mode-map (kbd "C-c o t") 'org-todo)
(define-key org-mode-map (kbd "C-c o s") 'org-schedule)
(define-key org-mode-map (kbd "C-c o d") 'org-deadline)
(define-key org-mode-map (kbd "C-c o T") 'org-time-stamp)
(define-key org-mode-map (kbd "C-c o p") 'org-priority)
;; Checkboxes and lists
(define-key org-mode-map (kbd "C-c o x") 'org-toggle-checkbox)
(define-key org-mode-map (kbd "C-c o -") 'org-ctrl-c-minus)
;; Refile
(define-key org-mode-map (kbd "C-c o r") 'org-refile))
;; Theme selection
(global-set-key (kbd "C-c t t") 'consult-theme)
;; Text scaling with standard Emacs bindings
(global-set-key (kbd "C-x C-=") 'text-scale-increase)
(global-set-key (kbd "C-x C--") 'text-scale-decrease)
(global-set-key (kbd "C-x C-0") 'text-scale-adjust)
(provide 'org-bindings)
;;; org-bindings.el ends here

View File

@@ -1,926 +0,0 @@
-- Set <space> as the leader key
-- See `:help mapleader`
-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used)
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
-- Set to true if you have a Nerd Font installed and selected in the terminal
vim.g.have_nerd_font = true
-- [[ Setting options ]]
-- See `:help vim.o`
-- NOTE: You can change these options as you wish!
-- For more options, you can see `:help option-list`
-- Make line numbers default
vim.o.number = true
-- You can also add relative line numbers, to help with jumping.
-- Experiment for yourself to see if you like it!
vim.o.relativenumber = true
-- Enable mouse mode, can be useful for resizing splits for example!
vim.o.mouse = 'a'
-- Don't show the mode, since it's already in the status line
vim.o.showmode = false
-- Sync clipboard between OS and Neovim.
-- Schedule the setting after `UiEnter` because it can increase startup-time.
-- Remove this option if you want your OS clipboard to remain independent.
-- See `:help 'clipboard'`
vim.schedule(function() vim.o.clipboard = 'unnamedplus' end)
-- Enable break indent
vim.o.breakindent = true
-- Enable undo/redo changes even after closing and reopening a file
vim.o.undofile = true
-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
vim.o.ignorecase = true
vim.o.smartcase = true
-- Keep signcolumn on by default
vim.o.signcolumn = 'yes'
-- Decrease update time
vim.o.updatetime = 250
-- Decrease mapped sequence wait time
vim.o.timeoutlen = 300
-- Configure how new splits should be opened
vim.o.splitright = true
vim.o.splitbelow = true
-- Sets how neovim will display certain whitespace characters in the editor.
-- See `:help 'list'`
-- and `:help 'listchars'`
--
-- Notice listchars is set using `vim.opt` instead of `vim.o`.
-- It is very similar to `vim.o` but offers an interface for conveniently interacting with tables.
-- See `:help lua-options`
-- and `:help lua-guide-options`
vim.o.list = true
vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '' }
-- Preview substitutions live, as you type!
vim.o.inccommand = 'split'
-- Show which line your cursor is on
vim.o.cursorline = true
-- Minimal number of screen lines to keep above and below the cursor.
vim.o.scrolloff = 10
-- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`),
-- instead raise a dialog asking if you wish to save the current file(s)
-- See `:help 'confirm'`
vim.o.confirm = true
-- [[ Basic Keymaps ]]
-- See `:help vim.keymap.set()`
-- Clear highlights on search when pressing <Esc> in normal mode
-- See `:help hlsearch`
vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>')
-- Diagnostic Config & Keymaps
-- See :help vim.diagnostic.Opts
vim.diagnostic.config {
update_in_insert = false,
severity_sort = true,
float = { border = 'rounded', source = 'if_many' },
underline = { severity = { min = vim.diagnostic.severity.WARN } },
-- Can switch between these as you prefer
virtual_text = true, -- Text shows up at the end of the line
virtual_lines = false, -- Text shows up underneath the line, with virtual lines
-- Auto open the float, so you can easily read the errors when jumping with `[d` and `]d`
-- Deprecated. Using new thing below
-- jump = { float = true },
jump = {
on_jump = function()
vim.diagnostic.open_float()
end,
},
}
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which
-- is not what someone will guess without a bit more experience.
--
-- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping
-- or just use <C-\><C-n> to exit terminal mode
vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' })
-- TIP: Disable arrow keys in normal mode
vim.keymap.set('n', '<left>', '<cmd>echo "Use h to move!!"<CR>')
vim.keymap.set('n', '<right>', '<cmd>echo "Use l to move!!"<CR>')
vim.keymap.set('n', '<up>', '<cmd>echo "Use k to move!!"<CR>')
vim.keymap.set('n', '<down>', '<cmd>echo "Use j to move!!"<CR>')
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' })
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' })
-- NOTE: Some terminals have colliding keymaps or are not able to send distinct keycodes
-- vim.keymap.set("n", "<C-S-h>", "<C-w>H", { desc = "Move window to the left" })
-- vim.keymap.set("n", "<C-S-l>", "<C-w>L", { desc = "Move window to the right" })
-- vim.keymap.set("n", "<C-S-j>", "<C-w>J", { desc = "Move window to the lower" })
-- vim.keymap.set("n", "<C-S-k>", "<C-w>K", { desc = "Move window to the upper" })
-- [[ Basic Autocommands ]]
-- See `:help lua-guide-autocommands`
-- Highlight when yanking (copying) text
-- Try it with `yap` in normal mode
-- See `:help vim.hl.on_yank()`
vim.api.nvim_create_autocmd('TextYankPost', {
desc = 'Highlight when yanking (copying) text',
group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }),
callback = function() vim.hl.on_yank() end,
})
-- [[ Install `lazy.nvim` plugin manager ]]
-- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info
local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath }
if vim.v.shell_error ~= 0 then error('Error cloning lazy.nvim:\n' .. out) end
end
---@type vim.Option
local rtp = vim.opt.rtp
rtp:prepend(lazypath)
-- [[ Configure and install plugins ]]
--
-- To check the current status of your plugins, run
-- :Lazy
--
-- You can press `?` in this menu for help. Use `:q` to close the window
--
-- To update plugins you can run
-- :Lazy update
--
-- NOTE: Here is where you install your plugins.
require('lazy').setup({
-- NOTE: Plugins can be added via a link or github org/name. To run setup automatically, use `opts = {}`
{ 'NMAC427/guess-indent.nvim', opts = {} },
-- Alternatively, use `config = function() ... end` for full control over the configuration.
-- If you prefer to call `setup` explicitly, use:
-- {
-- 'lewis6991/gitsigns.nvim',
-- config = function()
-- require('gitsigns').setup({
-- -- Your gitsigns configuration here
-- })
-- end,
-- }
--
-- Here is a more advanced example where we pass configuration
-- options to `gitsigns.nvim`.
--
-- See `:help gitsigns` to understand what the configuration keys do
{ -- Adds git related signs to the gutter, as well as utilities for managing changes
'lewis6991/gitsigns.nvim',
---@module 'gitsigns'
---@type Gitsigns.Config
---@diagnostic disable-next-line: missing-fields
opts = {
signs = {
add = { text = '+' }, ---@diagnostic disable-line: missing-fields
change = { text = '~' }, ---@diagnostic disable-line: missing-fields
delete = { text = '_' }, ---@diagnostic disable-line: missing-fields
topdelete = { text = '' }, ---@diagnostic disable-line: missing-fields
changedelete = { text = '~' }, ---@diagnostic disable-line: missing-fields
},
},
},
-- NOTE: Plugins can also be configured to run Lua code when they are loaded.
--
-- This is often very useful to both group configuration, as well as handle
-- lazy loading plugins that don't need to be loaded immediately at startup.
--
-- For example, in the following configuration, we use:
-- event = 'VimEnter'
--
-- which loads which-key before all the UI elements are loaded. Events can be
-- normal autocommands events (`:help autocmd-events`).
--
-- Then, because we use the `opts` key (recommended), the configuration runs
-- after the plugin has been loaded as `require(MODULE).setup(opts)`.
{ -- Useful plugin to show you pending keybinds.
'folke/which-key.nvim',
event = 'VimEnter',
---@module 'which-key'
---@type wk.Opts
---@diagnostic disable-next-line: missing-fields
opts = {
-- delay between pressing a key and opening which-key (milliseconds)
delay = 0,
icons = { mappings = vim.g.have_nerd_font },
-- Document existing key chains
spec = {
{ '<leader>s', group = '[S]earch', mode = { 'n', 'v' } },
{ '<leader>t', group = '[T]oggle' },
{ '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } }, -- Enable gitsigns recommended keymaps first
{ 'gr', group = 'LSP Actions', mode = { 'n' } },
},
},
},
-- NOTE: Plugins can specify dependencies.
--
-- The dependencies are proper plugin specifications as well - anything
-- you do for a plugin at the top level, you can do for a dependency.
--
-- Use the `dependencies` key to specify the dependencies of a particular plugin
{ -- Fuzzy Finder (files, lsp, etc)
'nvim-telescope/telescope.nvim',
-- By default, Telescope is included and acts as your picker for everything.
-- If you would like to switch to a different picker (like snacks, or fzf-lua)
-- you can disable the Telescope plugin by setting enabled to false and enable
-- your replacement picker by requiring it explicitly (e.g. 'custom.plugins.snacks')
-- Note: If you customize your config for yourself,
-- its best to remove the Telescope plugin config entirely
-- instead of just disabling it here, to keep your config clean.
enabled = true,
event = 'VimEnter',
dependencies = {
'nvim-lua/plenary.nvim',
{ -- If encountering errors, see telescope-fzf-native README for installation instructions
'nvim-telescope/telescope-fzf-native.nvim',
-- `build` is used to run some command when the plugin is installed/updated.
-- This is only run then, not every time Neovim starts up.
build = 'make',
-- `cond` is a condition used to determine whether this plugin should be
-- installed and loaded.
cond = function() return vim.fn.executable 'make' == 1 end,
},
{ 'nvim-telescope/telescope-ui-select.nvim' },
-- Useful for getting pretty icons, but requires a Nerd Font.
{ 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font },
},
config = function()
-- Telescope is a fuzzy finder that comes with a lot of different things that
-- it can fuzzy find! It's more than just a "file finder", it can search
-- many different aspects of Neovim, your workspace, LSP, and more!
--
-- The easiest way to use Telescope, is to start by doing something like:
-- :Telescope help_tags
--
-- After running this command, a window will open up and you're able to
-- type in the prompt window. You'll see a list of `help_tags` options and
-- a corresponding preview of the help.
--
-- Two important keymaps to use while in Telescope are:
-- - Insert mode: <c-/>
-- - Normal mode: ?
--
-- This opens a window that shows you all of the keymaps for the current
-- Telescope picker. This is really useful to discover what Telescope can
-- do as well as how to actually do it!
-- [[ Configure Telescope ]]
-- See `:help telescope` and `:help telescope.setup()`
require('telescope').setup {
-- You can put your default mappings / updates / etc. in here
-- All the info you're looking for is in `:help telescope.setup()`
--
-- defaults = {
-- mappings = {
-- i = { ['<c-enter>'] = 'to_fuzzy_refine' },
-- },
-- },
-- pickers = {}
extensions = {
['ui-select'] = { require('telescope.themes').get_dropdown() },
},
}
-- Enable Telescope extensions if they are installed
pcall(require('telescope').load_extension, 'fzf')
pcall(require('telescope').load_extension, 'ui-select')
-- See `:help telescope.builtin`
local builtin = require 'telescope.builtin'
vim.keymap.set('n', '<leader>sh', builtin.help_tags, { desc = '[S]earch [H]elp' })
vim.keymap.set('n', '<leader>sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' })
vim.keymap.set('n', '<leader>sf', builtin.find_files, { desc = '[S]earch [F]iles' })
vim.keymap.set('n', '<leader>ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' })
vim.keymap.set({ 'n', 'v' }, '<leader>sw', builtin.grep_string, { desc = '[S]earch current [W]ord' })
vim.keymap.set('n', '<leader>sg', builtin.live_grep, { desc = '[S]earch by [G]rep' })
vim.keymap.set('n', '<leader>sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' })
vim.keymap.set('n', '<leader>sr', builtin.resume, { desc = '[S]earch [R]esume' })
vim.keymap.set('n', '<leader>s.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
vim.keymap.set('n', '<leader>sc', builtin.commands, { desc = '[S]earch [C]ommands' })
vim.keymap.set('n', '<leader><leader>', builtin.buffers, { desc = '[ ] Find existing buffers' })
-- This runs on LSP attach per buffer (see main LSP attach function in 'neovim/nvim-lspconfig' config for more info,
-- it is better explained there). This allows easily switching between pickers if you prefer using something else!
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }),
callback = function(event)
local buf = event.buf
-- Find references for the word under your cursor.
vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' })
-- Jump to the implementation of the word under your cursor.
-- Useful when your language has ways of declaring types without an actual implementation.
vim.keymap.set('n', 'gri', builtin.lsp_implementations, { buffer = buf, desc = '[G]oto [I]mplementation' })
-- Jump to the definition of the word under your cursor.
-- This is where a variable was first declared, or where a function is defined, etc.
-- To jump back, press <C-t>.
vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' })
-- Fuzzy find all the symbols in your current document.
-- Symbols are things like variables, functions, types, etc.
vim.keymap.set('n', 'gO', builtin.lsp_document_symbols, { buffer = buf, desc = 'Open Document Symbols' })
-- Fuzzy find all the symbols in your current workspace.
-- Similar to document symbols, except searches over your entire project.
vim.keymap.set('n', 'gW', builtin.lsp_dynamic_workspace_symbols, { buffer = buf, desc = 'Open Workspace Symbols' })
-- Jump to the type of the word under your cursor.
-- Useful when you're not sure what type a variable is and you want to see
-- the definition of its *type*, not where it was *defined*.
vim.keymap.set('n', 'grt', builtin.lsp_type_definitions, { buffer = buf, desc = '[G]oto [T]ype Definition' })
end,
})
-- Override default behavior and theme when searching
vim.keymap.set('n', '<leader>/', function()
-- You can pass additional configuration to Telescope to change the theme, layout, etc.
builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
winblend = 10,
previewer = false,
})
end, { desc = '[/] Fuzzily search in current buffer' })
-- It's also possible to pass additional configuration options.
-- See `:help telescope.builtin.live_grep()` for information about particular keys
vim.keymap.set(
'n',
'<leader>s/',
function()
builtin.live_grep {
grep_open_files = true,
prompt_title = 'Live Grep in Open Files',
}
end,
{ desc = '[S]earch [/] in Open Files' }
)
-- Shortcut for searching your Neovim configuration files
vim.keymap.set('n', '<leader>sn', function() builtin.find_files { cwd = vim.fn.stdpath 'config' } end, { desc = '[S]earch [N]eovim files' })
end,
},
-- LSP Plugins
{
-- Main LSP Configuration
'neovim/nvim-lspconfig',
dependencies = {
-- Automatically install LSPs and related tools to stdpath for Neovim
-- Mason must be loaded before its dependents so we need to set it up here.
-- NOTE: `opts = {}` is the same as calling `require('mason').setup({})`
{
'mason-org/mason.nvim',
---@module 'mason.settings'
---@type MasonSettings
---@diagnostic disable-next-line: missing-fields
opts = {},
},
-- Maps LSP server names between nvim-lspconfig and Mason package names.
'mason-org/mason-lspconfig.nvim',
'WhoIsSethDaniel/mason-tool-installer.nvim',
-- Useful status updates for LSP.
{ 'j-hui/fidget.nvim', opts = {} },
},
config = function()
-- Brief aside: **What is LSP?**
--
-- LSP is an initialism you've probably heard, but might not understand what it is.
--
-- LSP stands for Language Server Protocol. It's a protocol that helps editors
-- and language tooling communicate in a standardized fashion.
--
-- In general, you have a "server" which is some tool built to understand a particular
-- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers
-- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone
-- processes that communicate with some "client" - in this case, Neovim!
--
-- LSP provides Neovim with features like:
-- - Go to definition
-- - Find references
-- - Autocompletion
-- - Symbol Search
-- - and more!
--
-- Thus, Language Servers are external tools that must be installed separately from
-- Neovim. This is where `mason` and related plugins come into play.
--
-- If you're wondering about lsp vs treesitter, you can check out the wonderfully
-- and elegantly composed help section, `:help lsp-vs-treesitter`
-- This function gets run when an LSP attaches to a particular buffer.
-- That is to say, every time a new file is opened that is associated with
-- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this
-- function will be executed to configure the current buffer
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }),
callback = function(event)
-- NOTE: Remember that Lua is a real programming language, and as such it is possible
-- to define small helper and utility functions so you don't have to repeat yourself.
--
-- In this case, we create a function that lets us more easily define mappings specific
-- for LSP related items. It sets the mode, buffer and description for us each time.
local map = function(keys, func, desc, mode)
mode = mode or 'n'
vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
end
-- Rename the variable under your cursor.
-- Most Language Servers support renaming across files, etc.
map('grn', vim.lsp.buf.rename, '[R]e[n]ame')
-- Execute a code action, usually your cursor needs to be on top of an error
-- or a suggestion from your LSP for this to activate.
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
-- WARN: This is not Goto Definition, this is Goto Declaration.
-- For example, in C this would take you to the header.
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
-- The following two autocommands are used to highlight references of the
-- word under your cursor when your cursor rests there for a little while.
-- See `:help CursorHold` for information about when this is executed
--
-- When you move your cursor, the highlights will be cleared (the second autocommand).
local client = vim.lsp.get_client_by_id(event.data.client_id)
if client and client:supports_method('textDocument/documentHighlight', event.buf) then
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
buffer = event.buf,
group = highlight_augroup,
callback = vim.lsp.buf.document_highlight,
})
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
buffer = event.buf,
group = highlight_augroup,
callback = vim.lsp.buf.clear_references,
})
vim.api.nvim_create_autocmd('LspDetach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }),
callback = function(event2)
vim.lsp.buf.clear_references()
vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf }
end,
})
end
-- The following code creates a keymap to toggle inlay hints in your
-- code, if the language server you are using supports them
--
-- This may be unwanted, since they displace some of your code
if client and client:supports_method('textDocument/inlayHint', event.buf) then
map('<leader>th', function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) end, '[T]oggle Inlay [H]ints')
end
end,
})
-- Enable the following language servers
-- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
-- See `:help lsp-config` for information about keys and how to configure
---@type table<string, vim.lsp.Config>
local servers = {
-- Web
html = {},
cssls = {},
eslint = {},
ts_ls = {},
-- C# / .NET
omnisharp = {},
-- csharp_ls = {}, --lighter if omnisharp is slow
stylua = {}, -- Used to format Lua code
-- Special Lua Config, as recommended by neovim help docs
lua_ls = {
on_init = function(client)
client.server_capabilities.documentFormattingProvider = false -- Disable formatting (formatting is done by stylua)
if client.workspace_folders then
local path = client.workspace_folders[1].name
if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then return end
end
client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, {
runtime = {
version = 'LuaJIT',
path = { 'lua/?.lua', 'lua/?/init.lua' },
},
workspace = {
checkThirdParty = false,
-- NOTE: this is a lot slower and will cause issues when working on your own configuration.
-- See https://github.com/neovim/nvim-lspconfig/issues/3189
library = vim.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), {
'${3rd}/luv/library',
'${3rd}/busted/library',
}),
},
})
end,
---@type lspconfig.settings.lua_ls
settings = {
Lua = {
format = { enable = false }, -- Disable formatting (formatting is done by stylua)
},
},
},
}
-- Ensure the servers and tools above are installed
--
-- To check the current status of installed tools and/or manually install
-- other tools, you can run
-- :Mason
--
-- You can press `g?` for help in this menu.
local ensure_installed = vim.tbl_keys(servers or {})
vim.list_extend(ensure_installed, {
-- You can add other tools here that you want Mason to install
'netcoredbg', -- C# Debugger
'csharpier', -- C# Formatter
'prettierd', -- Fast prettier for web files
})
require('mason-tool-installer').setup { ensure_installed = ensure_installed }
for name, server in pairs(servers) do
vim.lsp.config(name, server)
vim.lsp.enable(name)
end
end,
},
{ -- Autoformat
'stevearc/conform.nvim',
event = { 'BufWritePre' },
cmd = { 'ConformInfo' },
keys = {
{
'<leader>f',
function() require('conform').format { async = true } end,
mode = '',
desc = '[F]ormat buffer',
},
},
---@module 'conform'
---@type conform.setupOpts
opts = {
notify_on_error = false,
format_on_save = function(bufnr)
-- You can specify filetypes to autoformat on save here:
local enabled_filetypes = {
-- lua = true,
-- python = true,
}
if enabled_filetypes[vim.bo[bufnr].filetype] then
return { timeout_ms = 500 }
else
return nil
end
end,
default_format_opts = {
lsp_format = 'fallback', -- Use external formatters if configured below, otherwise use LSP formatting. Set to `false` to disable LSP formatting entirely.
},
-- You can also specify external formatters in here.
formatters_by_ft = {
lua = { 'stylua' },
cs = { 'csharpier' },
html = { 'prettierd' },
css = { 'prettierd' },
scss = { 'prettierd' },
javascript = { 'prettierd' },
javascriptreact = { 'prettierd' },
typescript = { 'prettierd' },
typescriptreact = { 'prettierd' },
json = { 'prettierd' },
jsonc = { 'prettierd' },
-- rust = { 'rustfmt' },
-- Conform can also run multiple formatters sequentially
-- python = { "isort", "black" },
--
-- You can use 'stop_after_first' to run the first available formatter from the list
-- javascript = { "prettierd", "prettier", stop_after_first = true },
},
},
},
{ -- Autocompletion
'saghen/blink.cmp',
event = 'VimEnter',
version = '1.*',
dependencies = {
-- Snippet Engine
{
'L3MON4D3/LuaSnip',
version = '2.*',
build = (function()
-- Build Step is needed for regex support in snippets.
-- This step is not supported in many windows environments.
-- Remove the below condition to re-enable on windows.
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then return end
return 'make install_jsregexp'
end)(),
dependencies = {
-- `friendly-snippets` contains a variety of premade snippets.
-- See the README about individual language/framework/plugin snippets:
-- https://github.com/rafamadriz/friendly-snippets
-- {
-- 'rafamadriz/friendly-snippets',
-- config = function()
-- require('luasnip.loaders.from_vscode').lazy_load()
-- end,
-- },
},
opts = {},
},
},
---@module 'blink.cmp'
---@type blink.cmp.Config
opts = {
keymap = {
-- 'default' (recommended) for mappings similar to built-in completions
-- <c-y> to accept ([y]es) the completion.
-- This will auto-import if your LSP supports it.
-- This will expand snippets if the LSP sent a snippet.
-- 'super-tab' for tab to accept
-- 'enter' for enter to accept
-- 'none' for no mappings
--
-- For an understanding of why the 'default' preset is recommended,
-- you will need to read `:help ins-completion`
--
-- No, but seriously. Please read `:help ins-completion`, it is really good!
--
-- All presets have the following mappings:
-- <tab>/<s-tab>: move to right/left of your snippet expansion
-- <c-space>: Open menu or open docs if already open
-- <c-n>/<c-p> or <up>/<down>: Select next/previous item
-- <c-e>: Hide menu
-- <c-k>: Toggle signature help
--
-- See :h blink-cmp-config-keymap for defining your own keymap
preset = 'default',
-- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see:
-- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps
},
appearance = {
-- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
-- Adjusts spacing to ensure icons are aligned
nerd_font_variant = 'mono',
},
completion = {
-- By default, you may press `<c-space>` to show the documentation.
-- Optionally, set `auto_show = true` to show the documentation after a delay.
documentation = { auto_show = false, auto_show_delay_ms = 500 },
},
sources = {
default = { 'lsp', 'path', 'snippets' },
},
snippets = { preset = 'luasnip' },
-- Blink.cmp includes an optional, recommended rust fuzzy matcher,
-- which automatically downloads a prebuilt binary when enabled.
--
-- By default, we use the Lua implementation instead, but you may enable
-- the rust implementation via `'prefer_rust_with_warning'`
--
-- See :h blink-cmp-config-fuzzy for more information
fuzzy = { implementation = 'lua' },
-- Shows a signature help window while you type arguments for a function
signature = { enabled = true },
},
},
{ -- You can easily change to a different colorscheme.
-- Change the name of the colorscheme plugin below, and then
-- change the command in the config to whatever the name of that colorscheme is.
--
-- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`.
'folke/tokyonight.nvim',
priority = 1000, -- Make sure to load this before all the other start plugins.
config = function()
---@diagnostic disable-next-line: missing-fields
require('tokyonight').setup {
styles = {
comments = { italic = false }, -- Disable italics in comments
},
}
-- Load the colorscheme here.
-- Like many other themes, this one has different styles, and you could load
-- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'.
vim.cmd.colorscheme 'tokyonight-night'
end,
},
-- Highlight todo, notes, etc in comments
{
'folke/todo-comments.nvim',
event = 'VimEnter',
dependencies = { 'nvim-lua/plenary.nvim' },
---@module 'todo-comments'
---@type TodoOptions
---@diagnostic disable-next-line: missing-fields
opts = { signs = false },
},
{ -- Collection of various small independent plugins/modules
'nvim-mini/mini.nvim',
config = function()
-- Better Around/Inside textobjects
--
-- Examples:
-- - va) - [V]isually select [A]round [)]paren
-- - yiiq - [Y]ank [I]nside [I]+1 [Q]uote
-- - ci' - [C]hange [I]nside [']quote
require('mini.ai').setup {
-- NOTE: Avoid conflicts with the built-in incremental selection mappings on Neovim>=0.12 (see `:help treesitter-incremental-selection`)
mappings = {
around_next = 'aa',
inside_next = 'ii',
},
n_lines = 500,
}
-- Add/delete/replace surroundings (brackets, quotes, etc.)
--
-- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
-- - sd' - [S]urround [D]elete [']quotes
-- - sr)' - [S]urround [R]eplace [)] [']
require('mini.surround').setup()
-- Simple and easy statusline.
-- You could remove this setup call if you don't like it,
-- and try some other statusline plugin
local statusline = require 'mini.statusline'
-- set use_icons to true if you have a Nerd Font
statusline.setup { use_icons = vim.g.have_nerd_font }
-- You can configure sections in the statusline by overriding their
-- default behavior. For example, here we set the section for
-- cursor location to LINE:COLUMN
---@diagnostic disable-next-line: duplicate-set-field
statusline.section_location = function() return '%2l:%-2v' end
-- ... and there is more!
-- Check out: https://github.com/nvim-mini/mini.nvim
end,
},
{ -- Highlight, edit, and navigate code
'nvim-treesitter/nvim-treesitter',
lazy = false,
build = ':TSUpdate',
branch = 'main',
-- [[ Configure Treesitter ]] See `:help nvim-treesitter-intro`
config = function()
-- ensure basic parser are installed
local parsers = {
'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc',
'c_sharp', 'css', 'javascript', 'typescript', 'tsx', 'json', 'regex',
}
require('nvim-treesitter').install(parsers)
---@param buf integer
---@param language string
local function treesitter_try_attach(buf, language)
-- check if parser exists and load it
if not vim.treesitter.language.add(language) then return end
-- enables syntax highlighting and other treesitter features
vim.treesitter.start(buf, language)
-- enables treesitter based folds
-- for more info on folds see `:help folds`
-- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
-- vim.wo.foldmethod = 'expr'
-- check if treesitter indentation is available for this language, and if so enable it
-- in case there is no indent query, the indentexpr will fallback to the vim's built in one
local has_indent_query = vim.treesitter.query.get(language, 'indents') ~= nil
-- enables treesitter based indentation
if has_indent_query then vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" end
end
local available_parsers = require('nvim-treesitter').get_available()
vim.api.nvim_create_autocmd('FileType', {
callback = function(args)
local buf, filetype = args.buf, args.match
local language = vim.treesitter.language.get_lang(filetype)
if not language then return end
local installed_parsers = require('nvim-treesitter').get_installed 'parsers'
if vim.tbl_contains(installed_parsers, language) then
-- enable the parser if it is installed
treesitter_try_attach(buf, language)
elseif vim.tbl_contains(available_parsers, language) then
-- if a parser is available in `nvim-treesitter` auto install it, and enable it after the installation is done
require('nvim-treesitter').install(language):await(function() treesitter_try_attach(buf, language) end)
else
-- try to enable treesitter features in case the parser exists but is not available from `nvim-treesitter`
treesitter_try_attach(buf, language)
end
end,
})
end,
},
-- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the
-- init.lua. If you want these files, they are in the repository, so you can just download them and
-- place them in the correct locations.
-- NOTE: Next step on your Neovim journey: Add/Configure additional plugins for Kickstart
--
-- Here are some example plugins that I've included in the Kickstart repository.
-- Uncomment any of the lines below to enable them (you will need to restart nvim).
--
require 'kickstart.plugins.debug',
-- require 'kickstart.plugins.indent_line',
-- require 'kickstart.plugins.lint',
-- require 'kickstart.plugins.autopairs',
-- require 'kickstart.plugins.neo-tree',
-- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps
-- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua`
-- This is the easiest way to modularize your config.
--
-- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going.
{ import = 'custom.plugins' },
--
-- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec`
-- Or use telescope!
-- In normal mode type `<space>sh` then write `lazy.nvim-plugin`
-- you can continue same window with `<space>sr` which resumes last telescope search
}, { ---@diagnostic disable-line: missing-fields
ui = {
-- If you are using a Nerd Font: set icons to an empty table which will use the
-- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table
icons = vim.g.have_nerd_font and {} or {
cmd = '',
config = '🛠',
event = '📅',
ft = '📂',
init = '',
keys = '🗝',
plugin = '🔌',
runtime = '💻',
require = '🌙',
source = '📄',
start = '🚀',
task = '📌',
lazy = '💤 ',
},
},
})
-- The line beneath this is called `modeline`. See `:help modeline`
-- vim: ts=2 sts=2 sw=2 et

View File

@@ -1,30 +0,0 @@
{
"LuaSnip": { "branch": "master", "commit": "642b0c595e11608b4c18219e93b88d7637af27bc" },
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
"conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" },
"fidget.nvim": { "branch": "main", "commit": "889e2e96edef4e144965571d46f7a77bcc4d0ddf" },
"gitsigns.nvim": { "branch": "main", "commit": "6d808f99bd63303646794406e270bd553ad7792e" },
"guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" },
"harpoon": { "branch": "harpoon2", "commit": "87b1a3506211538f460786c23f98ec63ad9af4e5" },
"lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
"lazygit.nvim": { "branch": "main", "commit": "a04ad0dbc725134edbee3a5eea29290976695357" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "0a3b42c3e503df87aef6d6513e13148381495c3a" },
"mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" },
"mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" },
"mason.nvim": { "branch": "main", "commit": "12ddd182d9efbdc848b540f16484a583d52da0fb" },
"mini.nvim": { "branch": "main", "commit": "5849ef04c32a6a8e55957b946c0a275801d87530" },
"nvim-dap": { "branch": "master", "commit": "45a69eba683a2c448dd9ecfc4de89511f0646b5f" },
"nvim-dap-go": { "branch": "main", "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" },
"nvim-dap-ui": { "branch": "master", "commit": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49" },
"nvim-lspconfig": { "branch": "master", "commit": "e146efacbafed3789ac568abcc5a981c5decaa58" },
"nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" },
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
"nvim-web-devicons": { "branch": "master", "commit": "c72328a5494b4502947a022fe69c0c47e53b6aa6" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" },
"telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" },
"telescope.nvim": { "branch": "master", "commit": "506338434fec5ad19cb1f8d45bf92d66c4917393" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
}

View File

@@ -1,30 +0,0 @@
return {
{
'ThePrimeagen/harpoon',
branch = 'harpoon2',
dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
local harpoon = require 'harpoon'
harpoon:setup()
-- Add current file to list
vim.keymap.set('n', '<leader>a', function() harpoon:list():add() end,
{ desc = 'Harpoon: [A]dd file' })
-- Toggle the quick menu
vim.keymap.set('n', '<leader>e', function() harpoon.ui:toggle_quick_menu(harpoon:list()) end,
{ desc = 'Harpoon: Toggle m[E]nu' })
-- Jump to file slots 1-4
-- NOTE: avoid <C-h/j/k/l> - kickstart uses these for window navigation
vim.keymap.set('n', '<leader>1', function() harpoon:list():select(1) end, { desc = 'Harpoon: File [1]' })
vim.keymap.set('n', '<leader>2', function() harpoon:list():select(2) end, { desc = 'Harpoon: File [2]' })
vim.keymap.set('n', '<leader>3', function() harpoon:list():select(3) end, { desc = 'Harpoon: File [3]' })
vim.keymap.set('n', '<leader>4', function() harpoon:list():select(4) end, { desc = 'Harpoon: File [4]' })
-- Prev/Next in list
vim.keymap.set('n', '<leader>[', function() harpoon:list():prev() end, { desc = 'Harpoon: Prev' })
vim.keymap.set('n', '<leader>]', function() harpoon:list():prev() end, { desc = 'Harpoon: Next' })
end,
},
}

View File

@@ -1,8 +0,0 @@
-- You can add your own plugins here or in other files in this directory!
-- I promise not to create any merge conflicts in this directory :)
--
-- See the kickstart.nvim README for more information
---@module 'lazy'
---@type LazySpec
return {}

View File

@@ -1,52 +0,0 @@
--[[
--
-- This file is not required for your own configuration,
-- but helps people determine if their system is setup correctly.
--
--]]
local check_version = function()
local verstr = tostring(vim.version())
if not vim.version.ge then
vim.health.error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr))
return
end
if vim.version.ge(vim.version(), '0.11') then
vim.health.ok(string.format("Neovim version is: '%s'", verstr))
else
vim.health.error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr))
end
end
local check_external_reqs = function()
-- Basic utils: `git`, `make`, `unzip`
for _, exe in ipairs { 'git', 'make', 'unzip', 'rg' } do
local is_executable = vim.fn.executable(exe) == 1
if is_executable then
vim.health.ok(string.format("Found executable: '%s'", exe))
else
vim.health.warn(string.format("Could not find executable: '%s'", exe))
end
end
return true
end
return {
check = function()
vim.health.start 'kickstart.nvim'
vim.health.info [[NOTE: Not every warning is a 'must-fix' in `:checkhealth`
Fix only warnings for plugins and languages you intend to use.
Mason will give warnings for languages that are not installed.
You do not need to install, unless you want to use those languages!]]
local uv = vim.uv or vim.loop
vim.health.info('System Information: ' .. vim.inspect(uv.os_uname()))
check_version()
check_external_reqs()
end,
}

View File

@@ -1,10 +0,0 @@
-- autopairs
-- https://github.com/windwp/nvim-autopairs
---@module 'lazy'
---@type LazySpec
return {
'windwp/nvim-autopairs',
event = 'InsertEnter',
opts = {},
}

View File

@@ -1,131 +0,0 @@
-- debug.lua
--
-- Shows how to use the DAP plugin to debug your code.
--
-- Primarily focused on configuring the debugger for Go, but can
-- be extended to other languages as well. That's why it's called
-- kickstart.nvim and not kitchen-sink.nvim ;)
---@module 'lazy'
---@type LazySpec
return {
-- NOTE: Yes, you can install new plugins here!
'mfussenegger/nvim-dap',
-- NOTE: And you can specify dependencies as well
dependencies = {
-- Creates a beautiful debugger UI
'rcarriga/nvim-dap-ui',
-- Required dependency for nvim-dap-ui
'nvim-neotest/nvim-nio',
-- Installs the debug adapters for you
'mason-org/mason.nvim',
'jay-babu/mason-nvim-dap.nvim',
-- Add your own debuggers here
'leoluz/nvim-dap-go',
},
keys = {
-- Basic debugging keymaps, feel free to change to your liking!
{ '<F5>', function() require('dap').continue() end, desc = 'Debug: Start/Continue' },
{ '<F1>', function() require('dap').step_into() end, desc = 'Debug: Step Into' },
{ '<F2>', function() require('dap').step_over() end, desc = 'Debug: Step Over' },
{ '<F3>', function() require('dap').step_out() end, desc = 'Debug: Step Out' },
{ '<leader>b', function() require('dap').toggle_breakpoint() end, desc = 'Debug: Toggle Breakpoint' },
{ '<leader>B', function() require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ') end, desc = 'Debug: Set Breakpoint' },
-- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception.
{ '<F7>', function() require('dapui').toggle() end, desc = 'Debug: See last session result.' },
},
config = function()
local dap = require 'dap'
local dapui = require 'dapui'
require('mason-nvim-dap').setup {
-- Makes a best effort to setup the various debuggers with
-- reasonable debug configurations
automatic_installation = true,
-- You can provide additional configuration to the handlers,
-- see mason-nvim-dap README for more information
handlers = {
coreclr = function(config)
config.adapters = {
type = 'executable',
command = vim.fn.exepath 'netcoredbg',
args = { '--interpreter=vscode' },
}
require('dap').adapters.coreclr = config.adapters
end,
},
-- You'll need to check that you have the required things installed
-- online, please don't ask me how to install them :)
ensure_installed = {
-- Update this to ensure that you have the debuggers for the langs you want
'delve',
'netcoredbg',
'js-debug-adapter',
},
}
-- Dap UI setup
-- For more information, see |:help nvim-dap-ui|
---@diagnostic disable-next-line: missing-fields
dapui.setup {
-- Set icons to characters that are more likely to work in every terminal.
-- Feel free to remove or use ones that you like more! :)
-- Don't feel like these are good choices.
icons = { expanded = '', collapsed = '', current_frame = '*' },
---@diagnostic disable-next-line: missing-fields
controls = {
icons = {
pause = '',
play = '',
step_into = '',
step_over = '',
step_out = '',
step_back = 'b',
run_last = '▶▶',
terminate = '',
disconnect = '',
},
},
}
-- Change breakpoint icons
-- vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' })
-- vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' })
-- local breakpoint_icons = vim.g.have_nerd_font
-- and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' }
-- or { Breakpoint = '●', BreakpointCondition = '⊜', BreakpointRejected = '⊘', LogPoint = '◆', Stopped = '⭔' }
-- for type, icon in pairs(breakpoint_icons) do
-- local tp = 'Dap' .. type
-- local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak'
-- vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl })
-- end
dap.configurations.cs = {
{
type = 'coreclr',
name = 'Launch .NET',
request = 'launch',
program = function()
return vim.fn.input('Path to dll: ', vim.fn.getcwd() .. '/bin/Debug/', 'file')
end,
},
}
dap.listeners.after.event_initialized['dapui_config'] = dapui.open
dap.listeners.before.event_terminated['dapui_config'] = dapui.close
dap.listeners.before.event_exited['dapui_config'] = dapui.close
-- Install golang specific config
require('dap-go').setup {
delve = {
-- On Windows delve must be run attached or it crashes.
-- See https://github.com/leoluz/nvim-dap-go/blob/main/README.md#configuring
detached = vim.fn.has 'win32' == 0,
},
}
end,
}

View File

@@ -1,63 +0,0 @@
-- Adds git related signs to the gutter, as well as utilities for managing changes
-- NOTE: gitsigns is already included in init.lua but contains only the base
-- config. This will add also the recommended keymaps.
---@module 'lazy'
---@type LazySpec
return {
'lewis6991/gitsigns.nvim',
---@module 'gitsigns'
---@type Gitsigns.Config
---@diagnostic disable-next-line: missing-fields
opts = {
on_attach = function(bufnr)
local gitsigns = require 'gitsigns'
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
map('n', ']c', function()
if vim.wo.diff then
vim.cmd.normal { ']c', bang = true }
else
gitsigns.nav_hunk 'next'
end
end, { desc = 'Jump to next git [c]hange' })
map('n', '[c', function()
if vim.wo.diff then
vim.cmd.normal { '[c', bang = true }
else
gitsigns.nav_hunk 'prev'
end
end, { desc = 'Jump to previous git [c]hange' })
-- Actions
-- visual mode
map('v', '<leader>hs', function() gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [s]tage hunk' })
map('v', '<leader>hr', function() gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [r]eset hunk' })
-- normal mode
map('n', '<leader>hs', gitsigns.stage_hunk, { desc = 'git [s]tage hunk' })
map('n', '<leader>hr', gitsigns.reset_hunk, { desc = 'git [r]eset hunk' })
map('n', '<leader>hS', gitsigns.stage_buffer, { desc = 'git [S]tage buffer' })
map('n', '<leader>hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' })
map('n', '<leader>hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' })
map('n', '<leader>hi', gitsigns.preview_hunk_inline, { desc = 'git preview hunk [i]nline' })
map('n', '<leader>hb', function() gitsigns.blame_line { full = true } end, { desc = 'git [b]lame line' })
map('n', '<leader>hd', gitsigns.diffthis, { desc = 'git [d]iff against index' })
map('n', '<leader>hD', function() gitsigns.diffthis '@' end, { desc = 'git [D]iff against last commit' })
map('n', '<leader>hQ', function() gitsigns.setqflist 'all' end, { desc = 'git hunk [Q]uickfix list (all files in repo)' })
map('n', '<leader>hq', gitsigns.setqflist, { desc = 'git hunk [q]uickfix list (all changes in this file)' })
-- Toggles
map('n', '<leader>tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' })
map('n', '<leader>tw', gitsigns.toggle_word_diff, { desc = '[T]oggle git intra-line [w]ord diff' })
-- Text object
map({ 'o', 'x' }, 'ih', gitsigns.select_hunk)
end,
},
}

View File

@@ -1,13 +0,0 @@
-- Add indentation guides even on blank lines
---@module 'lazy'
---@type LazySpec
return {
'lukas-reineke/indent-blankline.nvim',
-- Enable `lukas-reineke/indent-blankline.nvim`
-- See `:help ibl`
main = 'ibl',
---@module 'ibl'
---@type ibl.config
opts = {},
}

View File

@@ -1,59 +0,0 @@
-- Linting
---@module 'lazy'
---@type LazySpec
return {
'mfussenegger/nvim-lint',
event = { 'BufReadPre', 'BufNewFile' },
config = function()
local lint = require 'lint'
lint.linters_by_ft = {
markdown = { 'markdownlint' }, -- Make sure to install `markdownlint` via mason / npm
}
-- To allow other plugins to add linters to require('lint').linters_by_ft,
-- instead set linters_by_ft like this:
-- lint.linters_by_ft = lint.linters_by_ft or {}
-- lint.linters_by_ft['markdown'] = { 'markdownlint' }
--
-- However, note that this will enable a set of default linters,
-- which will cause errors unless these tools are available:
-- {
-- clojure = { "clj-kondo" },
-- dockerfile = { "hadolint" },
-- inko = { "inko" },
-- janet = { "janet" },
-- json = { "jsonlint" },
-- markdown = { "vale" },
-- rst = { "vale" },
-- ruby = { "ruby" },
-- terraform = { "tflint" },
-- text = { "vale" }
-- }
--
-- You can disable the default linters by setting their filetypes to nil:
-- lint.linters_by_ft['clojure'] = nil
-- lint.linters_by_ft['dockerfile'] = nil
-- lint.linters_by_ft['inko'] = nil
-- lint.linters_by_ft['janet'] = nil
-- lint.linters_by_ft['json'] = nil
-- lint.linters_by_ft['markdown'] = nil
-- lint.linters_by_ft['rst'] = nil
-- lint.linters_by_ft['ruby'] = nil
-- lint.linters_by_ft['terraform'] = nil
-- lint.linters_by_ft['text'] = nil
-- Create autocommand which carries out the actual linting
-- on the specified events.
local lint_augroup = vim.api.nvim_create_augroup('lint', { clear = true })
vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, {
group = lint_augroup,
callback = function()
-- Only run the linter in buffers that you can modify in order to
-- avoid superfluous noise, notably within the handy LSP pop-ups that
-- describe the hovered symbol using Markdown.
if vim.bo.modifiable then lint.try_lint() end
end,
})
end,
}

View File

@@ -1,29 +0,0 @@
-- Neo-tree is a Neovim plugin to browse the file system
-- https://github.com/nvim-neo-tree/neo-tree.nvim
---@module 'lazy'
---@type LazySpec
return {
'nvim-neo-tree/neo-tree.nvim',
version = '*',
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended
'MunifTanjim/nui.nvim',
},
lazy = false,
keys = {
{ '\\', ':Neotree reveal<CR>', desc = 'NeoTree reveal', silent = true },
},
---@module 'neo-tree'
---@type neotree.Config
opts = {
filesystem = {
window = {
mappings = {
['\\'] = 'close_window',
},
},
},
},
}

View File

@@ -15,7 +15,7 @@ unsetopt HIST_IGNORE_ALL_DUPS HIST_EXPIRE_DUPS_FIRST EXTENDED_HISTORY
PROMPT="%F{blue}%m %~%b"$'\n'"%(?.%F{green}%Bλ%b |.%F{red}?) %f" PROMPT="%F{blue}%m %~%b"$'\n'"%(?.%F{green}%Bλ%b |.%F{red}?) %f"
# PATH # PATH
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$HOME/go/bin:$HOME/.local/bin:$PATH" export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$HOME/go/bin:$HOME/.local/bin:/snap/bin:$PATH"
# Aliases # Aliases
alias e="emacsclient -t -a \"\"" alias e="emacsclient -t -a \"\""
@@ -45,6 +45,11 @@ eval "$(keychain --eval --quiet github git)"
# direnv hook # direnv hook
eval "$(direnv hook zsh)" eval "$(direnv hook zsh)"
# Start Emacs daemon if not already running
if ! emacsclient -e nil &>/dev/null; then
emacs --daemon &>/dev/null &
fi
echo -ne '\e[1 q' echo -ne '\e[1 q'
export NVM_DIR="$HOME/.nvm" export NVM_DIR="$HOME/.nvm"

View File

@@ -1,62 +0,0 @@
;;; dev-settings.el --- Work development environment (C#, TypeScript, JavaScript, CSS, HTML)
;;; C#
;; LSP server: dotnet tool install -g csharp-ls
(use-package csharp-ts-mode
:ensure nil
:mode "\\.cs\\'"
:hook (csharp-ts-mode . eglot-ensure))
;;; TypeScript / TSX
(use-package typescript-ts-mode
:ensure nil
:mode (("\\.ts\\'" . typescript-ts-mode)
("\\.tsx\\'" . tsx-ts-mode))
:hook ((typescript-ts-mode . eglot-ensure)
(tsx-ts-mode . eglot-ensure)))
;;; JavaScript / JSX
;; typescript-language-server handles JS too; install via: npm i -g typescript-language-server typescript
(use-package js-ts-mode
:ensure nil
:mode (("\\.js\\'" . js-ts-mode)
("\\.mjs\\'" . js-ts-mode)
("\\.cjs\\'" . js-ts-mode)
("\\.jsx\\'" . js-ts-mode))
:hook (js-ts-mode . eglot-ensure)
:config
(setq js-indent-level 2))
;;; CSS
;; LSP server: npm i -g vscode-langservers-extracted
(use-package css-ts-mode
:ensure nil
:mode "\\.css\\'"
:hook (css-ts-mode . eglot-ensure)
:config
(setq css-indent-offset 2))
;;; HTML
;; LSP server: npm i -g vscode-langservers-extracted
(use-package html-ts-mode
:ensure nil
:mode (("\\.html\\'" . html-ts-mode)
("\\.htm\\'" . html-ts-mode))
:hook (html-ts-mode . eglot-ensure))
;;; Prettier (formatting for JS/TS/CSS/HTML)
(use-package prettier
:hook ((typescript-ts-mode . prettier-mode)
(tsx-ts-mode . prettier-mode)
(js-ts-mode . prettier-mode)
(css-ts-mode . prettier-mode)
(html-ts-mode . prettier-mode)))
(provide 'dev-settings)
;;; dev-settings.el ends here

View File

@@ -0,0 +1,16 @@
;;; lisp/langs/copilot.el --- GitHub Copilot -*- lexical-binding: t -*-
;; copilot.el is not on MELPA; installed via package-vc (Emacs 29+)
(use-package copilot
:vc (:url "https://github.com/copilot-emacs/copilot.el" :rev :newest)
:hook (prog-mode . copilot-mode)
:bind (:map copilot-completion-map
;; copilot-completion-map is only active when ghost text is showing,
;; so these bindings don't interfere with Corfu's popup
("<tab>" . copilot-accept-completion)
("TAB" . copilot-accept-completion)
("M-f" . copilot-accept-completion-by-word)
("M-n" . copilot-next-completion)
("M-p" . copilot-previous-completion))
:custom
(copilot-idle-delay 0.5))

View File

@@ -0,0 +1,9 @@
;;; lisp/langs/csharp.el --- C# -*- lexical-binding: t -*-
;; csharp-ts-mode is built-in since Emacs 29
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((csharp-mode csharp-ts-mode) . ("csharp-ls"))))
(dolist (hook '(csharp-mode-hook csharp-ts-mode-hook))
(add-hook hook #'eglot-ensure))

View File

@@ -0,0 +1,42 @@
;;; lisp/langs/web.el --- JS / TS / HTML / CSS / React -*- lexical-binding: t -*-
;; web-mode for JSX, TSX, and HTML template files
(use-package web-mode
:mode (("\\.jsx\\'" . web-mode)
("\\.tsx\\'" . web-mode)
("\\.html?\\'" . web-mode))
:custom
(web-mode-markup-indent-offset 2)
(web-mode-css-indent-offset 2)
(web-mode-code-indent-offset 2))
;; typescript-language-server handles JS, TS, JSX, TSX
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((js-mode js-ts-mode typescript-ts-mode tsx-ts-mode web-mode)
. ("typescript-language-server" "--stdio")))
(add-to-list 'eglot-server-programs
'((html-mode mhtml-mode)
. ("vscode-html-language-server" "--stdio")))
(add-to-list 'eglot-server-programs
'((css-mode css-ts-mode)
. ("vscode-css-language-server" "--stdio"))))
(dolist (hook '(js-mode-hook js-ts-mode-hook
typescript-ts-mode-hook tsx-ts-mode-hook
web-mode-hook
html-mode-hook mhtml-mode-hook
css-mode-hook css-ts-mode-hook))
(add-hook hook #'eglot-ensure))
;; Async formatting via Prettier (apheleia runs formatters without blocking)
(use-package apheleia
:hook ((js-mode . apheleia-mode)
(js-ts-mode . apheleia-mode)
(typescript-ts-mode . apheleia-mode)
(tsx-ts-mode . apheleia-mode)
(css-mode . apheleia-mode)
(css-ts-mode . apheleia-mode)
(web-mode . apheleia-mode))
:config
(setf (alist-get 'web-mode apheleia-mode-alist) '(prettier)))