;;; bandali-essentials.el --- bandali's essentials -*- lexical-binding: t; -*- ;; Copyright (c) 2018-2025 Amin Bandali ;; Author: Amin Bandali ;; Keywords: files, internal ;; 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 of the License, 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 this program. If not, see . ;;; Commentary: ;; The core essentials of my GNU Emacs setup. ;;; Code: (use-package emacs :demand t :bind ("C-c e b" . eval-buffer) ("C-c e r" . eval-region) :config (when (display-graphic-p) ;; Too easy to accidentally suspend (freeze) Emacs GUI. (b/keymap-global-unset "C-z")) (setq-default ;; Case-sensitive search (and `dabbrev-expand'). ;; case-fold-search nil indent-tabs-mode nil ; always use space for indentation ;; tab-width 4 indicate-buffer-boundaries 'left) (setq ;; line-spacing 3 completion-ignore-case t read-buffer-completion-ignore-case t enable-recursive-minibuffers t resize-mini-windows t message-log-max 20000 mode-line-compact t ;; mouse-autoselect-window t scroll-conservatively 15 scroll-preserve-screen-position 1 ;; I don't feel like randomly jumping out of my chair. ring-bell-function 'ignore) ;; Mode-line compacting for older Emacsen. (when (and (version< emacs-version "28") mode-line-compact) ;; Manually make some `mode-line' spaces smaller. ;; Emacs 28 and above do a terrific job at this out of the box ;; when `mode-line-compact' is set to t (see above)." (setq-default mode-line-format (mapcar (lambda (x) (if (and (stringp x) (or (string= x " ") (string= x " "))) " " x)) mode-line-format) mode-line-buffer-identification (propertized-buffer-identification "%10b"))) ;; Fonts and types. (when (display-graphic-p) (set-fontset-font t 'arabic "Sahel WOL") (let ((emoji-font "Apple Color Emoji")) (when (member emoji-font (font-family-list)) (set-fontset-font t 'emoji `(,emoji-font . "iso10646-1") nil 'prepend))) (with-eval-after-load 'faces (let ((grey "#e7e7e7")) ;; (set-face-attribute 'default nil ;; :font "Source Code Pro" ;; :height 113 ; 130 ; 105 ;; :weight 'medium) ;; (set-face-attribute 'fixed-pitch nil ;; :font "Source Code Pro" ;; :weight 'medium) ;; (set-face-attribute 'default nil ;; :font "Inconsolata Medium-12:hinting=true:autohint=true") ;; (set-face-attribute 'fixed-pitch nil ;; :font "Inconsolata Medium-12:hinting=true:autohint=true") (set-face-attribute 'default nil :font "Source Code Pro Medium-10.5") (set-face-attribute 'fixed-pitch nil :font "Source Code Pro Medium-10.5") (set-face-attribute 'mode-line nil :box '(:line-width 2 :style released-button) :background grey :inherit 'fixed-pitch))))) (use-package delight :ensure t :defer 0.5) (use-package minibuffer :defer t :custom (read-file-name-completion-ignore-case t)) (use-package files :bind ("C-c f ." . find-file) :custom (make-backup-files nil) ;; Insert newline at the end of files. ;; (require-final-newline t) ;; Open read-only file buffers in view-mode, to get `q' for quit. (view-read-only t)) (use-package ffap :bind ("C-c f p" . find-file-at-point)) (use-package find-func :bind ("C-c f l" . find-library)) (use-package frame :bind ("C-c F m" . make-frame-command) ("C-c F d" . delete-frame)) (use-package window :defer t :custom (split-width-threshold 140)) (use-package text-mode :mode "\\(README.*\\|COMMIT_EDITMSG$\\)") (use-package conf-mode :mode "\\.*rc$") (use-package sh-script :mode ("\\.bashrc$" . sh-mode)) (use-package novice :defer t :config (setq disabled-command-function nil)) (use-package autorevert :defer 0.1 :custom ;; (auto-revert-verbose nil) (global-auto-revert-non-file-buffers nil) :config (global-auto-revert-mode 1)) (use-package time :defer 0.1 :bind ("C-c e i" . emacs-init-time) ("C-c e u" . emacs-uptime) :custom (display-time-default-load-average nil) (display-time-format " %a %Y-%m-%d %-l:%M%P") (display-time-mail-icon '(image :type xpm :file "gnus/gnus-pointer.xpm" :ascent center)) (display-time-use-mail-icon t) :config (setopt zoneinfo-style-world-list `(,@zoneinfo-style-world-list ("Etc/UTC" "UTC") ("Asia/Tehran" "Tehran") ("Australia/Melbourne" "Melbourne"))) (unless (display-graphic-p) (display-time-mode 1))) (defvar b/battery-format "%p%b %t") (use-package battery ;; :if (not (display-graphic-p)) :defer 0.1 :custom (battery-mode-line-format (format " [%s]" b/battery-format))) (use-package winner :defer 0.5 :config (winner-mode 1) (when (featurep 'exwm) ;; Prevent a bad interaction between EXWM and winner-mode, where ;; sometimes closing a window (like closing a terminal after ;; entering a GPG password via pinentry-gnome3's floating window) ;; results in a dead frame somewhere and effectively freezes EXWM. (advice-add 'winner-insert-if-new :around (lambda (orig-fun &rest args) ;; only add the frame if it's live (when (frame-live-p (car args)) (apply orig-fun args)))))) (use-package windmove :defer 0.5 :custom (windmove-wrap-around t) :bind ("M-H" . windmove-left) ("M-L" . windmove-right) ("M-K" . windmove-up) ("M-J" . windmove-down)) (use-package isearch :defer t :custom (isearch-allow-scroll t) (isearch-lazy-count t) ;; Match non-ASCII variants during search (search-default-mode #'char-fold-to-regexp)) (use-package vc :bind ("C-x v C-=" . vc-ediff)) (use-package vc-git :defer t :custom ;; (vc-git-show-stash 0) (vc-git-print-log-follow t)) (use-package ediff :defer t :custom (ediff-window-setup-function #'ediff-setup-windows-plain) (ediff-split-window-function #'split-window-horizontally)) (use-package face-remap :disabled :custom ;; Gentler font scaling. (text-scale-mode-step 1.05)) (use-package mwheel :defer 0.4 :custom (mouse-wheel-scroll-amount '(1 ((shift) . 1))) ; one line at a time (mouse-wheel-progressive-speed nil) ; don't accelerate scrolling (mouse-wheel-follow-mouse t)) ; scroll window under mouse (use-package pixel-scroll :defer 0.4 :config (pixel-scroll-mode 1)) (use-package epg-config :defer t :custom (epg-gpg-program (executable-find "gpg")) ;; Ask for GPG passphrase in minibuffer. ;; Will fail if gpg >= 2.1 is not available. (epg-pinentry-mode 'loopback)) (use-package auth-source :disabled :custom (auth-sources '("~/.authinfo.gpg")) (authinfo-hidden (regexp-opt '("password" "client-secret" "token")))) (use-package info :defer t :config (setq Info-directory-list `(,@Info-directory-list ,(expand-file-name (convert-standard-filename "info/") source-directory) "/usr/share/info/"))) (use-package ielm :bind ("C-c i" . ielm)) (use-package recentf ;; recently opened files :defer 0.2 :init (defun b/recentf-open () "Use `completing-read' to \\[find-file] a recent file." (interactive) (find-file (completing-read "Find recent file: " recentf-list))) :bind ("C-c f r" . b/recentf-open) :custom (recentf-max-saved-items 2000) :config (recentf-mode 1)) (use-package help :defer t :custom (help-window-select t) :config (temp-buffer-resize-mode 1)) (use-package help-mode :bind (:map help-mode-map ("p" . backward-button) ("n" . forward-button) ("b" . help-go-back) ("f" . help-go-forward))) (use-package help-fns :bind ("C-c h F" . describe-face)) (use-package doc-view :bind (:map doc-view-mode-map ("M-RET" . image-previous-line))) (use-package man :defer t :custom (Man-width 80)) (use-package shr :defer t :custom (shr-max-width 80)) (use-package mule-cmds :defer t :preface (provide 'mule-cmds) :custom (default-input-method "farsi-isiri-9147")) (use-package tramp :defer t :config (tramp-set-completion-function "ssh" (append (tramp-get-completion-function "ssh") (mapcar (lambda (file) `(tramp-parse-sconfig ,file)) (directory-files "~/.ssh/config.d/" 'full directory-files-no-dot-files-regexp))))) (use-package eldoc ;; Display Lisp objects at point in the echo area. :defer t :custom (eldoc-minor-mode-string " eldoc") :config (global-eldoc-mode 1)) (use-package paren ;; Highlight matching parens. :defer 0.2 :config (show-paren-mode 1)) (use-package simple :delight (auto-fill-function " f") :hook ((text-mode tex-mode) . auto-fill-mode) :custom ;; Save what I copy into clipboard from other applications into ;; Emacs' kill-ring, which would allow me to still be able to ;; easily access it in case I kill (cut or copy) something else ;; inside Emacs before yanking (pasting) what I'd originally ;; intended to. (save-interprogram-paste-before-kill t) :config (column-number-mode 1) (line-number-mode 1)) (use-package savehist ;; Save minibuffer history. :defer 0.2 :config (savehist-mode 1) (add-to-list 'savehist-additional-variables 'kill-ring)) (use-package saveplace ;; Automatically save place in files. :defer 0.2 :config (save-place-mode 1)) (use-package flyspell :defer t :custom (flyspell-mode-line-string " fly") :hook ((text-mode tex-mode) . flyspell-mode)) (use-package abbrev :delight :hook (text-mode . abbrev-mode)) (use-package eww :bind ("C-c e w" . eww) :custom (eww-download-directory (file-name-as-directory (getenv "XDG_DOWNLOAD_DIR")))) (use-package display-fill-column-indicator :defer 0.2 :config (global-display-fill-column-indicator-mode 1)) (use-package completion-preview ;; :if (package-installed-p 'completion-preview) :if (version<= "30" emacs-version) :bind (:map completion-preview-active-mode-map ("M-n" . completion-preview-next-candidate) ("M-p" . completion-preview-prev-candidate) ("M-i" . completion-preview-insert)) :hook ((prog-mode text-mode comint-mode) . completion-preview-mode)) (use-package version :bind ("C-c e v" . emacs-version)) (use-package bandali-utils :bind ("C-c d" . b/duplicate-line-or-region) ("C-c j" . b/join-line-top) ("C-S-j" . b/join-line-top) ("C-c s c" . b/*scratch*) ("C-c v" . b/invert-default-face) ("C-c q" . b/unfill-paragraph-or-region) (:map text-mode-map ("M-RET" . b/insert-asterism))) (provide 'bandali-essentials) ;;; bandali-essentials.el ends here