diff options
| author | coast <coasteen@proton.me> | 2026-10-13 05:03:11 +0330 |
|---|---|---|
| committer | coast <coasteen@proton.me> | 2026-10-13 05:03:11 +0330 |
| commit | 8c5c2d270fd0f3bbc276e3b1cc28fc1dfae3fa59 (patch) | |
| tree | a18e4d6016c4df3ca97e017b9f9d351398e950da /emacs | |
| download | coast-newdot-8c5c2d270fd0f3bbc276e3b1cc28fc1dfae3fa59.tar.gz coast-newdot-8c5c2d270fd0f3bbc276e3b1cc28fc1dfae3fa59.tar.bz2 coast-newdot-8c5c2d270fd0f3bbc276e3b1cc28fc1dfae3fa59.tar.xz coast-newdot-8c5c2d270fd0f3bbc276e3b1cc28fc1dfae3fa59.tar.zst | |
init
Diffstat (limited to 'emacs')
| -rw-r--r-- | emacs/init.el | 317 | ||||
| -rw-r--r-- | emacs/user-lisp/modeline.el | 140 |
2 files changed, 457 insertions, 0 deletions
diff --git a/emacs/init.el b/emacs/init.el new file mode 100644 index 0000000..9e26acd --- /dev/null +++ b/emacs/init.el @@ -0,0 +1,317 @@ +;; -*- lexical-binding: t; -*- + +(require 'package) +(setq package-check-signature nil + package-archives '(("gnu" . "https://elpa.gnu.org/packages/") + ("nongnu" . "https://elpa.nongnu.org/packages/") + ("melpa" . "https://melpa.org/packages/"))) +(package-initialize) +(unless package-archive-contents + (package-refresh-contents)) + +(require 'use-package) +(require 'seq) +(require 'treesit) + +(setq use-package-always-ensure t + inhibit-startup-screen t + initial-scratch-message nil + initial-buffer-choice nil + ring-bell-function #'ignore + use-short-answers t + create-lockfiles nil + make-backup-files nil + auto-save-default nil + select-enable-clipboard t + select-enable-primary nil + save-interprogram-paste-before-kill nil + confirm-nonexistent-file-or-buffer nil + switch-to-buffer-obey-display-actions t + custom-file (expand-file-name "custom.el" user-emacs-directory) + display-line-numbers-type 'relative + mouse-wheel-scroll-amount '(3 ((shift) . 1)) + mouse-wheel-progressive-speed nil + mouse-wheel-scroll-amount-horizontal '(3 . 1) + pixel-scroll-precision-mode nil + split-height-threshold nil + split-width-threshold nil) + +(setq initial-major-mode 'text-mode) +(setq initial-buffer-choice t) + +(setq-default indent-tabs-mode nil + tab-width 4) + +(menu-bar-mode -1) + +(when (file-exists-p custom-file) + (load custom-file)) + +(global-display-line-numbers-mode 1) +(column-number-mode 1) +(electric-pair-mode 1) +(show-paren-mode 1) +(save-place-mode 1) +(recentf-mode 1) +(savehist-mode 1) +(xterm-mouse-mode 1) + +(use-package vertico + :init + (vertico-mode 1)) + +(use-package marginalia + :init + (marginalia-mode 1)) + +(use-package which-key + :init + (which-key-mode 1)) + +(use-package orderless + :custom + (completion-styles '(orderless basic))) + +(use-package consult + :bind (("C-x b" . consult-buffer) + ("M-s r" . consult-ripgrep) + ("M-s l" . consult-line))) + +(use-package corfu + :custom + (corfu-auto t) + (corfu-auto-prefix 2) + :init + (global-corfu-mode 1)) + +(use-package evil + :init + (setq evil-want-keybinding nil + evil-want-C-u-scroll t + evil-want-Y-yank-to-eol t + evil-undo-system 'undo-redo + evil-shift-width 4 + evil-visual-x-select-clipboard nil) + :config + (evil-mode 1) + (setq evil-echo-state nil)) + +(use-package evil-collection + :after evil + :config + (evil-collection-init)) + +(use-package evil-surround + :after evil + :config + (global-evil-surround-mode 1)) + +(use-package evil-commentary + :after evil + :config + (evil-commentary-mode 1)) + +(make-directory "~/notes/" t) + +(use-package vterm) + +(use-package elcord + :config + (elcord-mode 1)) + +(use-package org + :ensure nil + :custom + (org-directory "~/notes/") + (org-agenda-files '("~/notes/")) + (org-default-notes-file "~/notes/inbox.org") + (org-startup-indented t) + (org-log-done 'time) + (org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "WAIT(w)" "|" "DONE(d)" "CANC(c)"))) + (org-capture-templates + '(("t" "Todo" entry + (file+headline "~/notes/inbox.org" "Tasks") + "* TODO %?\n %U\n") + ("i" "Idea" entry + (file+headline "~/notes/inbox.org" "Ideas") + "* %?\n %U\n"))) + :config + (require 'org-tempo) + (add-hook 'org-mode-hook #'visual-line-mode)) + +(use-package evil-org + :after (evil org) + :hook (org-mode . evil-org-mode) + :config + (require 'evil-org-agenda) + (evil-org-agenda-set-keys)) + +(use-package denote + :custom + (denote-directory "~/notes/") + (denote-file-type 'org)) + +(use-package consult-denote + :after (consult denote) + :config + (consult-denote-mode 1)) + +(use-package eglot + :ensure nil + :hook ((c-mode . eglot-ensure) + (c++-mode . eglot-ensure) + (rust-mode . eglot-ensure) + (go-mode . eglot-ensure) + (zig-mode . eglot-ensure)) + :config + (add-to-list + 'eglot-server-programs + '((c-mode c++-mode) . ("clangd" "--background-index" "--header-insertion=never"))) + (add-to-list 'eglot-server-programs '(zig-mode . ("zls")))) + +(use-package flymake + :ensure nil + :hook (prog-mode . flymake-mode)) + +(use-package rust-mode + :mode "\\.rs\\'") + +(use-package go-mode + :mode "\\.go\\'") + +(use-package zig-mode + :mode "\\.zig\\'") + +(require 'warnings) +(add-to-list 'warning-suppress-types '(bytecomp)) + +(defvar coast-treesit-language-sources + '((bash . ("https://github.com/tree-sitter/tree-sitter-bash" "src")) + (c . ("https://github.com/tree-sitter/tree-sitter-c" "src")) + (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp" "src")) + (css . ("https://github.com/tree-sitter/tree-sitter-css" "src")) + (go . ("https://github.com/tree-sitter/tree-sitter-go" "src")) + (haskell . ("https://github.com/tree-sitter/tree-sitter-haskell" "src")) + (html . ("https://github.com/tree-sitter/tree-sitter-html" "src")) + (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "src")) + (json . ("https://github.com/tree-sitter/tree-sitter-json" "src")) + (lua . ("https://github.com/tree-sitter-grammars/tree-sitter-lua" "src")) + (make . ("https://github.com/tree-sitter-grammars/tree-sitter-make" "src")) + (markdown . ("https://github.com/tree-sitter/tree-sitter-markdown" "src")) + (python . ("https://github.com/tree-sitter/tree-sitter-python" "src")) + (rust . ("https://github.com/tree-sitter/tree-sitter-rust" "src")) + (toml . ("https://github.com/tree-sitter/tree-sitter-toml" "src")) + (tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "tsx/src")) + (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "typescript/src")) + (yaml . ("https://github.com/tree-sitter-grammars/tree-sitter-yaml" "src")))) + +(defun coast-treesit-install (language) + (let* ((source (alist-get language coast-treesit-language-sources)) + (url (car source)) + (subdir (cadr source))) + (when source + (add-to-list + 'treesit-language-source-alist + (if subdir + (list language url nil subdir) + (list language url))) + (treesit-install-language-grammar language)))) + +(defun my/make-terminal-transparent (&optional frame) + (unless (display-graphic-p frame) + (let ((target-frame (or frame (selected-frame))) + (faces '(default line-number line-number-current-line fringe + window-divider vertical-border hl-line))) + (dolist (face faces) + (when (facep face) + (set-face-background face "unspecified-bg" target-frame))) + (set-terminal-parameter (frame-terminal target-frame) + 'background-mode 'dark)))) + +(add-hook 'window-setup-hook #'my/make-terminal-transparent) +(add-hook 'after-make-frame-functions #'my/make-terminal-transparent) +(advice-add 'load-theme :after + (lambda (&rest _) (my/make-terminal-transparent))) + +(use-package doom-themes) + +(defun coast/remove-scratch-buffer () + (let ((buffer (get-buffer "*scratch*"))) + (when (and buffer + (not (buffer-modified-p buffer)) + (not (get-buffer-window buffer t))) + (kill-buffer buffer)))) + +(add-hook 'after-init-hook #'coast/remove-scratch-buffer) + +(defun coast-treesit-install-missing () + (dolist (language (mapcar #'car coast-treesit-language-sources)) + (unless (treesit-language-available-p language) + (condition-case nil + (coast-treesit-install language) + (error nil))))) + +(add-hook 'after-init-hook #'coast-treesit-install-missing) + +(add-hook 'emacs-startup-hook + (lambda () + (delete-other-windows))) + +(add-to-list 'load-path "/home/coast/.emacs.d/user-lisp") +(require 'modeline) + +(use-package treemacs + :ensure t + :defer t + :config + (setq treemacs-collapse-dirs (if treemacs-python-executable 3 0) + treemacs-deferred-git-apply-delay 0.5 + treemacs-directory-name-transformer #'identity + treemacs-display-in-side-window t + treemacs-eldoc-display 'simple + treemacs-file-event-delay 5000 + treemacs-file-follow-delay 0.2 + treemacs-follow-after-init t + treemacs-expand-after-init t + treemacs-indentation 2 + treemacs-indentation-string " " + treemacs-is-other-window nil + treemacs-max-git-entries 5000 + treemacs-no-png-images nil + treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory) + treemacs-recenter-distance 0.1 + treemacs-file-watch-mode t + treemacs-fringe-indicator-mode 'always + treemacs-hide-gitignored-files-mode nil + treemacs-width 30) + + (treemacs-resize-icons 11) + (treemacs-follow-mode t) + (treemacs-project-follow-mode t) + (treemacs-filewatch-mode t) + (treemacs-hide-gitignored-files-mode -1)) + +(use-package treemacs-evil + :after (treemacs evil) + :ensure t) + +(use-package treemacs-icons-dired + :hook (dired-mode . treemacs-icons-dired-mode) + :ensure t) + +(use-package treemacs-magit + :after (treemacs magit) + :ensure t) + +(defun my/treemacs-open-current-dir () + "Toggle Treemacs open to current directory/project." + (interactive) + (require 'treemacs) + (let ((state (treemacs-current-visibility))) + (if (eq state 'visible) + (treemacs) + (treemacs-add-and-display-current-project-exclusively)))) + +(with-eval-after-load 'evil + (evil-define-key 'normal 'global (kbd "SPC e") #'my/treemacs-open-current-dir)) diff --git a/emacs/user-lisp/modeline.el b/emacs/user-lisp/modeline.el new file mode 100644 index 0000000..627584c --- /dev/null +++ b/emacs/user-lisp/modeline.el @@ -0,0 +1,140 @@ +;; -*- lexical-binding: t; -*- + +(require 'cl-lib) +(require 'subr-x) + +(defvar my/ml-icons t + "Non-nil uses Nerd Font glyphs, nil falls back to ASCII.") + +;; Transparent background, white text +(set-face-attribute 'mode-line nil + :background "unspecified-bg" :foreground "white" + :box nil :inverse-video nil :underline nil :overline nil) +(set-face-attribute 'mode-line-inactive nil + :background "unspecified-bg" :foreground "brightblack" + :box nil :inverse-video nil :underline nil :overline nil) + +;;;; git diff counts (+added ~modified -removed), refreshed on open and save +(defvar-local my/ml-diff-stat nil) + +(defun my/ml-diff-update () + (setq my/ml-diff-stat nil) + (when (and buffer-file-name + (not (file-remote-p buffer-file-name)) + (eq (vc-backend buffer-file-name) 'Git)) + (let ((file buffer-file-name) + (default-directory (file-name-directory buffer-file-name)) + (a 0) (m 0) (r 0)) + (with-temp-buffer + (when (eq 0 (process-file "git" nil t nil "diff" "-U0" "--no-color" + "--no-ext-diff" "--" file)) + (goto-char (point-min)) + (while (re-search-forward + "^@@ -[0-9]+\\(?:,\\([0-9]+\\)\\)? \\+[0-9]+\\(?:,\\([0-9]+\\)\\)? @@" + nil t) + (let ((o (if (match-string 1) (string-to-number (match-string 1)) 1)) + (n (if (match-string 2) (string-to-number (match-string 2)) 1))) + (cond ((= o 0) (cl-incf a n)) + ((= n 0) (cl-incf r o)) + (t (cl-incf m (min o n)) + (cl-incf a (max 0 (- n o))) + (cl-incf r (max 0 (- o n))))))))) + (setq my/ml-diff-stat (list a m r))))) + +(add-hook 'find-file-hook #'my/ml-diff-update) +(add-hook 'after-save-hook #'my/ml-diff-update) +(add-hook 'after-revert-hook #'my/ml-diff-update) + +;;;; components +(defun my/ml-state () + (if (bound-and-true-p evil-local-mode) evil-state 'emacs)) + +(defun my/ml-block (text) + (propertize text 'face '(:foreground "black" :background "white" :weight bold))) + +(defun my/ml-mode () + (my/ml-block + (format " %s " + (pcase (my/ml-state) + ('normal "NORMAL") + ('insert "INSERT") + ('visual (pcase (bound-and-true-p evil-visual-selection) + ('line "V-LINE") ('block "V-BLOCK") (_ "VISUAL"))) + ('replace "REPLACE") + ('operator "O-PENDING") + ('motion "MOTION") + (_ "EMACS"))))) + +(defun my/ml-branch () + (when (and vc-mode (stringp vc-mode)) + (concat (if my/ml-icons "\ue0a0 " "") + (replace-regexp-in-string "\\`[ ]*[A-Za-z]+[-:@!?]" "" vc-mode)))) + +(defun my/ml-diff () + (when my/ml-diff-stat + (pcase-let ((`(,a ,m ,r) my/ml-diff-stat)) + (let ((parts (delq nil (list (and (> a 0) (format "+%d" a)) + (and (> m 0) (format "~%d" m)) + (and (> r 0) (format "-%d" r)))))) + (when parts (string-join parts " ")))))) + +(defun my/ml-diag () + (when (bound-and-true-p flymake-mode) + (let ((e 0) (w 0) (i 0)) + (dolist (d (flymake-diagnostics)) + (let ((ty (flymake-diagnostic-type d))) + (cond ((memq ty '(:error eglot-error)) (cl-incf e)) + ((memq ty '(:warning eglot-warning)) (cl-incf w)) + ((memq ty '(:note eglot-note)) (cl-incf i))))) + (let ((parts (delq nil + (list (and (> e 0) (format "%s%d" (if my/ml-icons "\U000F015A " "E:") e)) + (and (> w 0) (format "%s%d" (if my/ml-icons "\U000F002A " "W:") w)) + (and (> i 0) (format "%s%d" (if my/ml-icons "\U000F02FD " "I:") i)))))) + (when parts (string-join parts " ")))))) + +(defun my/ml-file () + (concat (buffer-name) + (cond (buffer-read-only " [-]") + ((buffer-modified-p) " [+]") + (t "")))) + +(defun my/ml-encoding () + (replace-regexp-in-string "-\\(unix\\|dos\\|mac\\)\\'" "" + (symbol-name (or buffer-file-coding-system 'utf-8)))) + +(defun my/ml-eol () + (pcase (coding-system-eol-type (or buffer-file-coding-system 'utf-8-unix)) + (1 (if my/ml-icons "\ue70f" "dos")) + (2 (if my/ml-icons "\uf179" "mac")) + (_ (if my/ml-icons "\uf17c" "unix")))) + +(defun my/ml-filetype () + (string-remove-suffix "-mode" (symbol-name major-mode))) + +(defun my/ml-loc (block) + (let ((s (format " %s:%-2d " (format-mode-line "%3l") (1+ (current-column))))) + (if block (my/ml-block s) s))) + +(defun my/ml-section (items) + (let ((items (cl-remove-if (lambda (s) (or (null s) (string-empty-p s))) items))) + (if items (concat " " (string-join items " | ") " ") ""))) + +;;;; assembly +(defun my/ml-format () + (let* ((active (mode-line-window-selected-p)) + (left (if active + (concat (my/ml-mode) + (my/ml-section (list (my/ml-branch) (my/ml-diff) (my/ml-diag))) + (my/ml-section (list (my/ml-file)))) + (my/ml-section (list (my/ml-file))))) + (right (if active + (concat (my/ml-section (list (my/ml-encoding) (my/ml-eol) (my/ml-filetype))) + (my/ml-loc t)) + (my/ml-loc nil))) + (fill (propertize " " 'display + `((space :align-to (- right ,(string-width right))))))) + (concat left fill right))) + +(setq-default mode-line-format '((:eval (my/ml-format)))) + +(provide 'modeline) |
