commit 3f8a09c845b33334e16b1c2a36780a56356ddaa4 Author: cspark Date: Thu Feb 5 00:34:05 2026 +0000 Init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8f18a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +tramp-autosave/ +tramp +history +ido.last +recentf +eln-cache/ +tree-sitter/ +tutorial/ +auto-save-list/ +transient/ +straight/ +eshell/history +eshell/lastdir + +agenda.org +bookmarks +projectile-bookmarks.eld \ No newline at end of file diff --git a/README.org b/README.org new file mode 100644 index 0000000..9b430f1 --- /dev/null +++ b/README.org @@ -0,0 +1,6 @@ +* Modernised GNU Emacs Configuration + +This is a modernised GNU Emacs Configuration, an evolution of my old emacs configuration: +`https://git.cspark.dev/cspark/Emacs-Configuration` + +It is intended to be more focused and clean, using modern more modular/simpler packages or the builtins. diff --git a/early-init.el b/early-init.el new file mode 100644 index 0000000..1d6ba05 --- /dev/null +++ b/early-init.el @@ -0,0 +1,2 @@ +;; For straight.el +(setq package-enable-at-startup nil) diff --git a/eshell/alias b/eshell/alias new file mode 100644 index 0000000..9e8bb27 --- /dev/null +++ b/eshell/alias @@ -0,0 +1,2 @@ +alias cd z $1 +alias ssh cd /ssh:$1: diff --git a/init.el b/init.el new file mode 100644 index 0000000..ffe8481 --- /dev/null +++ b/init.el @@ -0,0 +1,476 @@ +(menu-bar-mode 0) +(tool-bar-mode 0) +(scroll-bar-mode 0) +(column-number-mode 1) + +;; Set custom tab width here +(setq custom-tab-width 8) + +;; Temporary file config +(setq backup-directory-alist + `((".*" . ,temporary-file-directory))) +(setq auto-save-file-name-transforms + `((".*" ,temporary-file-directory t))) + +;; Fixes to stop weird window geometry issues +(setq frame-inhibit-implied-resize t) +(setq frame-resize-pixelwise t) + +;; Ensure that tabs are default over spaces +(setq-default tab-width custom-tab-width) +(setq tab-width custom-tab-width) +(setq-default indent-tabs-mode 't) +(setq indent-tabs-mode 't) +(advice-add 'indent-to :around + (lambda (orig-fun column &rest args) + (when (eq indent-tabs-mode 'only) + (setq column (* tab-width (round column tab-width)))) + (apply orig-fun column args))) +(defvaralias 'c-basic-offset 'tab-width) +(electric-indent-mode 0) + +;; Clipboard config +(setopt select-active-regions nil) +(setopt select-enable-clipboard 't) +(setopt select-enable-primary nil) +(setopt interprogram-cut-function #'gui-select-text) + +;; Midnight Mode +; Automatically clean up old unused buffers +(midnight-mode 1) + +;; Emacs client configuration +(set-frame-font "SFMono Nerd Font 20") +(setq default-frame-alist '((font . "SFMono Nerd Font 20"))) +(defun client-config () + (scroll-bar-mode 0) +) +(add-hook 'after-make-frame-functions #'(lambda (frame) + (select-frame frame) + (client-config))) + +;; Ensure TAB key ACTUALLY works like a TAB key +(defun my/complete-or-tab () + "Complete at point or insert a tab if no characters before point." + (interactive) + (if (and (char-before) (not (member (char-before) '(?\s ?\t ?\n)))) ; Check for whitespace, tabs or newline + (completion-at-point) ; If yes, do completion at point + (insert-tab))) ; If no, insert a tab character +(global-set-key (kbd "TAB") 'my/complete-or-tab) +(define-key global-map [remap backward-delete-char-untabify] 'backward-delete-char) + +;; Track recently opened files +(recentf-mode 1) + +;; Ido Config +(setq ido-everywhere 1) +(setq ido-use-virtual-buffers t) +(setq ido-enable-flex-matching t) +;;(ido-mode 1) +; Custom ido keybindings +(add-hook 'ido-setup-hook + '(lambda () + (define-key ido-completion-map (kbd "") 'ido-prev-match) + (define-key ido-completion-map (kbd "") 'ido-next-match) + + (define-key ido-completion-map (kbd "C-p") 'ido-prev-match) + (define-key ido-completion-map (kbd "C-n") 'ido-next-match) + + (define-key ido-completion-map (kbd "C-k") 'ido-prev-match) + (define-key ido-completion-map (kbd "C-j") 'ido-next-match) +)) + +;; Ido Occur - OG Swiper +;(load (expand-file-name (concat user-emacs-directory "plugins/ido-occur.el"))) +;(define-key global-map [remap isearch-forward] 'ido-occur) + +;; Stop weird C-9 keybindings causing conflicts on typo +(define-key global-map [remap digit-argument] "") + +;; Package management setup +(require 'package) +(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) +; Comment/uncomment this line to enable MELPA Stable if desired. See `package-archive-priorities` +; and `package-pinned-packages`. Most users will not need or want to do this. +;(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t) +(package-initialize) +;; Straight.el +(defvar bootstrap-version) +(let + ((bootstrap-file + (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) + (bootstrap-version 5)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) +(setq straight-use-package-by-default t) + +;; Optimisation +; GCMH +;Enforce a sneaky Garbage Collection strategy to minimize GC interference with user activity. +;During normal use a high GC threshold is set. +;When idling GC is triggered and a low threshold is set. +;This greatly improves performance/startup time of emacs. +(use-package gcmh + :ensure t + :init + (gcmh-mode 1) + + ;; Ensure garbage collector does not run TOO frequently which causes random freezes + (defun gcmh-mode-optimisation-setup-hook () + (setq gc-cons-threshold most-positive-fixnum)) + + (defun gcmh-mode-optimisation-exit-hook () + (setq gc-cons-threshold 800000)) + + (add-hook 'minibuffer-setup-hook 'gcmh-mode-optimisation-setup-hook) + (add-hook 'minibuffer-exit-hook 'gcmh-mode-optimisation-exit-hook) +) +; Fontification +(jit-lock-mode 1) +(setq jit-lock-stealth-time 1.25) +(setq jit-lock-stealth-nice 0.5) ;; Seconds between font locking. +(setq jit-lock-chunk-size 4096) + +(setq jit-lock-defer-time 0) +(with-eval-after-load 'evil + (add-hook 'evil-insert-state-entry-hook + (lambda () + (setq jit-lock-defer-time 0.25)) nil t) + (add-hook 'evil-insert-state-exit-hook + (lambda () + (setq jit-lock-defer-time 0)) nil t)) + +;; Emacs minibuffer configurations. +(use-package emacs + :ensure t + :custom + (tab-always-indent 'complete) + + ;; Enable context menu. `vertico-multiform-mode' adds a menu in the minibuffer + ;; to switch display modes. + (context-menu-mode t) + ;; Support opening new minibuffers from inside existing minibuffers. + (enable-recursive-minibuffers t) + ;; Hide commands in M-x which do not work in the current mode. Vertico + ;; commands are hidden in normal buffers. This setting is useful beyond + ;; Vertico. + (read-extended-command-predicate #'command-completion-default-include-p) + ;; Do not allow the cursor in the minibuffer prompt + (minibuffer-prompt-properties + '(read-only t cursor-intangible t face minibuffer-prompt) + ) +) + +;; Doom Theme +(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-gruvbox-light t) + +;; Autocompletion configuration +;(use-package ido-vertical-mode +; :ensure t +; :config (ido-vertical-mode 1)) + +;; Enable Vertico. +(use-package vertico + :ensure t + ;;:custom + ;; (vertico-scroll-margin 0) ;; Different scroll margin + ;; (vertico-count 20) ;; Show more candidates + ;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer + ;; (vertico-cycle t) ;; Enable cycling for `vertico-next/previous' + :config + (define-key vertico-map (kbd "C-k") 'vertico-previous) + (define-key vertico-map (kbd "C-j") 'vertico-next) + :init + (vertico-mode) +) + +;; Fuzzy matching for completion frameworks like Vertico +(use-package orderless + :ensure t + :custom + (completion-styles '(orderless basic)) + (completion-category-overrides '((file (styles partial-completion)))) + (completion-pcm-leading-wildcard t) ;; Emacs 31: partial-completion behaves like substring +) + +;; Enhanced commands that Vertico can make use of +(use-package consult + :ensure t + :config + (define-key global-map [remap isearch-forward] 'consult-ripgrep) + (define-key global-map [remap switch-to-buffer] 'consult-buffer) +) + +;; Persist history over Emacs restarts. Vertico sorts by history position. +(use-package savehist + :ensure t + :init + (savehist-mode) +) + +;; Corfu Autocomplete in buffer +(use-package corfu + :ensure t + :hook + (prog-mode . corfu-mode) + (html-ts-mode . corfu-mode) + (css-ts-mode . corfu-mode) + ;; (shell-mode . corfu-mode) + ;; (eshell-mode . corfu-mode)) + :config + (setq + auto nil + corfu-preselect 'first + ) + ;;(global-corfu-mode) +) + +;; Evil Config +; Vim Bindings +(use-package evil + :ensure t + :bind (("" . keyboard-escape-quit)) + :init + (evil-mode 1) + :config + (define-key evil-insert-state-map (kbd "C-g") 'evil-force-normal-state) + (define-key evil-motion-state-map [remap evil-search-forward] 'consult-line) +) + +;; Eshell config +;; Like zoxide +(use-package eshell-z + :ensure t + :config + (add-hook 'eshell-mode-hook + (defun my-eshell-mode-hook () + (require 'eshell-z))) +) +;; Bash completion commands in eshell +(use-package bash-completion + :ensure t + :init + (autoload 'bash-completion-dynamic-complete + "bash-completion" + "BASH completion hook") + (add-hook 'shell-dynamic-complete-functions + 'bash-completion-dynamic-complete) + (add-hook 'eshell-mode-hook + (lambda () + (add-hook 'completion-at-point-functions + 'bash-completion-capf-nonexclusive nil t))) +) +;; Eat is a terminal emulator that can integrate nicely with eshell, allows us to run full ncurses applications inside eshell. +(use-package eat + :straight '(eat :type git + :host codeberg + :repo "akib/emacs-eat" + :files ("*.el" ("term" "term/*.el") "*.texi" + "*.ti" ("terminfo/e" "terminfo/e/*") + ("terminfo/65" "terminfo/65/*") + ("integration" "integration/*") + (:exclude ".dir-locals.el" "*-tests.el"))) + :ensure t + :init + ;; For `eat-eshell-mode'. + (add-hook 'eshell-load-hook #'eat-eshell-mode) + + ;; For `eat-eshell-visual-command-mode'. + (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode) +) +;; New create new eshell instance +(defun eshell/new () + (interactive) + (eshell t)) + +;; Sudo edit command to escalate priv if need be +(use-package sudo-edit + :ensure t + :config + (add-hook 'before-save-hook 'sudo-before-save-hook) +) +(setq tramp-auto-save-directory "~/.emacs.d/tramp-autosave") + +;; TRAMP +;TRAMP edit files over SSH configuration + +(use-package tramp + :ensure t + :config + (add-to-list 'tramp-remote-path 'tramp-own-remote-path) + (when (eq window-system 'w32) + (setq tramp-default-method "plink")) +) + +;; Org Mode Config +; Org Latex Preview Scale +; Automatically toggle Org mode LaTeX fragment previews as the cursor enters and exits them +(use-package org-fragtog + :ensure t + :config + (add-hook 'org-mode-hook 'org-latex-preview) + (add-hook 'org-mode-hook 'org-fragtog-mode) + (setq org-format-latex-options (plist-put org-format-latex-options :scale 3.0)) +) + +;; Treesit Config +(use-package treesit + :straight nil + :commands (treesit-install-language-grammar nf/treesit-install-all-languages) + :init + (setq treesit-language-source-alist + '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) + (c . ("https://github.com/tree-sitter/tree-sitter-c")) + (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) + (css . ("https://github.com/tree-sitter/tree-sitter-css")) + (cmake . ("https://github.com/uyha/tree-sitter-cmake")) + (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")) + (json . ("https://github.com/tree-sitter/tree-sitter-json")) + (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) + (lua . ("https://github.com/Azganoth/tree-sitter-lua")) + (make . ("https://github.com/alemuller/tree-sitter-make")) + (ocaml . ("https://github.com/tree-sitter/tree-sitter-ocaml" "master" "ocaml/src")) + (python . ("https://github.com/tree-sitter/tree-sitter-python")) + (php . ("https://github.com/tree-sitter/tree-sitter-php")) + (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")) + (tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")) + (ruby . ("https://github.com/tree-sitter/tree-sitter-ruby")) + (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) + (sql . ("https://github.com/m-novikov/tree-sitter-sql")) + (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) + (zig . ("https://github.com/GrayJack/tree-sitter-zig"))) + ) + :config ;; Credit to https://github.com/Nathan-Furnal/dotemacs/blob/df9b845563a84a927ff762e172334cf772253a44/init.el#L1154 + (defun nf/treesit-install-all-languages () + "Install all languages specified by `treesit-language-source-alist'." + (interactive) + (let ((languages (mapcar 'car treesit-language-source-alist))) + (dolist (lang languages) + (treesit-install-language-grammar lang) + (message "`%s' parser was installed." lang) + (sit-for 0.75)))) +) +(setq treesit-font-lock-level 4) +; Remap basic modes to treesit equivalent +(use-package rust-ts-mode + :straight nil + :mode "\\.rs\\'") +(use-package nix-ts-mode + :straight nil + :mode "\\.nix\\'") +(use-package html-ts-mode + :straight nil + :mode "\\.html\\'") +(use-package css-ts-mode + :straight nil + :mode "\\.css\\'") +(use-package js-ts-mode + :straight nil + :mode "\\.js\\'") +(use-package typescript-ts-mode + :straight nil + :mode "\\.ts\\'") +(use-package tsx-ts-mode + :straight nil + :mode "\\.tsx\\'") +;(use-package emacs-lisp-ts-mode +; :ensure t) +; Remap base modes to their treesitter counterpart +(setq major-mode-remap-alist + '( + ;(emacs-lisp-mode . emacs-lisp-ts-mode) + + (c-mode . c-ts-mode) + (rust-mode . rust-ts-mode) + (rustic-mode . rust-ts-mode) + (python-mode . python-ts-mode) + (html-mode . html-ts-mode) + (css-mode . css-ts-mode) + (js-mode . js-ts-mode) + (javascript-mode . js-ts-mode) + ) +) + +;; Programming treesit style config +; Enforcing tabs as programming style +(add-hook 'prog-mode-hook + (lambda () + (setq-local tab-width custom-tab-width) + (setq-local indent-tabs-mode 't))) +(add-hook 'nix-ts-mode-hook + (lambda () + (setq-local nix-ts-mode-indent-offset custom-tab-width))) +(add-hook 'c-ts-mode-hook + (lambda () + (setq-local c-ts-mode-indent-style 'linux) + (setq-local c-ts-mode-indent-offset custom-tab-width) + (c-ts-mode-toggle-comment-style -1))) +(add-hook 'rust-ts-mode-hook + (lambda () + (setq-local rust-ts-mode-indent-offset custom-tab-width))) + +;; LSP Configuration +(use-package eglot + :hook + ((( + prog-mode + nix-ts-mode + html-ts-mode + css-ts-mode + js-ts-mode + typescript-ts-mode + tsx-ts-mode + ) . eglot-ensure)) + :custom + (eglot-ignored-server-capabilities '(:documentOnTypeFormattingProvider)) +) + +;; HTML Emmet Snippets +(use-package emmet-mode + :ensure t + :hook + (html-ts-mode . emmet-mode) + (css-ts-mode . emmet-mode) + :config + (setq emmet-indentation custom-tab-width) +) + +;; JS Prettier Mode +(use-package prettier-js + :ensure t + :hook + (js-ts-mode . prettier-js-mode) + (typescript-ts-mode . prettier-js-mode) + (tsx-ts-mode . prettier-js-mode) + :config + (setq prettier-js-use-modules-bin t) +) + +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(auth-source-save-behavior nil) + '(package-selected-packages nil)) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + ) diff --git a/plugins/ido-occur.el b/plugins/ido-occur.el new file mode 100644 index 0000000..fc80d52 --- /dev/null +++ b/plugins/ido-occur.el @@ -0,0 +1,170 @@ +;;; ido-occur-isguon.el --- Yet another `occur' with `ido'. Modified by isguon + +;; Copyright (C) 2016 Danil . +;; Author: Danil , Josuah Demangeon , sebasar +;; Version: 0.2.0 +;; Package-Requires: ((dash "2.13.0")) +;; Keywords: inner buffer search +;; URL: https://github.com/danil/ido-occur + +;;; Commentary: +;; Yet another `occur' with `ido'. +;; See the README.md for more details. + +;;; License: + +;; This file is not part of GNU Emacs. +;; However, it is distributed under the same license. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Code: + +(require 'ido) +(require 'dash) + +(defgroup ido-occur nil + "Yet another `occur' with `ido'." + :group 'help + :group 'convenience) + +(defcustom ido-occur--prompt "List lines matching: " + "Minibuffer prompt." + :type 'string + :group 'ido-occur) + +(defcustom ido-occur--decorations + '("\n-> " "" "\n " "\n ..." "[" "]" + " [No match]" " [Matched]" " [Not readable]" + " [Too big]" " [Confirm]") + "Decorations for when ther is no vertical mode." + :type 'list + :group 'ido-occur) + +(defun ido-occur--lines-as-string (buffer) + "Get all lines with properties of the `BUFFER'." + (with-current-buffer buffer + (save-restriction + (widen) + (buffer-substring (point-min) (point-max))))) + +(defun ido-occur--decorate-lines-list (lines) + "Add line number to each string in `LINES'." + + (let* ((lines-count (number-to-string (length lines)))) + + (-map-indexed (lambda (index str) + "Transform `INDEX' to number and add to `STR'." + + (let* ((line-number (+ index 1)) + + (number-length (number-to-string (length lines-count))) + + (formated-line-number (format (concat "%" number-length "s") + line-number))) + + (format "%s %s" formated-line-number str))) + + lines))) + +(defun ido-occur--lines-as-list (buffer line-number) + "List all lines of `BUFFER' with respects to current `LINE-NUMBER'. +List lines from `LINE-NUMBER' to end of `BUFFER' +and from end of `BUFFER' to beginning of `BUFFER'." + + (let ((line-number (line-number-at-pos)) + + (lines (ido-occur--decorate-lines-list + (split-string (ido-occur--lines-as-string buffer) "\n")))) + + (-concat (-drop (- line-number 1) lines) + (-take line-number lines)))) + +(defun ido-occur--strip-text-properties (txt) + "Strip text properties from `TXT'." + (set-text-properties 0 (length txt) nil txt) txt) + +(defun ido-occur--run (&optional query) + "Yet another `occur' with `ido'. +When non-nil, QUERY is the initial search pattern." + + (interactive) + + (let* ((initial-column (current-column)) + + (line (ido-occur--strip-text-properties + (ido-completing-read ido-occur--prompt + (ido-occur--lines-as-list (current-buffer) + (line-number-at-pos)) + nil + nil + query))) + (line-length (length line)) + + (new-column (if (<= line-length initial-column) + line-length + initial-column)) + + (line-number (string-to-number (car (split-string line))))) + + (goto-line line-number) ;ido-occur.el:119:16:Warning: `goto-line' is for interactive use only; use `forward-line' instead. + (beginning-of-line) + (move-to-column new-column))) + +;;;###autoload +(defun ido-occur (&optional query) + "Yet another `occur' with `ido'. +When non-nil, QUERY is the initial search pattern." + + (interactive) + + ;; Because in original "Ido" matcher preserves candidates sort order. + (when (fboundp 'ido-clever-match-disable) (ido-clever-match-disable)) + + (cond ((bound-and-true-p ido-vertical-mode) + (ido-occur--run query)) + + ((bound-and-true-p ido-grid-mode) + (let ((ido-grid-mode-max-columns 1) + (ido-grid-mode-max-rows 8) + (ido-grid-mode-prefix-scrolls t)) + (ido-occur--run query))) + + (t + (let ((ido-decorations ido-occur--decorations)) + (ido-occur--run query)))) + + (when (fboundp 'ido-clever-match-enable) (ido-clever-match-enable))) + +;;;###autoload +(defun ido-occur-at-point () + "Open `ido-occur' at point." + + (interactive) + + (ido-occur (if (symbol-at-point) (symbol-name (symbol-at-point)) ""))) + +;;;###autoload +(defun ido-occur-from-isearch () + "Open `ido-occur' from `isearch'." + + (interactive) + + (ido-occur (if isearch-regexp isearch-string (regexp-quote isearch-string)))) + +(provide 'ido-occur) + +;;; ido-occur.el ends here