Last active
December 3, 2024 03:40
-
-
Save vishesh/8aa9dec6b0097b9c5e14688638831c6a to your computer and use it in GitHub Desktop.
Leanest usable emacs config, without using any external packages in emacs29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;; init.el --- Emacs configuration. -*- lexical-binding: t -*- | |
| ;;; Copyright (C) 2023 Vishesh Yadav | |
| ;;; Author: Vishesh Yadav <visehsh3y@gmail.com> | |
| ;; | |
| ;; Leanest usable emacs config, without using any external packages in emacs29. | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Personal | |
| ;;;---------------------------------------------------------------------------- | |
| (setq user-full-name "Vishesh Yadav") | |
| (setq user-mail-address "vishesh3y@gmail.com") | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Constants | |
| ;;;---------------------------------------------------------------------------- | |
| (when (< emacs-major-version 27) | |
| (error "This requires Emacs 27.0 and above!")) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Setup Package Management | |
| ;;;---------------------------------------------------------------------------- | |
| ;; -> Install `'use-package`. | |
| (require 'package) | |
| (setq package-enable-at-startup nil) | |
| (setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/") | |
| ("nongnu" . "https://elpa.nongnu.org/nongnu/") | |
| ("melpa" . "http://melpa.org/packages/"))) | |
| (package-initialize) | |
| ;; Setup `use-package' | |
| (unless (package-installed-p 'use-package) | |
| (package-refresh-contents) | |
| (package-install 'use-package)) | |
| ;; Should set before loading `use-package' | |
| (eval-and-compile | |
| (setq byte-compile-warnings '(cl-functions)) | |
| (setq use-package-always-ensure t) | |
| (setq use-package-always-defer t) | |
| (setq use-package-expand-minimally t)) | |
| (eval-when-compile | |
| (require 'use-package)) | |
| ;; Load path | |
| (add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory)) | |
| (add-to-list 'load-path (expand-file-name "site-lisp" user-emacs-directory)) | |
| (setq custom-theme-directory (expand-file-name "themes" user-emacs-directory)) | |
| (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) | |
| (load custom-file 'no-error) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Editing | |
| ;;;---------------------------------------------------------------------------- | |
| (prefer-coding-system 'utf-8) | |
| ;; Tab and Space | |
| (global-display-fill-column-indicator-mode) | |
| (setq-default major-mode 'text-mode | |
| c-basic-offset 4 | |
| fill-column 80 | |
| tab-width 4 | |
| indent-tabs-mode nil) | |
| ;; Close brackets/quotes automatically. | |
| (electric-pair-mode +1) | |
| (setq kill-ring-max 500) | |
| ;; Save clipboard contents into kill-ring before replace them | |
| (setq save-interprogram-paste-before-kill t) | |
| ;; Repeating C-SPC after popping mark pops it again | |
| (setq set-mark-command-repeat-pop t) | |
| ;; Don't wrap lines. | |
| (setq-default truncate-lines t) | |
| ;; Delete selection if you insert | |
| (use-package delsel | |
| :hook (after-init . delete-selection-mode)) | |
| ;; Rectangle | |
| (use-package rect | |
| :ensure nil | |
| :bind (("<C-return>" . rectangle-mark-mode))) | |
| (bind-key "C-a" 'back-to-indentation-or-beginning-of-line) | |
| (bind-key "M-g" 'goto-line) | |
| (bind-key "C-M-'" 'match-paren) | |
| (bind-key "C-w" 'kill-region-or-backward-word) | |
| (bind-key "M-w" 'kill-region-or-thing-at-point) | |
| (bind-key "C-S-k" 'kill-whole-line) | |
| (bind-key "C-o" 'open-line-below) | |
| (bind-key "C-c C-o" 'open-line-above) | |
| (bind-key "C-S-o" 'open-line-above) | |
| (bind-key "M-j" 'join-line) | |
| (bind-key "M-_" 'previous-buffer) | |
| (bind-key "M-+" 'next-buffer) | |
| (bind-key "C-x C-b" 'switch-to-buffer) | |
| (bind-key "C-6" 'global-display-line-numbers-mode) | |
| (bind-key "M-s i" 'completion-at-point) | |
| (bind-key "M-\\" 'imenu) | |
| (bind-key "C-c g" 'grep-completing-read) | |
| (bind-key "C-c C-g" 'rgrep) | |
| (bind-keys ("C-M->" . indent-rigidly-right) | |
| ("C-M-<" . indent-rigidly-left)) | |
| (use-package ibuffer :bind (("C-x b" . ibuffer-bs-show))) | |
| (setq hippie-expand-try-functions-list | |
| '(try-expand-dabbrev | |
| try-expand-dabbrev-all-buffers | |
| try-expand-dabbrev-from-kill | |
| try-complete-file-name-partially | |
| try-complete-file-name try-expand-all-abbrevs | |
| try-expand-list try-expand-line try-complete-lisp-symbol-partially | |
| try-complete-lisp-symbol)) | |
| (bind-key "M-/" 'hippie-expand) | |
| ;; Click to browse URL or to send to e-mail address | |
| (use-package goto-addr | |
| :ensure nil | |
| :hook ((text-mode . goto-address-mode) | |
| (prog-mode . goto-address-prog-mode))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Search | |
| ;;;---------------------------------------------------------------------------- | |
| ;; Make backspace delete the search term not goto last address | |
| (define-key isearch-mode-map [remap isearch-delete-char] 'isearch-del-char) | |
| (defun isearchp-kill-ring-save () | |
| "Copy the current search string to the kill ring. Credits: isearch+" | |
| (interactive) | |
| (kill-new isearch-string) | |
| (sit-for 1) | |
| (isearch-update)) | |
| ;; Default query-replace shortcut on macOS would conflict with system shortcut | |
| ;; to take screenshot. So lets rebind these. | |
| (bind-key "C-?" #'query-replace) | |
| (bind-keys :map isearch-mode-map | |
| ("C-?" . isearch-query-replace) | |
| ("M-w" . isearchp-kill-ring-save)) | |
| (defcustom vyconfig-use-ripgrep nil | |
| "Use ripgrep for completing-read search." | |
| :group 'vyconfig | |
| :type 'boolean) | |
| (defun grep-completing-read () | |
| "Do a project search using completing-read" | |
| (interactive) | |
| (let* ((default-term (if (region-active-p) | |
| (substring-no-properties | |
| (buffer-substring (mark) (point))) | |
| (thing-at-point 'symbol))) | |
| (term (read-string "search for: " default-term)) | |
| (execute-search | |
| (lambda (term) | |
| (cond | |
| ((and vyconfig-use-ripgrep (executable-find "rg")) | |
| ;; FIXME: Takes regexp, making it awkward for terms with special | |
| ;; chars. | |
| (process-lines "rg" "--line-number -e" term)) | |
| ((and (project-current nil) | |
| (equal (cadr (project-current nil)) 'Git)) | |
| (process-lines "git" "grep" "-niH" "-e" term)) | |
| (t (process-lines "grep" "-nirH" "-e" term))))) | |
| (results (funcall execute-search term)) | |
| (line-list (split-string (completing-read "results: " results) ":")) | |
| (rfile (car line-list)) | |
| (rlnum (string-to-number (car (cdr line-list))))) | |
| (find-file rfile) | |
| (goto-line rlnum) | |
| (recenter))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Programming | |
| ;;;---------------------------------------------------------------------------- | |
| (bind-keys | |
| ("C-c c" . recompile) | |
| ("<f12>" . compile)) | |
| (bind-key "M-;" 'comment-dwim) | |
| (bind-key "C-7" 'comment-line) | |
| (use-package cc-mode | |
| :bind (:map c-mode-base-map | |
| ("C-c o" . eglot-clangd-find-other-file))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Project | |
| ;;;---------------------------------------------------------------------------- | |
| (use-package project | |
| :bind (("C-c M-k" . project-kill-buffers) | |
| ("C-c m" . project-compile) | |
| ("C-x f" . find-file) | |
| ("C-t" . find-file-in-project-or-directory)) | |
| :bind-keymap ("C-c p" . project-prefix-map) | |
| :defines find-file-in-project-or-directory | |
| :custom | |
| (project-switch-commands | |
| '((project-find-file "Find file") | |
| (project-find-regexp "Grep" ?h))) | |
| :config | |
| (defun find-file-in-project-or-directory () | |
| (interactive) | |
| (if (project-current nil) | |
| (project-find-file) | |
| (call-interactively #'find-name-dired)))) | |
| (use-package vc | |
| :bind | |
| (("C-c i" . vc-git-grep) | |
| ("C-x g" . vc-dir-root)) | |
| :config | |
| (defun vc-git-expanded-log-entry (revision) | |
| "Just adds commit stats to expanded commit entry in log-view." | |
| (with-temp-buffer | |
| (apply #'vc-git-command t nil nil | |
| (list "log" revision "-1" "--stat" "--no-color" "--stat" "--")) | |
| (goto-char (point-min)) | |
| (unless (eobp) | |
| ;; Indent the expanded log entry. | |
| (while (re-search-forward "^" nil t) | |
| (replace-match " ") | |
| (forward-line)) | |
| (concat "\n" (buffer-string)))))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Diffing | |
| ;;;---------------------------------------------------------------------------- | |
| ;; A comprehensive visual interface to diff & patch | |
| (use-package ediff | |
| :hook(;; show org ediffs unfolded | |
| (ediff-prepare-buffer . outline-show-all) | |
| ;; restore window layout when done | |
| (ediff-quit . winner-undo)) | |
| :config | |
| (setq ediff-window-setup-function 'ediff-setup-windows-plain) | |
| (setq ediff-split-window-function 'split-window-horizontally) | |
| (setq ediff-merge-split-window-function 'split-window-horizontally)) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Large files | |
| ;;;---------------------------------------------------------------------------- | |
| (defun fast-file-view-mode () | |
| "Makes the buffer readonly and disables fontlock and other bells and whistles | |
| for faster viewing" | |
| (interactive) | |
| (setq buffer-read-only t) | |
| (buffer-disable-undo) | |
| (fundamental-mode) | |
| (font-lock-mode -1) | |
| (when (boundp 'anzu-mode) | |
| (anzu-mode -1))) | |
| (defun large-find-file-hook () | |
| "If a file is over a given size, make the buffer read only." | |
| (when (> (buffer-size) (* 1024 1024)) | |
| (fast-file-view-mode))) | |
| (add-hook 'find-file-hook 'large-find-file-hook) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Window Management | |
| ;;;---------------------------------------------------------------------------- | |
| (bind-key "C-q" 'other-window) | |
| ;; Directional window-selection routines | |
| (use-package windmove | |
| :ensure nil | |
| :hook (after-init . windmove-default-keybindings)) | |
| ;; Restore old window configurations | |
| (use-package winner | |
| :ensure nil | |
| :hook (after-init . winner-mode) | |
| :init (setq winner-boring-buffers '("*Completions*" | |
| "*Compile-Log*" | |
| "*inferior-lisp*" | |
| "*Fuzzy Completions*" | |
| "*Apropos*" | |
| "*Help*" | |
| "*cvs*" | |
| "*Buffer List*" | |
| "*Ibuffer*" | |
| "*esh command on file*"))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Buffers and Files | |
| ;;;---------------------------------------------------------------------------- | |
| (setq delete-by-moving-to-trash t) ; Deleting files go to OS's trash folder | |
| (setq make-backup-files nil) ; Forbide to make backup files | |
| (setq auto-save-default nil) ; Disable auto save | |
| (use-package autorevert | |
| :diminish auto-revert-mode | |
| :hook (after-init . global-auto-revert-mode)) | |
| (use-package saveplace | |
| :hook (after-init . save-place-mode)) | |
| (use-package recentf | |
| ;; lazy load recentf | |
| :hook (find-file . (lambda () (unless recentf-mode | |
| (recentf-mode) | |
| (recentf-track-opened-file)))) | |
| :bind ("C-c <RET>" . recentf) | |
| :init | |
| (add-hook 'after-init-hook #'recentf-mode) | |
| (setq recentf-max-saved-items 200) | |
| :config | |
| (add-to-list 'recentf-exclude (expand-file-name package-user-dir)) | |
| (add-to-list 'recentf-exclude ".objs") | |
| (add-to-list 'recentf-exclude ".cache") | |
| (add-to-list 'recentf-exclude ".cask") | |
| (add-to-list 'recentf-exclude "bookmarks") | |
| (add-to-list 'recentf-exclude "COMMIT_EDITMSG\\'")) | |
| (use-package savehist | |
| :hook (after-init . savehist-mode) | |
| :init (setq enable-recursive-minibuffers t ; Allow commands in minibuffers | |
| history-length 1000 | |
| savehist-additional-variables '(mark-ring | |
| global-mark-ring | |
| search-ring | |
| regexp-search-ring | |
| extended-command-history) | |
| savehist-autosave-interval 60)) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; GUI/CLI/Frame/Look and Feel/System | |
| ;;;---------------------------------------------------------------------------- | |
| (when (display-graphic-p) | |
| (add-to-list 'default-frame-alist '(height . 60)) | |
| (add-to-list 'default-frame-alist '(width . 100))) | |
| (make-face-bold 'font-lock-keyword-face) | |
| ;;; Tweak modifier keys per platform. | |
| ;; OS specific tweaks | |
| (cond | |
| ((string-equal system-type "darwin") | |
| (setq ns-use-thin-smoothing t) | |
| (setq mac-option-key-is-meta t | |
| mac-command-key-is-meta nil | |
| mac-command-modifier 'meta | |
| mac-option-modifier 'super | |
| ns-use-native-fullscreen nil)) | |
| ((string-equal system-type "gnu/linux") t)) | |
| (when (display-graphic-p) | |
| (bind-keys ([(control f11)] . toggle-frame-fullscreen))) | |
| ;; Load remote environment when using tramp-mode. | |
| (eval-after-load 'tramp '(setenv "SHELL" "/bin/bash")) | |
| ;;; Remove some GUI features. | |
| (menu-bar-mode -1) | |
| (when window-system | |
| (tool-bar-mode -1) | |
| (scroll-bar-mode -1)) | |
| (setq use-file-dialog nil | |
| use-dialog-box nil | |
| inhibit-startup-screen t | |
| inhibit-startup-echo-area-message t) | |
| (global-unset-key (kbd "<C-wheel-down>")) | |
| (global-unset-key (kbd "<C-wheel-up>")) | |
| ;; Secondary click open context menu in GUI. | |
| (context-menu-mode) | |
| ;; Menubar in terminal. | |
| (bind-key "M-`" #'tmm-menubar) | |
| ;; Ask yes or no, explicitely. | |
| (fset 'yes-or-no-p 'y-or-n-p) | |
| (bind-key "C-<tab>" 'other-frame) | |
| ;; Show column numbers in mode line. | |
| (setq column-number-mode t) | |
| ;; Go directly to scratch buffer. | |
| (setq inhibit-splash-screen t) | |
| ;; For Mac OSX weird redraw bug on bell | |
| (setq ring-bell-function (lambda () (message "*woop*"))) | |
| ;; Compilation output, autoscroll | |
| (setq compilation-scroll-output t) | |
| ;; Line Numbers in gutter. | |
| (use-package display-line-numbers | |
| :hook ((prog-mode . display-line-numbers-mode) | |
| (prog-mode . which-function-mode) | |
| (markdown-mode . display-line-numbers-mode) | |
| (text-mode . display-line-numbers-mode))) | |
| ;; Show path if names are same | |
| (setq uniquify-buffer-name-style 'post-forward-angle-brackets) | |
| ;;; Scrolling | |
| (when (and window-system (>= emacs-major-version 29)) | |
| (pixel-scroll-precision-mode 1)) | |
| (setq scroll-preserve-screen-position 'always | |
| mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; Scroll one line at a time. | |
| mouse-wheel-progressive-speed nil | |
| scroll-step 1 | |
| scroll-margin 1 | |
| scroll-conservatively 10000) | |
| (setq visible-bell t | |
| inhibit-compacting-font-caches t ; Don’t compact font caches during GC. | |
| adaptive-fill-regexp "[ t]+|[ t]*([0-9]+.|*+)[ t]*" | |
| adaptive-fill-first-line-regexp "^* *$" | |
| sentence-end "\\([。!?]\\|……\\|[.?!][]\"')}]*\\($\\|[ \t]\\)\\)[ \t\n]*" | |
| sentence-end-double-space nil) | |
| ;; Never kill scratch. | |
| (with-current-buffer "*scratch*" | |
| (emacs-lock-mode 'kill)) | |
| ;; Don't show native comp warnings. | |
| (setq native-comp-async-report-warnings-errors 'silent) | |
| ;; Enable colors in compilation output. | |
| ;; HACK: Don't apply on grep-mode. | |
| (use-package ansi-color | |
| :config | |
| (defun --compilation-filter (fn proc string) | |
| "Wrap `compilation-filter' (FN PROC STRING) to support `ansi-color'." | |
| (let ((buf (process-buffer proc))) | |
| (when (buffer-live-p buf) | |
| (with-current-buffer buf | |
| (funcall fn proc string) | |
| (when (not (equal major-mode 'grep-mode)) | |
| (let ((inhibit-read-only t)) | |
| (ansi-color-apply-on-region (point-min) (point-max)))))))) | |
| (advice-add 'compilation-filter :around #'--compilation-filter)) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Completions | |
| ;;;---------------------------------------------------------------------------- | |
| (setq tab-always-indent 'complete) | |
| ;; For making completion-at-point work with icomplete/fido. | |
| ;; https://www.reddit.com/r/emacs/comments/ulsrb5/what_have_you_recently_removed_from_your_emacs/ | |
| (defun completing-read-at-point (start end col &optional pred) | |
| (if (minibufferp) (completion--in-region start end col pred) | |
| (let* ((init (buffer-substring-no-properties start end)) | |
| (all (completion-all-completions init col pred (length init))) | |
| (completion (cond | |
| ((atom all) nil) | |
| ((and (consp all) (atom (cdr all))) (car all)) | |
| (t (completing-read "Completions: " col pred t init))))) | |
| (if completion | |
| (progn | |
| (delete-region start end) | |
| (insert completion) | |
| t) | |
| (message "No completions") nil)))) | |
| (setq completion-category-defaults nil) | |
| (setq completion-in-region-function #'completing-read-at-point) | |
| (use-package minibuffer | |
| :ensure nil | |
| :bind (:map minibuffer-mode-map | |
| ("C-n" . minibuffer-next-completion) | |
| ("C-p" . minibuffer-previous-completion) | |
| ("M-<RET>" . my/minibuffer-choose-completion)) | |
| :bind (:map completion-in-region-mode-map | |
| ("C-n" . minibuffer-next-completion) | |
| ("C-p" . minibuffer-previous-completion) | |
| ("M-<RET>" . my/minibuffer-choose-completion)) | |
| :init | |
| (setq enable-recursive-minibuffers t | |
| completion-styles '(initials partial-completion flex) | |
| completions-format 'one-column | |
| completions-header-format nil | |
| completion-auto-help t | |
| completion-show-help nil | |
| completions-max-height 10 | |
| resize-mini-windows t | |
| completion-flex-nospace nil | |
| completion-pcm-complete-word-inserts-delimiters t | |
| completion-auto-select nil | |
| completion-ignore-case t | |
| read-buffer-completion-ignore-case t | |
| read-file-name-completion-ignore-case t) | |
| (defun my/minibuffer-choose-completion (&optional no-exit no-quit) | |
| (interactive "P") | |
| (with-minibuffer-completions-window | |
| (let ((completion-use-base-affixes nil)) | |
| (choose-completion nil no-exit no-quit))))) | |
| (use-package icomplete | |
| :bind (:map icomplete-fido-mode-map | |
| ("TAB" . icomplete-force-complete) | |
| ("C-j" . icomplete-ret) | |
| ("C-n" . icomplete-forward-completions) | |
| ("C-p" . icomplete-backward-completions)) | |
| :hook (icomplete-minibuffer-setup . (lambda () (setq-local truncate-lines t))) | |
| :init | |
| (setq icomplete-in-buffer t | |
| icomplete-with-completion-tables t | |
| icomplete-hide-common-prefix nil | |
| icomplete-prospects-height 6 | |
| icomplete-compute-delay 0) | |
| (fido-mode +1) | |
| (fido-vertical-mode +1)) | |
| ;; LSP | |
| (use-package eglot | |
| :hook ((c++-mode . eglot-ensure) | |
| (c-mode . eglot-ensure) | |
| (python-mode . eglot-ensure)) | |
| :bind (:map eglot-mode-map | |
| ("C-c a r" . #'eglot-rename) | |
| ("C-c h" . #'eldoc) | |
| ("C-<down-mouse-1>" . #'xref-find-definitions) | |
| ("C-S-<down-mouse-1>". #'xref-find-references) | |
| ("C-c C-c" . #'eglot-code-actions) | |
| ("C-M-<tab>" . #'eglot-format)) | |
| :config | |
| (defun eglot-clangd-find-other-file (&optional new-window) | |
| "Switch between the corresponding C/C++ source and header file." | |
| (interactive) | |
| (let* ((server (eglot--current-server-or-lose)) | |
| (rep | |
| (jsonrpc-request | |
| server | |
| :textDocument/switchSourceHeader | |
| (eglot--TextDocumentIdentifier)))) | |
| (unless (equal rep nil) | |
| (funcall #'find-file (eglot--uri-to-path rep))))) | |
| (with-eval-after-load 'eglot | |
| (setq --my-clangd-args '("clangd" | |
| "-j=4" | |
| "--background-index" | |
| "--clang-tidy" | |
| "--all-scopes-completion" | |
| "--completion-style=detailed" | |
| "--header-insertion=iwyu" | |
| "--header-insertion-decorators=0")) | |
| (add-to-list 'eglot-server-programs `(c-mode . ,--my-clangd-args)) | |
| (add-to-list 'eglot-server-programs `(c++-mode . ,--my-clangd-args))) | |
| (setq eldoc-echo-area-use-multiline-p nil | |
| eglot-extend-to-xref t | |
| eldoc-idle-delay 0.1 | |
| eglot-autoshutdown t)) | |
| (use-package flymake | |
| :bind (("C-c l a" . flymake-show-project-diagnostics) | |
| ("C-c l b" . flymake-show-buffer-diagnostics) | |
| ("C-x ]" . flymake-goto-next-error) | |
| ("C-x [" . flymake-goto-prev-error))) | |
| (use-package flyspell | |
| :hook (text-mode . flyspell-mode)) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Highlight | |
| ;;;---------------------------------------------------------------------------- | |
| (use-package hi-lock | |
| :bind | |
| (("M-n" . isearch-forward-symbol-at-point) | |
| ("M-l" . my/toggle-mark-symbol-at-point)) | |
| :config | |
| (defun my/toggle-mark-symbol-at-point () | |
| (interactive) | |
| (if hi-lock-interactive-patterns | |
| (unhighlight-regexp (car (car hi-lock-interactive-patterns))) | |
| (highlight-symbol-at-point)))) | |
| (use-package hl-line | |
| :hook (after-init . global-hl-line-mode)) | |
| (use-package paren | |
| :hook (after-init . show-paren-mode) | |
| :config | |
| (setq show-paren-when-point-inside-paren t | |
| show-paren-when-point-in-periphery t)) | |
| ;; Visualize TAB, (HARD) SPACE, NEWLINE | |
| (use-package whitespace | |
| :ensure nil | |
| :bind ("C-x w" . whitespace-mode) | |
| :hook ((prog-mode outline-mode conf-mode) . whitespace-mode) | |
| :config | |
| (setq whitespace-line-column fill-column) ;; limit line length | |
| ;; Automatically clean up bad whitespace | |
| (setq whitespace-action '(auto-cleanup)) | |
| ;; Only show bad whitespace | |
| (setq whitespace-style '(face trailing indentation empty))) | |
| ;; Pulse current line | |
| (use-package pulse | |
| :ensure nil | |
| :preface | |
| (defun my-pulse-momentary (&rest _) | |
| "Pulse the current line." | |
| (pulse-momentary-highlight-one-line (point) 'next-error)) | |
| (defun my-recenter (&rest _) | |
| "Recenter and pulse the current line." | |
| (recenter) | |
| (my-pulse-momentary)) | |
| :hook ((bookmark-after-jump next-error other-window | |
| dumb-jump-after-jump imenu-after-jump) . my-recenter) | |
| :init (dolist (cmd '(recenter-top-bottom | |
| other-window windmove-do-window-select | |
| pop-to-mark-command pop-global-mark | |
| pager-page-down pager-page-up)) | |
| (advice-add cmd :after #'my-pulse-momentary))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Utils | |
| ;;;---------------------------------------------------------------------------- | |
| (use-package dired | |
| :ensure nil | |
| :bind (:map dired-mode-map | |
| ("C-c C-p" . wdired-change-to-wdired-mode)) | |
| :hook ((dired-mode . (lambda () (local-unset-key (kbd "C-t"))))) ; image-dired | |
| :config | |
| (setq dired-recursive-deletes 'always | |
| dired-recursive-copies 'always | |
| dired-isearch-filenames 'dwim) | |
| (when (executable-find "gls") | |
| ;; Use GNU ls when possible. | |
| (setq dired-use-ls-dired nil) | |
| (setq ls-lisp-use-insert-directory-program t) | |
| (setq insert-directory-program "gls") | |
| (setq dired-listing-switches "-alh --group-directories-first")) | |
| (use-package dired-aux :ensure nil)) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Library | |
| ;;;---------------------------------------------------------------------------- | |
| (defun match-paren (&optional arg) | |
| "Go to the matching parenthesis character if one is adjacent to point." | |
| (interactive "^p") | |
| (cond ((looking-at "\\s(") (forward-sexp arg)) | |
| ((looking-back "\\s)" 1) (backward-sexp arg)) | |
| ;; Now, try to succeed from inside of a bracket | |
| ((looking-at "\\s)") (forward-char) (backward-sexp arg)) | |
| ((looking-back "\\s(" 1) (backward-char) (forward-sexp arg)))) | |
| (defun kill-region-or-backward-word () | |
| "If the region is active and non-empty, call `kill-region'. | |
| Otherwise, call `backward-kill-word'." | |
| (interactive) | |
| (call-interactively | |
| (if (use-region-p) 'kill-region 'backward-kill-word))) | |
| (defun open-line-below () | |
| (interactive) | |
| (move-end-of-line 1) | |
| (newline) | |
| (indent-according-to-mode)) | |
| (defun open-line-above () | |
| (interactive) | |
| (move-beginning-of-line 1) | |
| (newline) | |
| (forward-line -1) | |
| (indent-according-to-mode)) | |
| (defun kill-region-or-thing-at-point (beg end) | |
| (interactive "r") | |
| (unless (region-active-p) | |
| (save-excursion | |
| (setq beg (re-search-backward "\\_<" nil t)) | |
| (setq end (re-search-forward "\\_>" nil t)))) | |
| (kill-ring-save beg end)) | |
| (defun back-to-indentation-or-beginning-of-line () | |
| (interactive) | |
| (if (= (point) (save-excursion (back-to-indentation) (point))) | |
| (beginning-of-line) | |
| (back-to-indentation))) | |
| (defun find-file-at-point-with-line() | |
| "Goto file at point, and move cursor to line number if given." | |
| (interactive) | |
| (setq line-num 0) | |
| (save-excursion | |
| (search-forward-regexp "[^ ]:" (point-max) t) | |
| (if (looking-at "[0-9]+") | |
| (setq line-num | |
| (string-to-number | |
| (buffer-substring (match-beginning 0) (match-end 0)))))) | |
| (find-file (ffap-guesser)) | |
| (if (not (equal line-num 0)) | |
| (goto-line line-num))) | |
| ;;;---------------------------------------------------------------------------- | |
| ;;; Unorganized | |
| ;;;---------------------------------------------------------------------------- | |
| ;; For local configurations. | |
| (load (expand-file-name "local.el" user-emacs-directory) 'noerror) | |
| (define-minor-mode minor-mode-blackout-mode | |
| "Hides minor modes from the mode line." | |
| t) | |
| (catch 'done | |
| (mapc (lambda (x) | |
| (when (and (consp x) | |
| (equal (cadr x) '("" minor-mode-alist))) | |
| (let ((original (copy-sequence x))) | |
| (setcar x 'minor-mode-blackout-mode) | |
| (setcdr x (list "" original))) | |
| (throw 'done t))) | |
| mode-line-modes)) | |
| (defun timestamp () | |
| (interactive) | |
| (insert (format-time-string "%Y-%M-%d %I:%M:%S %Z"))) | |
| ;;------------------------------------------------------------------------------ | |
| (provide 'init) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment