#+TITLE: Ezri's Settings #+AUTHOR: Ezri & Simponic #+STARTUP: fold Shamelessly stole this from Simponic, made some limited modifications myself. Namely to indent style, theme, and line numbers. Also added Github Copilot. * Packages ** Melpa #+BEGIN_SRC emacs-lisp (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) #+END_SRC * General emacs ** Indentation Indent using tabs, render with tab-width of 2. #+BEGIN_SRC emacs-lisp (setq default-tab-width 2) (setq-default tab-width 2) (setq-default indent-tabs-mode t) (setq sh-indentation 2) (smart-tabs-insinuate 'c 'c++ 'java 'javascript 'python) (add-hook 'conf-mode-hook (lambda () (setq indent-line-function #'insert-tab indent-tabs-mode t))) (add-hook 'nftables-mode-hook (lambda () (setq indent-tabs-mode nil))) #+END_SRC ** Line numbers #+BEGIN_SRC emacs-lisp (global-display-line-numbers-mode) #+END_SRC ** Filesystem stuff #+BEGIN_SRC emacs-lisp (setq auto-save-default nil) (setq make-backup-files nil) (setq create-lockfiles nil) (global-auto-revert-mode t) ;; Change files on disk as they are updated #+END_SRC ** UI stuff #+BEGIN_SRC emacs-lisp ;; (when (window-system) ;; (menu-bar-mode -1) ;; (tool-bar-mode -1) ;; (toggle-scroll-bar -1) ;; (if (display-graphic-p) ;; (funcall (lambda () ;; (set-fringe-mode '(1 . 1)) ;; ))) ;; (setq frame-resize-pixelwise t)) (setq inhibit-startup-screen t) (defun my-frame-config (&optional frame) (setq frame-resize-pixelwise t) (if (display-graphic-p) (set-fringe-mode '(1 . 1))) (if (not frame) ;; The initial call, run when emacs starts (funcall (lambda () (menu-bar-mode -1) (tool-bar-mode -1) (toggle-scroll-bar -1) ))) ;;-----------------------------------------;; ;; reinitialize modes in case of new frame ;; ;;-----------------------------------------;; (if menu-bar-mode (menu-bar-mode -1)) (if tool-bar-mode (tool-bar-mode -1)) (if scroll-bar-mode (scroll-bar-mode -1))) (my-frame-config) ;; Run initially so that direct invocations work (add-hook 'after-make-frame-functions 'my-frame-config) #+END_SRC ** TUI stuff #+BEGIN_SRC emacs-lisp (defun terminal-config (&optional frame) "Establish settings for teh current terminal." (if (not frame) ;; The initial call. (xterm-mouse-mode 1) (if xterm-mouse-mode ;; Re-initialize the mode in case of a new terminal. (xterm-mouse-mode 1)))) (terminal-config) (add-hook 'after-make-frame-functions 'terminal-config) #+END_SRC ** Custom keymap #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-;") 'comment-or-uncomment-region) #+END_SRC ** System path (macos) #+BEGIN_SRC emacs-lisp ;; Use system path on macos - needed for node (use-package exec-path-from-shell :ensure t :init (when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize))) #+END_SRC ** Execute command to buffer #+BEGIN_SRC emacs-lisp (defun shell-command-capture-output (command) (interactive "sShell command: ") ;; run shell command (with-output-to-temp-buffer "*Shell Command Output*" (shell-command command "*Shell Command Output*") (pop-to-buffer "*Shell Command Output*") ;; make buffer read-only (read-only-mode))) #+END_SRC * Theming ** Highlight current line #+BEGIN_SRC emacs-lisp (global-hl-line-mode) #+END_SRC ** Font #+BEGIN_SRC emacs-lisp (add-to-list 'default-frame-alist '(font . "JetBrains Mono-9")) #+END_SRC ** Doom-themes #+BEGIN_SRC emacs-lisp (defun my-theme-config (&optional frame) (use-package doom-themes :ensure t :config ;; Global settings (defaults) (setq doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-italic t) ; if nil, italics is universally disabled (load-theme 'doom-personal t) ;; Enable flashing mode-line on errors (doom-themes-visual-bell-config) ;; Enable custom neotree theme (all-the-icons must be installed!) (doom-themes-neotree-config) ;; or for treemacs users (setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme (doom-themes-treemacs-config) ;; Corrects (and improves) org-mode's native fontification. (doom-themes-org-config))) (my-theme-config) (add-hook 'after-make-frame-functions 'my-theme-config) #+END_SRC ** Doom-modeline #+BEGIN_SRC emacs-lisp (defun my-modeline-config (&optional frame) (use-package doom-modeline :ensure t :init (doom-modeline-mode 1))) (my-modeline-config) (add-hook 'after-make-frame-functions 'my-modeline-config) #+END_SRC ** All the icons #+BEGIN_SRC emacs-lisp (use-package all-the-icons :ensure t) #+END_SRC ** Tabs #+BEGIN_SRC emacs-lisp (defun my/set-tab-theme () (let ((bg (face-attribute 'mode-line :background)) (fg (face-attribute 'default :foreground)) (hg (face-attribute 'default :background)) (base (face-attribute 'mode-line :background)) (box-width (/ (line-pixel-height) 4))) (set-face-attribute 'tab-line nil :background base :foreground fg :height 0.8 :inherit nil :box (list :line-width -1 :color base) ) (set-face-attribute 'tab-line-tab nil :foreground fg :background bg :weight 'normal :inherit nil :box (list :line-width box-width :color bg)) (set-face-attribute 'tab-line-tab-inactive nil :foreground fg :background base :weight 'normal :inherit nil :box (list :line-width box-width :color base)) (set-face-attribute 'tab-line-highlight nil :foreground fg :background hg :weight 'normal :inherit nil :box (list :line-width box-width :color hg)) (set-face-attribute 'tab-line-tab-current nil :foreground fg :background hg :weight 'normal :inherit nil :box (list :line-width box-width :color hg)))) (defun my/tab-line-name-buffer (buffer &rest _buffers) "Create name for tab with padding and truncation. If buffer name is shorter than `tab-line-tab-max-width' it gets centered with spaces, otherwise it is truncated, to preserve equal width for all tabs. This function also tries to fit as many tabs in window as possible, so if there are no room for tabs with maximum width, it calculates new width for each tab and truncates text if needed. Minimal width can be set with `tab-line-tab-min-width' variable." (with-current-buffer buffer (let* ((window-width (window-width (get-buffer-window))) (tab-amount (length (tab-line-tabs-window-buffers))) (window-max-tab-width (if (>= (* (+ tab-line-tab-max-width 3) tab-amount) window-width) (/ window-width tab-amount) tab-line-tab-max-width)) (tab-width (- (cond ((> window-max-tab-width tab-line-tab-max-width) tab-line-tab-max-width) ((< window-max-tab-width tab-line-tab-min-width) tab-line-tab-min-width) (t window-max-tab-width)) 3)) ;; compensation for ' x ' button (buffer-name (string-trim (buffer-name))) (name-width (length buffer-name))) (if (>= name-width tab-width) (concat " " (truncate-string-to-width buffer-name (- tab-width 2)) "…") (let* ((padding (make-string (+ (/ (- tab-width name-width) 2) 1) ?\s)) (buffer-name (concat padding buffer-name))) (concat buffer-name (make-string (- tab-width (length buffer-name)) ?\s))))))) (defun tab-line-close-tab (&optional e) "Close the selected tab. If tab is presented in another window, close the tab by using `bury-buffer` function. If tab is unique to all existing windows, kill the buffer with `kill-buffer` function. Lastly, if no tabs left in the window, it is deleted with `delete-window` function." (interactive "e") (let* ((posnp (event-start e)) (window (posn-window posnp)) (buffer (get-pos-property 1 'tab (car (posn-string posnp))))) (with-selected-window window (let ((tab-list (tab-line-tabs-window-buffers)) (buffer-list (flatten-list (seq-reduce (lambda (list window) (select-window window t) (cons (tab-line-tabs-window-buffers) list)) (window-list) nil)))) (select-window window) (if (> (seq-count (lambda (b) (eq b buffer)) buffer-list) 1) (progn (if (eq buffer (current-buffer)) (bury-buffer) (set-window-prev-buffers window (assq-delete-all buffer (window-prev-buffers))) (set-window-next-buffers window (delq buffer (window-next-buffers)))) (unless (cdr tab-list) (ignore-errors (delete-window window)))) (and (kill-buffer buffer) (unless (cdr tab-list) (ignore-errors (delete-window window))))))))) (unless (version< emacs-version "27") (use-package tab-line :ensure nil :hook (after-init . global-tab-line-mode) :config (defcustom tab-line-tab-min-width 10 "Minimum width of a tab in characters." :type 'integer :group 'tab-line) (defcustom tab-line-tab-max-width 30 "Maximum width of a tab in characters." :type 'integer :group 'tab-line) (setq tab-line-close-button-show t tab-line-new-button-show nil tab-line-separator "" tab-line-tab-name-function #'my/tab-line-name-buffer tab-line-right-button (propertize (if (char-displayable-p ?▶) " ▶ " " > ") 'keymap tab-line-right-map 'mouse-face 'tab-line-highlight 'help-echo "Click to scroll right") tab-line-left-button (propertize (if (char-displayable-p ?◀) " ◀ " " < ") 'keymap tab-line-left-map 'mouse-face 'tab-line-highlight 'help-echo "Click to scroll left") tab-line-close-button (propertize (if (char-displayable-p ?×) " × " " x ") 'keymap tab-line-tab-close-map 'mouse-face 'tab-line-close-highlight 'help-echo "Click to close tab")) (my/set-tab-theme) ;;(dolist (mode '(ediff-mode process-menu-mode term-mode vterm-mode)) ;;(add-to-list 'tab-line-exclude-modes mode)) (dolist (mode '(ediff-mode process-menu-mode)) (add-to-list 'tab-line-exclude-modes mode)) )) (defun my-tab-config (&optional frame) "if frame is a terminal, disable tab-line-mode" (when (not (display-graphic-p frame)) (tab-line-mode nil))) (global-tab-line-mode t) (add-hook 'after-make-frame-functions 'my-tab-config) #+END_SRC * Projectile #+BEGIN_SRC emacs-lisp (use-package projectile :bind ("C-c p" . 'projectile-command-map) :init (projectile-mode +1) (setq projectile-enable-caching t) :ensure t) #+END_SRC * Swiper, Ivy #+BEGIN_SRC emacs-lisp (use-package counsel :ensure t :bind ("C-s" . 'swiper-isearch) ("M-x" . 'counsel-M-x) :init (setq ivy-use-virtual-buffers t) (setq enable-recursive-minibuffers t) (ivy-mode 1)) #+END_SRC * Neotree #+BEGIN_SRC emacs-lisp (use-package neotree :ensure t :bind ("C-c j" . 'neotree-toggle) :init ;; slow rendering (setq inhibit-compacting-font-caches t) ;; set icons theme (setq neo-theme (if (display-graphic-p) 'icons 'arrow)) ;; Every time when the neotree window is opened, let it find current file and jump to node (setq neo-smart-open t) ;; When running ‘projectile-switch-project’ (C-c p p), ‘neotree’ will change root automatically (setq projectile-switch-project-action 'neotree-projectile-action) (setq neo-window-width 35) ;; show hidden files (setq-default neo-show-hidden-files t)) #+END_SRC * Custom Mode Bindings ** SystemD unit files #+BEGIN_SRC emacs-lisp ;; Base systemd unit files (add-to-list 'auto-mode-alist '("\\.service\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.timer\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.mount\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.automount\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.target\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.path\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.slice\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.socket\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.device\\'" . conf-unix-mode)) ;; systemd-networkd (add-to-list 'auto-mode-alist '("\\.network\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.link\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.netdev\\'" . conf-unix-mode)) #+END_SRC ** elkowar's wacky widgets #+BEGIN_SRC emacs-lisp (add-to-list 'auto-mode-alist '("\\.yuck\\'" . conf-unix-mode)) #+END_SRC ** Webdev #+BEGIN_SRC emacs-lisp (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode)) #+END_SRC * Markdown mode ** Auto Text Wrap #+BEGIN_SRC emacs-lisp (add-hook 'markdown-mode-hook (lambda () (setq fill-column 85) (visual-fill-column-mode) (visual-line-mode) (display-fill-column-indicator-mode))) #+END_SRC * Org mode ** General #+BEGIN_SRC emacs-lisp (setq org-startup-indented t) #+END_SRC ** Auto Text Wrap #+BEGIN_SRC emacs-lisp (add-hook 'org-mode-hook (lambda () (setq fill-column 85) (visual-fill-column-mode) (visual-line-mode))) #+END_SRC ** Babel *** Elixir #+BEGIN_SRC emacs-lisp (use-package ob-elixir :ensure t) #+END_SRC *** Load Languages #+BEGIN_SRC emacs-lisp (org-babel-do-load-languages 'org-babel-load-languages '((lisp . t) (elixir . t) (emacs-lisp . t) (python . t))) #+END_SRC ** org-bullets #+BEGIN_SRC emacs-lisp (use-package org-bullets :ensure t :init (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))) #+END_SRC ** org-appear #+BEGIN_SRC emacs-lisp (use-package org-appear :ensure t :init (add-hook 'org-mode-hook 'org-appear-mode)) #+END_SRC ** Presentations #+BEGIN_SRC emacs-lisp (use-package org-present :ensure t :straight '(org-present :type git :host github :repo "rlister/org-present")) #+END_SRC * Development ** Copilot #+BEGIN_SRC emacs-lisp ;; Load copilot (add-to-list 'load-path "/home/ezri/.emacs.d/copilot.el") (require 'copilot) ;; Enable completion (add-hook 'prog-mode-hook 'copilot-mode) #+END_SRC ** Tree-Sitter #+BEGIN_SRC emacs-lisp (setq treesit-language-source-alist '((bash "https://github.com/tree-sitter/tree-sitter-bash") (cmake "https://github.com/uyha/tree-sitter-cmake") (css "https://github.com/tree-sitter/tree-sitter-css") (elisp "https://github.com/Wilfred/tree-sitter-elisp") (go "https://github.com/tree-sitter/tree-sitter-go") (html "https://github.com/tree-sitter/tree-sitter-html") (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src") (json "https://github.com/tree-sitter/tree-sitter-json") (make "https://github.com/alemuller/tree-sitter-make") (markdown "https://github.com/ikatyang/tree-sitter-markdown") (python "https://github.com/tree-sitter/tree-sitter-python") (toml "https://github.com/tree-sitter/tree-sitter-toml") (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src") (yaml "https://github.com/ikatyang/tree-sitter-yaml"))) #+END_SRC ** Git #+BEGIN_SRC emacs-lisp (use-package magit :ensure t) #+END_SRC ** Autocomplete #+BEGIN_SRC emacs-lisp (use-package auto-complete :ensure t) (ac-config-default) (defun my-tab () (interactive) (or (copilot-accept-completion) (ac-expand nil))) (with-eval-after-load 'auto-complete ; diable inline preview (setq ac-disable-inline t) ; show menu if have only one candidate (setq ac-candidate-menu-min 0)) (define-key copilot-completion-map (kbd "") 'copilot-accept-completion) (define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion) #+END_SRC ** Company mode #+BEGIN_SRC emacs-lisp (use-package company :ensure t :init (global-company-mode t) :bind (:map company-active-map ("C-n" . company-select-next) ("C-p" . company-select-previous)) :config (setq company-idle-delay 0.3)) #+END_SRC ** LSP #+BEGIN_SRC emacs-lisp (use-package eglot :ensure t :defer t :bind (:map eglot-mode-map ("C-c C-e" . eglot-rename) ("C-." . eglot-code-actions)) :hook ((python-mode . eglot-ensure) (python-mode . flyspell-prog-mode) (python-mode . superword-mode) (python-mode . hs-minor-mode)) :config (setq-default eglot-workspace-configuration '((:pylsp . (:configurationSources ["flake8"] :plugins ( :mccabe (:enabled :json-false) :pyflakes (:enabled :json-false) :flake8 (:enabled :json-false :maxLineLength 88) :ruff (:enabled t :lineLength 88) :pydocstyle (:enabled t :convention "numpy") :yapf (:enabled :json-false) :autopep8 (:enabled :json-false) :black (:enabled t :line_length 88 :cache_config t))))))) #+END_SRC ** Languages *** Elixir #+BEGIN_SRC emacs-lisp (use-package elixir-mode :ensure t :hook ((before-save . (lambda () (when (eq major-mode 'elixir-mode) (elixir-format)))))) #+END_SRC *** Rust After installing the ~rust-analyzer~ program, the following can be used: #+BEGIN_SRC emacs-lisp (use-package rust-mode :ensure t) (setq lsp-rust-server 'rust-analyzer) #+END_SRC *** Vue #+BEGIN_SRC emacs-lisp (add-hook 'mmm-mode-hook (lambda () (set-face-background 'mmm-default-submode-face nil))) #+END_SRC *** Web Stuff **** Typescript #+BEGIN_SRC emacs-lisp ;; TODO: Update to tree-sitter in Emacs 29 (setq major-mode-remap-alist '((typescript-mode . typescript-ts-mode) (python-mode . python-ts-mode) (js2-mode . js-ts-mode) (json-mode . json-ts-mode))) (add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode)) ;; (add-hook 'tsx-ts-mode-hook #'eglot) ;; (add-hook 'tsx-ts-mode-hook #'setup-tide-mode) ;; (add-hook 'typescript-ts-mode-hook #'eglot) ;; (add-hook 'typescript-ts-mode-hook #'setup-tide-mode) #+END_SRC **** TIDE #+BEGIN_SRC emacs-lisp (defun setup-tide-mode () (interactive) (tide-setup) (flycheck-mode +1) (setq flycheck-check-syntax-automatically '(save mode-enabled)) (eldoc-mode +1) (tide-hl-identifier-mode +1) ;; company is an optional dependency. You have to ;; install it separately via package-install ;; `M-x package-install [ret] company` (company-mode +1)) (use-package tide :ensure t :after (typescript-mode company flycheck) :hook ((typescript-mode . setup-tide-mode) ;; TODO: Update to tree-sitter in Emacs 29 (js2-mode . setup-tide-mode))) #+END_SRC **** Web Mode #+BEGIN_SRC emacs-lisp ;; web-mode (setq web-mode-markup-indent-offset 2) (setq web-mode-code-indent-offset 2) (setq web-mode-css-indent-offset 2) (use-package web-mode :ensure t :mode (("\\.scss\\'" . web-mode) ("\\.css\\'" . web-mode) ("\\.jsx\\'" . web-mode) ("\\.html\\'" . web-mode)) :commands web-mode) #+END_SRC **** Prettier #+BEGIN_SRC emacs-lisp (use-package prettier-js :ensure t) (add-hook 'js2-mode-hook 'prettier-js-mode) (add-hook 'typescript-mode 'prettier-js-mode) (add-hook 'web-mode-hook 'prettier-js-mode) #+END_SRC **** Prisma #+BEGIN_SRC emacs-lisp (use-package prisma-mode :ensure t :straight '(prisma-mode :type git :host github :repo "pimeys/emacs-prisma-mode")) #+END_SRC **** Svelte #+BEGIN_SRC emacs-lisp (use-package svelte-mode :ensure t :straight '(svelte-mode :type git :host github :repo "leafOfTree/svelte-mode")) #+END_SRC *** Kotlin #+BEGIN_SRC emacs-lisp (use-package kotlin-mode :ensure t) #+END_SRC *** Java #+BEGIN_SRC emacs-lisp (use-package lsp-java :config (add-hook 'java-mode-hook 'lsp) :ensure t) #+END_SRC #+RESULTS: : t *** PHP #+BEGIN_SRC emacs-lisp (use-package php-mode :ensure t) #+END_SRC #+RESULTS: * Format All The Buffers #+BEGIN_SRC emacs-lisp (use-package format-all :ensure t) (add-hook 'prog-mode-hook 'format-all-mode) (add-hook 'format-all-mode-hook 'format-all-ensure-formatter) #+END_SRC #+RESULTS: | format-all-ensure-formatter | * Multiple Cursors #+BEGIN_SRC emacs-lisp (use-package multiple-cursors :straight t :ensure t :bind (("H-SPC" . set-rectangular-region-anchor) ("C-M-SPC" . set-rectangular-region-anchor) ("C->" . mc/mark-next-like-this) ("C-<" . mc/mark-previous-like-this) ("C-c C->" . mc/mark-all-like-this) ("C-c C-SPC" . mc/edit-lines) )) #+END_SRC * Obsidian #+BEGIN_SRC emacs-lisp ;; (use-package obsidian ;; :ensure t ;; :demand t ;; :config ;; (obsidian-specify-path "~/PersonalDocuments/Personal/TTRPG Vault") ;; (global-obsidian-mode t) ;; :custom ;; :bind (:map obsidian-mode-map ;; ("C-c C-o" . obsidian-follow-link-at-point) ;; ("C-c C-b" . obsidian-backlink-jump) ;; ("C-c C-l" . obsidian-insert-wikilink))) #+END_SRC * TRAMP Customization #+BEGIN_SRC emacs-lisp (add-hook 'after-init-hook 'tramp-nspawn-setup) #+END_SRC