Move dired, eshell, ibuffer, ido, and ivy to separate files in lisp/
[~bandali/configs] / init.el
diff --git a/init.el b/init.el
index f8f755a..184ae64 100644 (file)
--- a/init.el
+++ b/init.el
@@ -19,8 +19,7 @@
 
 ;; GNU Emacs configuration of Amin Bandali, computer scientist,
 ;; Free Software activist, and GNU maintainer & webmaster.  Packages
-;; are installed through GNU Guix for a fully reproducible setup.
-;; Before switching to Guix, I used straight.el, and before that Borg.
+;; are installed through using Borg for a fully reproducible setup.
 
 ;; Over the years, I've taken inspiration from configurations of many
 ;; great people.  Some that I can remember off the top of my head are:
 \f
 ;;; Package management
 
-;; No package.el  (for emacs 26 and before)
-(when (version< emacs-version "27")
-  (setq package-enable-at-startup nil)
-  ;; (package-initialize)
-  )
-;; for emacs 27 and later, we use early-init.el.  see
-;; https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b
-
 (progn ;   `borg'
   (add-to-list 'load-path
                (expand-file-name "lib/borg" user-emacs-directory))
 ;; start up emacs server.  see
 ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server
 (use-package server
-  :defer 0.4
+  :defer 0.5
   :config (or (server-running-p) (server-mode)))
 
 \f
 ;;; Useful utilities
 
-;; useful libraries
-(require 'cl-lib)
-(require 'subr-x)
-
 (defmacro b/setq-every (value &rest vars)
   "Set all the variables from VARS to value VALUE."
   (declare (indent defun) (debug t))
 (defun b/add-elisp-section ()
   (interactive)
   (insert "\n")
-  (previous-line)
+  (forward-line -1)
   (insert "\n\f\n;;; "))
 
 ;; (defvar b/fill-column 47
@@ -279,7 +266,7 @@ For disabling the behaviour for certain buffers and/or modes."
  indent-tabs-mode nil
  tab-width 4
  ;; cursor shape
- cursor-type 'bar)
+ cursor-type t)
 
 ;; unicode support
 (comment
@@ -377,7 +364,7 @@ For disabling the behaviour for certain buffers and/or modes."
   (display-time-mode)
   :custom
   (display-time-default-load-average nil)
-  (display-time-format "%a %b %-e %-l:%M%P")
+  (display-time-format " %a %b %-e %-l:%M%P")
   (display-time-mail-icon '(image :type xpm :file "gnus/gnus-pointer.xpm" :ascent center))
   (display-time-use-mail-icon t))
 
@@ -386,7 +373,7 @@ For disabling the behaviour for certain buffers and/or modes."
   :config
   (display-battery-mode)
   :custom
-  (battery-mode-line-format " %p%% %t"))
+  (battery-mode-line-format "%p%% %t"))
 
 (use-package fringe
   :demand
@@ -473,9 +460,7 @@ For disabling the behaviour for certain buffers and/or modes."
   :config
   ;; ask for GPG passphrase in minibuffer
   ;; this will fail if gpg>=2.1 is not available
-  (if (version< "27" emacs-version)
-      (setq epg-pinentry-mode 'loopback)
-    (setq epa-pinentry-mode 'loopback))
+  (setq epg-pinentry-mode 'loopback)
   :custom
   (epg-gpg-program (executable-find "gpg")))
 
@@ -510,6 +495,10 @@ For disabling the behaviour for certain buffers and/or modes."
  ("C-c e u" . emacs-uptime)
  ("C-c e v" . emacs-version)
 
+ ("C-c f ." . find-file)
+ ("C-c f d" . find-name-dired)
+ ("C-c f l" . find-library)
+
  ("C-c F m" . make-frame-command)
  ("C-c F d" . delete-frame)
  ("C-c F D" . server-edit)
@@ -517,6 +506,8 @@ For disabling the behaviour for certain buffers and/or modes."
  ("C-S-h C" . describe-char)
  ("C-S-h F" . describe-face)
 
+ ("C-c x"   . execute-extended-command)
+
  ("C-x k"   . b/kill-current-buffer)
  ("C-x K"   . kill-buffer)
  ("C-x s"   . save-buffer)
@@ -543,108 +534,18 @@ For disabling the behaviour for certain buffers and/or modes."
 \f
 ;;; Essential packages
 
+(add-to-list
+ 'load-path
+ (expand-file-name
+  (convert-standard-filename "lisp") user-emacs-directory))
+
 (when b/exwm-p
   (require 'bandali-exwm))
 
-(use-package org
-  :config
-  (setq org-src-tab-acts-natively t
-        org-src-preserve-indentation nil
-        org-edit-src-content-indentation 0
-        org-link-email-description-format "Email %c: %s" ; %.30s
-        org-highlight-latex-and-related '(entities)
-        org-use-speed-commands t
-        org-startup-folded 'content
-        org-catch-invisible-edits 'show-and-error
-        org-log-done 'time)
-  (when (version< org-version "9.3")
-    (setq org-email-link-description-format
-          org-link-email-description-format))
-  (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t)
-  (add-to-list 'org-modules 'org-habit)
-  :bind
-  (("C-c a o a" . org-agenda)
-   :map org-mode-map
-   ("M-L" . org-insert-last-stored-link)
-   ("M-O" . org-toggle-link-display))
-  :hook ((org-mode . org-indent-mode)
-         (org-mode . auto-fill-mode)
-         (org-mode . flyspell-mode))
-  :custom
-  (org-pretty-entities t)
-  (org-agenda-files '("~/usr/org/todos/personal.org"
-                      "~/usr/org/todos/habits.org"
-                      "~/src/git/masters-thesis/todo.org"))
-  (org-agenda-start-on-weekday 0)
-  (org-agenda-time-leading-zero t)
-  (org-habit-graph-column 44)
-  (org-latex-packages-alist '(("" "listings") ("" "color")))
-  :custom-face
-  '(org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21"))))
-  '(org-block ((t (:background "#1d1f21"))))
-  '(org-latex-and-related ((t (:foreground "#b294bb")))))
-
-(use-package ox-latex
-  :after ox
-  :config
-  (setq org-latex-listings 'listings
-        ;; org-latex-prefer-user-labels t
-        )
-  (add-to-list 'org-latex-classes
-               '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
-                 ("\\section{%s}"       . "\\section*{%s}")
-                 ("\\subsection{%s}"    . "\\subsection*{%s}")
-                 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
-                 ("\\paragraph{%s}"     . "\\paragraph*{%s}")
-                 ("\\subparagraph{%s}"  . "\\subparagraph*{%s}"))
-               t)
-  (require 'ox-beamer))
-
-(use-package ox-extra
-  :config
-  (ox-extras-activate '(latex-header-blocks ignore-headlines)))
-
-;; asynchronous tangle, using emacs-async to asynchronously tangle an
-;; org file.  closely inspired by
-;; https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles
-(with-eval-after-load 'org
-  (defvar b/show-async-tangle-results nil
-    "Keep *emacs* async buffers around for later inspection.")
-
-  (defvar b/show-async-tangle-time nil
-    "Show the time spent tangling the file.")
-
-  (defun b/async-babel-tangle ()
-    "Tangle org file asynchronously."
-    (interactive)
-    (let* ((file-tangle-start-time (current-time))
-           (file (buffer-file-name))
-           (file-nodir (file-name-nondirectory file))
-           ;; (async-quiet-switch "-q")
-           (file-noext (file-name-sans-extension file)))
-      (async-start
-       `(lambda ()
-          (require 'org)
-          (org-babel-tangle-file ,file))
-       (unless b/show-async-tangle-results
-         `(lambda (result)
-            (if result
-                (message "Tangled %s%s"
-                         ,file-nodir
-                         (if b/show-async-tangle-time
-                             (format " (%.3fs)"
-                                     (float-time (time-subtract (current-time)
-                                                                ',file-tangle-start-time)))
-                           ""))
-              (message "Tangling %s failed" ,file-nodir))))))))
-
-(add-to-list
- 'safe-local-variable-values
- '(eval add-hook 'after-save-hook #'b/async-babel-tangle 'append 'local))
+(require 'bandali-org)
 
 ;; *the* right way to do git
 (use-package magit
-  :defer 0.5
   :bind (("C-x g"   . magit-status)
          ("C-c g g" . magit-status)
          ("C-c g b" . magit-blame-addition)
@@ -679,253 +580,18 @@ For disabling the behaviour for certain buffers and/or modes."
   :custom
   (recentf-max-saved-items 2000))
 
-;; smart M-x enhancement (needed by counsel for history)
-;; (use-package smex)
-
-(bind-keys
- ("C-c f ." . find-file)
- ("C-c f d" . find-name-dired)
- ("C-c f l" . find-library)
- ;; ("C-c f r" . recentf-open-files)
- ("C-c x"   . execute-extended-command))
-
-(comment
-  (use-package ido
-    :demand
-    :bind
-    (:map ido-common-completion-map
-          ([escape] . minibuffer-keyboard-quit)
-          ("DEL"    . b/ido-backspace))
-    :config
-    (require 'delsel)
-    (defun b/ido-backspace ()
-      "Forward to `backward-delete-char'.  On error (read-only), quit."
-      (interactive)
-      (condition-case nil
-          (backward-delete-char 1)
-        (error
-         (minibuffer-keyboard-quit))))
-    (ido-mode 1)
-    (ido-everywhere 1)
-    :custom
-    (ido-enable-flex-matching t)
-    ;; (ido-enable-regexp t)
-    ;; (ido-enable-prefix t)
-    (ido-max-window-height 10)
-    (ido-use-virtual-buffers t))
-
-  (use-package ido-vertical-mode
-    :defer 0.3
-    :config
-    (ido-vertical-mode 1)
-    :custom
-    (ido-vertical-define-keys 'C-n-C-p-up-and-down)
-    (ido-vertical-show-count t))
-
-  (use-package ido-completing-read+
-    :defer 0.3
-    :after ido
-    :config
-    (ido-ubiquitous-mode 1))
-
-  (use-package crm-custom
-    :defer 0.3
-    :config
-    (crm-custom-mode 1))
-
-  (use-package icomplete
-    :defer 0.3
-    :config
-    (icomplete-mode 1)))
-
+;; needed for history for counsel
 (use-package amx
   :defer 0.3
   :config
   (amx-mode))
 
-(use-package ivy
-  :defer 0.3
-  :bind
-  (:map ivy-minibuffer-map
-   ([escape] . keyboard-escape-quit)
-   ([S-up]   . ivy-previous-history-element)
-   ([S-down] . ivy-next-history-element)
-   ("DEL"    . ivy-backward-delete-char))
-  :config
-  (setq ivy-wrap t
-        ;; ivy-height 14
-        ivy-use-virtual-buffers t
-        ivy-virtual-abbreviate 'abbreviate
-        ivy-count-format "%d/%d ")
-
-  (defvar b/ivy-ignore-buffer-modes '(magit-mode erc-mode dired-mode))
-  (defun b/ivy-ignore-buffer-p (str)
-    "Return non-nil if str names a buffer with a major mode
-derived from one of `b/ivy-ignore-buffer-modes'.
-
-This function is intended for use with `ivy-ignore-buffers'."
-    (let* ((buf (get-buffer str))
-           (mode (and buf (buffer-local-value 'major-mode buf))))
-      (and mode
-           (apply #'provided-mode-derived-p mode b/ivy-ignore-buffer-modes))))
-  (add-to-list 'ivy-ignore-buffers 'b/ivy-ignore-buffer-p)
-
-  (ivy-mode 1)
-  :custom-face
-  (ivy-minibuffer-match-face-1 ((t (:background "#eeeeee"))))
-  (ivy-minibuffer-match-face-2 ((t (:background "#e7e7e7" :weight bold))))
-  (ivy-minibuffer-match-face-3 ((t (:background "light goldenrod" :weight semi-bold))))
-  (ivy-minibuffer-match-face-4 ((t (:background "misty rose" :weight semi-bold))))
-  (ivy-current-match ((((class color) (background light))
-                       :background "#d7d7d7" :foreground "black")
-                      (((class color) (background dark))
-                       :background "#65a7e2" :foreground "black"))))
-
-(use-package swiper
-  :demand
-  :after ivy
-  :bind (("C-S-s" . swiper-isearch)))
-
-(use-package counsel
-  :demand
-  :after ivy
-  :bind (("C-c f r" . counsel-recentf)
-         :map minibuffer-local-map
-         ("C-r" . counsel-minibuffer-history))
-  :config
-  (counsel-mode 1)
-  (defalias 'locate #'counsel-locate))
-
-(comment
-(use-package eshell
-  :defer 0.5
-  :commands eshell
-  :bind ("C-c a s e" . eshell)
-  :config
-  (eval-when-compile (defvar eshell-prompt-regexp))
-  (defun b/eshell-quit-or-delete-char (arg)
-    (interactive "p")
-    (if (and (eolp) (looking-back eshell-prompt-regexp nil))
-        (eshell-life-is-too-much)
-      (delete-char arg)))
-
-  (defun b/eshell-clear ()
-    (interactive)
-    (let ((inhibit-read-only t))
-      (erase-buffer))
-    (eshell-send-input))
-
-  (defun b/eshell-setup ()
-    (make-local-variable 'company-idle-delay)
-    (defvar company-idle-delay)
-    (setq company-idle-delay nil)
-    (bind-keys :map eshell-mode-map
-               ("C-d"   . b/eshell-quit-or-delete-char)
-               ("C-S-l" . b/eshell-clear)
-               ("M-r"   . counsel-esh-history)
-               ;; ([tab]   . company-complete)
-               )
-    (if (version< "27" emacs-version)
-        (bind-keys :map eshell-hist-mode-map
-                   ("M-r" . counsel-esh-history))
-      (bind-keys :map eshell-mode-map
-                 ("M-r" . counsel-esh-history))))
+;; (require 'bandali-ido)
+(require 'bandali-ivy)
 
-  (setq
-   eshell-prompt-regexp "\\(.*\n\\)*[$#] "
-   eshell-prompt-function
-   (lambda ()
-     (concat
-      (propertize (format "%s@%s:" (user-login-name) (system-name))
-                  'face 'default)
-      (propertize (abbreviate-file-name default-directory)
-                  'face 'font-lock-comment-face)
-      (propertize "\n" 'face 'default)
-      (if (= (user-uid) 0)
-          (propertize "#" 'face 'red)
-        (propertize "$" 'face 'default))
-      (propertize " " 'face 'default))))
-
-  :hook (eshell-mode . b/eshell-setup)
-  :custom
-  (eshell-hist-ignoredups t)
-  (eshell-input-filter 'eshell-input-filter-initial-space))
+(require 'bandali-eshell)
 
-(use-package ibuffer
-  :bind
-  (("C-x C-b" . ibuffer)
-   :map ibuffer-mode-map
-   ("P"   . ibuffer-backward-filter-group)
-   ("N"   . ibuffer-forward-filter-group)
-   ("M-p" . ibuffer-do-print)
-   ("M-n" . ibuffer-do-shell-command-pipe-replace))
-  :config
-  ;; Use human readable Size column instead of original one
-  (define-ibuffer-column size-h
-    (:name "Size" :inline t)
-    (cond
-     ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
-     ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
-     ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
-     (t (format "%8d" (buffer-size)))))
-  :custom
-  (ibuffer-saved-filter-groups
-   '(("default"
-      ("dired" (mode . dired-mode))
-      ("org"   (mode . org-mode))
-      ("gnus"
-       (or
-        (mode . gnus-group-mode)
-        (mode . gnus-summary-mode)
-        (mode . gnus-article-mode)
-        ;; not really, but...
-        (mode . message-mode)))
-      ("web"
-       (or
-        ;; (mode . web-mode)
-        (mode . mhtml-mode)
-        (mode . css-mode)
-        (mode . scss-mode)
-        (mode . js2-mode)))
-      ("shell"
-       (or
-        (mode . eshell-mode)
-        (mode . shell-mode)
-        (mode . term-mode)))
-      ("programming"
-       (or
-        (mode . python-mode)
-        (mode . c-mode)
-        (mode . c++-mode)
-        (mode . java-mode)
-        (mode . emacs-lisp-mode)
-        (mode . scheme-mode)
-        (mode . haskell-mode)
-        (mode . lean-mode)
-        ;; (mode . go-mode)
-        (mode . alloy-mode)))
-      ("tex"
-       (or
-        (mode . bibtex-mode)
-        (mode . latex-mode)))
-      ("emacs"
-       (or
-        (name . "^\\*scratch\\*$")
-        (name . "^\\*Messages\\*$")))
-      ("exwm" (mode . exwm-mode))
-      ("erc" (mode . erc-mode)))))
-  (ibuffer-formats
-   '((mark modified read-only locked " "
-           (name 72 72 :left :elide)
-           " "
-           (size-h 9 -1 :right)
-           " "
-           (mode 16 16 :left :elide)
-           " " filename-and-process)
-     (mark " "
-           (name 16 -1)
-           " " filename)))
-  :hook (ibuffer . (lambda () (ibuffer-switch-to-saved-filter-groups "default"))))
+(require 'bandali-ibuffer)
 
 (use-package outline
   :disabled
@@ -945,58 +611,11 @@ This function is intended for use with `ivy-ignore-buffers'."
    ("h"   . outline-hide-subtree)
    ("s"   . outline-show-subtree)))
 
+(comment
 (use-package ls-lisp
   :custom (ls-lisp-dirs-first t))
 
-(use-package dired
-  :config
-  (setq dired-dwim-target t
-        dired-listing-switches "-alh"
-        ls-lisp-use-insert-directory-program nil)
-
-  ;; easily diff 2 marked files
-  ;; https://oremacs.com/2017/03/18/dired-ediff/
-  (defun dired-ediff-files ()
-    (interactive)
-    (require 'dired-aux)
-    (defvar ediff-after-quit-hook-internal)
-    (let ((files (dired-get-marked-files))
-          (wnd (current-window-configuration)))
-      (if (<= (length files) 2)
-          (let ((file1 (car files))
-                (file2 (if (cdr files)
-                           (cadr files)
-                         (read-file-name
-                          "file: "
-                          (dired-dwim-target-directory)))))
-            (if (file-newer-than-file-p file1 file2)
-                (ediff-files file2 file1)
-              (ediff-files file1 file2))
-            (add-hook 'ediff-after-quit-hook-internal
-                      (lambda ()
-                        (setq ediff-after-quit-hook-internal nil)
-                        (set-window-configuration wnd))))
-        (error "no more than 2 files should be marked"))))
-
-  (require 'dired-x)
-  (setq dired-guess-shell-alist-user
-        '(("\\.pdf\\'"  "evince" "zathura" "okular")
-          ("\\.doc\\'"  "libreoffice")
-          ("\\.docx\\'" "libreoffice")
-          ("\\.ppt\\'"  "libreoffice")
-          ("\\.pptx\\'" "libreoffice")
-          ("\\.xls\\'"  "libreoffice")
-          ("\\.xlsx\\'" "libreoffice")
-          ("\\.flac\\'" "mpv")))
-  :bind (:map dired-mode-map
-              ("b"  . dired-up-directory)
-              ("E"  . dired-ediff-files)
-              ("e"  . dired-toggle-read-only)
-              ("\\" . dired-hide-details-mode)
-              ("z"  . (lambda ()
-                        (interactive)
-                        (b/dired-start-process "zathura"))))
-  :hook (dired-mode . dired-hide-details-mode))
+(require 'bandali-dired)
 
 (use-package help
   :config