Moving to Doom Emacs!

This commit is contained in:
Derek Taylor
2019-12-16 20:21:19 -06:00
parent d9f2f456f1
commit d4b4c33550
683 changed files with 51877 additions and 100 deletions

View File

@@ -0,0 +1,43 @@
#+TITLE: emacs/dired
#+DATE: May 27, 2018
#+SINCE: v2.0
#+STARTUP: inlineimages
* Table of Contents :TOC_3:noexport:
- [[#description][Description]]
- [[#module-flags][Module Flags]]
- [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
- [[#keybindings][Keybindings]]
* Description
This module provides configuration for dired.
** Module Flags
+ =+ranger= Enables dired to be more like [[https://github.com/ranger/ranger][ranger]].
+ =+icons= Enables the display of fancy icons depending on file types in dired
buffers.
** Plugins
+ [[https://github.com/purcell/diredfl][diredfl]]
+ [[https://github.com/stsquad/dired-rsync][dired-rsync]]
+ [[https://github.com/dgutov/diff-hl/][diff-hl]]
+ [[https://github.com/yqrashawn/fd-dired][fd-dired]]
+ =+ranger=
+ [[https://github.com/ralesi/ranger.el][ranger]]
+ =+icons=
+ [[https://github.com/jtbm37/all-the-icons-dired][all-the-icons-dired]]
* Prerequisites
This module has no prerequisites *except on BSDs* where =GNU ls= (~gls~) is
needed for it to work properly (Doom doctor will notify you if it is missing).
* Keybindings
| Keybind | Description |
|-----------+------------------------------|
| =SPC f d= | Find directory with dired |
| =q= | Exit dired buffer |
| =C-c C-r= | Run =dired-rsync= |
| =C-c C-e= | Rename entries with =wdired= |
Other keybindings can be found on the official [[https://www.gnu.org/software/emacs/refcards/pdf/dired-ref.pdf][Dired reference card]].

View File

@@ -0,0 +1,15 @@
;;; emacs/dired/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +dired/quit-all ()
"Kill all `dired-mode' buffers."
(interactive)
(mapc #'kill-buffer (doom-buffers-in-mode 'dired-mode))
(message "Killed all dired buffers"))
;;;###autoload
(defun +dired-enable-git-info-h ()
"Enable `dired-git-info-mode' in git repos."
(and (not (file-remote-p default-directory))
(locate-dominating-file "." ".git")
(dired-git-info-mode 1)))

View File

@@ -0,0 +1,196 @@
;;; tools/dired/config.el -*- lexical-binding: t; -*-
(use-package! dired
:commands dired-jump
:init
(setq ;; Always copy/delete recursively
dired-recursive-copies 'always
dired-recursive-deletes 'top
;; Instantly revert Dired buffers on re-visiting them, with no message.
;; (A message is shown if insta-revert is either disabled or determined
;; dynamically by setting this variable to a function.)
dired-auto-revert-buffer t
;; Auto refresh dired, but be quiet about it
dired-hide-details-hide-symlink-targets nil
;; make dired suggest a target for moving/copying intelligently
dired-dwim-target t
;; files
image-dired-dir (concat doom-cache-dir "image-dired/")
image-dired-db-file (concat image-dired-dir "db.el")
image-dired-gallery-dir (concat image-dired-dir "gallery/")
image-dired-temp-image-file (concat image-dired-dir "temp-image")
image-dired-temp-rotate-image-file (concat image-dired-dir "temp-rotate-image"))
:config
(let ((args (list "-aBhl" "--group-directories-first")))
(when IS-BSD
;; Use GNU ls as `gls' from `coreutils' if available. Add `(setq
;; dired-use-ls-dired nil)' to your config to suppress the Dired warning
;; when not using GNU ls.
(if-let (gls (executable-find "gls"))
(setq insert-directory-program gls)
;; BSD ls doesn't support --group-directories-first
(setq args (delete "--group-directories-first" args))))
(setq dired-listing-switches (string-join args " ")))
(add-hook! 'dired-mode-hook
(defun +dired-disable-gnu-ls-flags-in-tramp-buffers-h ()
"Fix #1703: dired over TRAMP displays a blank screen.
This is because there's no guarantee the remote system has GNU ls, which is the
only variant that supports --group-directories-first."
(when (file-remote-p default-directory)
(setq-local dired-listing-switches
(string-join
(split-string dired-listing-switches
"--group-directories-first")
" ")))))
;; Don't complain about this command being disabled when we use it
(put 'dired-find-alternate-file 'disabled nil)
(map! :map dired-mode-map
;; Kill all dired buffers on q
:ng "q" #'+dired/quit-all
;; To be consistent with ivy/helm+wgrep integration
"C-c C-e" #'wdired-change-to-wdired-mode))
(use-package! dired-rsync
:general (dired-mode-map "C-c C-r" #'dired-rsync))
(use-package! diredfl
:hook (dired-mode . diredfl-mode))
(use-package! diff-hl
:hook (dired-mode . diff-hl-dired-mode)
:hook (magit-post-refresh . diff-hl-magit-post-refresh)
:config
;; use margin instead of fringe
(diff-hl-margin-mode))
(use-package! ranger
:when (featurep! +ranger)
:after dired
:init
;; set up image-dired to allow picture resize
(setq image-dired-dir (concat doom-cache-dir "image-dir")
ranger-override-dired t)
:config
(unless (file-directory-p image-dired-dir)
(make-directory image-dired-dir))
(set-popup-rule! "^\\*ranger" :ignore t)
(defadvice! +dired--cleanup-header-line-a ()
"Ranger fails to clean up `header-line-format' when it is closed, so..."
:before #'ranger-revert
(dolist (buffer (buffer-list))
(when (buffer-live-p buffer)
(with-current-buffer buffer
(when (equal header-line-format '(:eval (ranger-header-line)))
(setq header-line-format nil))))))
(defadvice! +dired--cleanup-mouse1-bind-a ()
"Ranger binds an anonymous function to mouse-1 after previewing a buffer
that prevents the user from escaping the window with the mouse. This command is
never cleaned up if the buffer already existed before ranger was initialized, so
we have to clean it up ourselves."
:after #'ranger-setup-preview
(when (window-live-p ranger-preview-window)
(with-current-buffer (window-buffer ranger-preview-window)
(local-unset-key [mouse-1]))))
(setq ranger-cleanup-on-disable t
ranger-excluded-extensions '("mkv" "iso" "mp4")
ranger-deer-show-details t
ranger-max-preview-size 10
ranger-show-literal nil
ranger-hide-cursor nil))
(use-package! all-the-icons-dired
:when (featurep! +icons)
:hook (dired-mode . all-the-icons-dired-mode)
:config
;; HACK Fixes #1929: icons break file renaming in Emacs 27+, because the icon
;; is considered part of the filename, so we disable icons while we're in
;; wdired-mode.
(when EMACS27+
(defvar +wdired-icons-enabled -1)
(defadvice! +dired-disable-icons-in-wdired-mode-a (&rest _)
:before #'+wdired-before-start-advice
(setq-local +wdired-icons-enabled (if all-the-icons-dired-mode 1 -1))
(when all-the-icons-dired-mode
(all-the-icons-dired-mode -1)))
(defadvice! +dired-restore-icons-after-wdired-mode-a (&rest _)
:after #'+wdired-after-finish-advice
(all-the-icons-dired-mode +wdired-icons-enabled))))
(use-package! dired-x
:unless (featurep! +ranger)
:hook (dired-mode . dired-omit-mode)
:config
(setq dired-omit-verbose nil
dired-omit-files
(concat dired-omit-files
"\\|^.DS_Store\\'"
"\\|^.project\\(?:ile\\)?\\'"
"\\|^.\\(svn\\|git\\)\\'"
"\\|^.ccls-cache\\'"
"\\|\\(?:\\.js\\)?\\.meta\\'"
"\\|\\.\\(?:elc\\|o\\|pyo\\|swp\\|class\\)\\'"))
;; Disable the prompt about whether I want to kill the Dired buffer for a
;; deleted directory. Of course I do!
(setq dired-clean-confirm-killing-deleted-buffers nil)
;; Let OS decide how to open certain files
(when-let (cmd (cond (IS-MAC "open")
(IS-LINUX "xdg-open")
(IS-WINDOWS "start")))
(setq dired-guess-shell-alist-user
`(("\\.\\(?:docx\\|pdf\\|djvu\\|eps\\)\\'" ,cmd)
("\\.\\(?:jpe?g\\|png\\|gif\\|xpm\\)\\'" ,cmd)
("\\.\\(?:xcf\\)\\'" ,cmd)
("\\.csv\\'" ,cmd)
("\\.tex\\'" ,cmd)
("\\.\\(?:mp4\\|mkv\\|avi\\|flv\\|rm\\|rmvb\\|ogv\\)\\(?:\\.part\\)?\\'" ,cmd)
("\\.\\(?:mp3\\|flac\\)\\'" ,cmd)
("\\.html?\\'" ,cmd)
("\\.md\\'" ,cmd))))
(map! :map dired-mode-map
:localleader
"h" #'dired-omit-mode))
(use-package! fd-dired
:when (executable-find doom-projectile-fd-binary)
:defer t
:init
(global-set-key [remap find-dired] #'fd-dired)
(set-popup-rule! "^\\*F\\(?:d\\|ind\\)\\*$" :ignore t))
;;;###package dired-git-info
(map! :after dired
:map (dired-mode-map ranger-mode-map)
:ng ")" #'dired-git-info-mode)
(after! wdired
;; Temporarily disable `dired-git-info-mode' when entering wdired, due to
;; reported incompatibilities.
(defvar +dired--git-info-p nil)
(defadvice! +dired--disable-git-info-a (&rest _)
:before #'wdired-change-to-wdired-mode
(setq +dired--git-info-p (bound-and-true-p dired-git-info-mode))
(when +dired--git-info-p
(dired-git-info-mode -1)))
(defadvice! +dired--reactivate-git-info-a (&rest _)
:after '(wdired-exit
wdired-abort-changes
wdired-finish-edit)
(when +dired--git-info-p
(dired-git-info-mode +1))))

View File

@@ -0,0 +1,4 @@
;;; emacs/dired/doctor.el -*- lexical-binding: t; -*-
(when (and IS-BSD (not (executable-find "gls")))
(warn! "Cannot find gls (GNU ls). This may cause issues with dired"))

View File

@@ -0,0 +1,12 @@
;; -*- no-byte-compile: t; -*-
;;; emacs/dired/packages.el
(package! diredfl)
(package! dired-git-info)
(package! diff-hl)
(package! dired-rsync)
(when (featurep! +ranger)
(package! ranger))
(when (featurep! +icons)
(package! all-the-icons-dired))
(package! fd-dired)

View File

@@ -0,0 +1,26 @@
;;; emacs/electric/autoload.el -*- lexical-binding: t; -*-
;;;###autodef
(defun set-electric! (modes &rest plist)
"Declare that WORDS (list of strings) or CHARS (lists of chars) should trigger
electric indentation.
Enables `electric-indent-local-mode' in MODES.
\(fn MODES &key WORDS CHARS)"
(declare (indent defun))
(dolist (mode (doom-enlist modes))
(let ((hook (intern (format "%s-hook" mode)))
(fn (intern (format "+electric|init-%s" mode))))
(cond ((null (car-safe plist))
(remove-hook hook fn)
(unintern fn nil))
((fset fn
(lambda ()
(when (eq major-mode mode)
(setq-local electric-indent-inhibit nil)
(cl-destructuring-bind (&key chars words) plist
(electric-indent-local-mode +1)
(if chars (setq electric-indent-chars chars))
(if words (setq +electric-indent-words words))))))
(add-hook hook fn))))))

View File

@@ -0,0 +1,18 @@
;;; emacs/electric/config.el -*- lexical-binding: t; -*-
;; Smarter, keyword-based electric-indent
(defvar-local +electric-indent-words '()
"The list of electric words. Typing these will trigger reindentation of the
current line.")
;;
(after! electric
(setq-default electric-indent-chars '(?\n ?\^?))
(add-hook! 'electric-indent-functions
(defun +electric-indent-char-fn (_c)
(when (and (eolp) +electric-indent-words)
(save-excursion
(backward-word)
(looking-at-p (concat "\\<" (regexp-opt +electric-indent-words))))))))

View File

@@ -0,0 +1,36 @@
#+TITLE: emacs/ibuffer
#+DATE: October 20, 2019
#+SINCE: v2.1.0
#+STARTUP: inlineimages
* Table of Contents :TOC_3:noexport:
- [[#description][Description]]
- [[#module-flags][Module Flags]]
- [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
- [[#features][Features]]
- [[#configuration][Configuration]]
- [[#troubleshooting][Troubleshooting]]
* Description
This module augments ibuffer.
+ Adds project-based grouping of buffers
+ Support for file-type icons
+ Uses human-readable file-size
** Module Flags
+ =+icons= Enables filetype icons for buffers
** Plugins
+ [[https://github.com/purcell/ibuffer-projectile][ibuffer-projectile]]
+ [[https://github.com/purcell/ibuffer-vc][ibuffer-vc]]
* Prerequisites
This module has no prereqisites.
* TODO Features
* TODO Configuration
* TODO Troubleshooting

View File

@@ -0,0 +1,68 @@
;;; emacs/ibuffer/config.el -*- lexical-binding: t; -*-
(after! ibuffer
(set-popup-rule! "^\\*Ibuffer\\*$" :ignore t)
(setq ibuffer-show-empty-filter-groups nil
ibuffer-filter-group-name-face '(:inherit (success bold))
ibuffer-formats
`((mark modified read-only locked
,@(if (featurep! +icons)
`(;; Here you may adjust by replacing :right with :center
;; or :left According to taste, if you want the icon
;; further from the name
" " (icon 2 2 :left :elide)
,(propertize " " 'display `(space :align-to 8)))
'(" "))
(name 18 18 :left :elide)
" " (size 9 -1 :right)
" " (mode 16 16 :left :elide)
,@(when (require 'ibuffer-vc nil t)
'(" " (vc-status 12 :left)))
" " filename-and-process)
(mark " " (name 16 -1) " " filename)))
;; Display buffer icons on GUI
(define-ibuffer-column icon (:name " ")
(let ((icon (if (and (buffer-file-name)
(all-the-icons-auto-mode-match?))
(all-the-icons-icon-for-file (file-name-nondirectory (buffer-file-name)) :v-adjust -0.05)
(all-the-icons-icon-for-mode major-mode :v-adjust -0.05))))
(if (symbolp icon)
(setq icon (all-the-icons-faicon "file-o" :face 'all-the-icons-dsilver :height 0.8 :v-adjust 0.0))
icon)))
;; Redefine size column to display human readable size
(define-ibuffer-column size
(:name "Size"
:inline t
:header-mouse-map ibuffer-size-header-map)
(file-size-human-readable (buffer-size)))
(when (featurep! :completion ivy)
(defadvice! +ibuffer-use-counsel-maybe-a (_file &optional _wildcards)
"Use `counsel-find-file' instead of `find-file'."
:override #'ibuffer-find-file
(interactive)
(counsel-find-file
(let ((buf (ibuffer-current-buffer)))
(if (buffer-live-p buf)
(with-current-buffer buf
default-directory)
default-directory)))))
(map! :map ibuffer-mode-map :n "q" #'kill-current-buffer))
(use-package! ibuffer-projectile
;; Group ibuffer's list by project root
:hook (ibuffer . ibuffer-projectile-set-filter-groups)
:config
(setq ibuffer-projectile-prefix
(if (featurep! +icons)
(concat (all-the-icons-octicon
"file-directory"
:face ibuffer-filter-group-name-face
:v-adjust -0.05)
" ")
"Project: ")))

View File

@@ -0,0 +1,5 @@
;; -*- no-byte-compile: t; -*-
;;; emacs/ibuffer/packages.el
(package! ibuffer-projectile)
(package! ibuffer-vc)

View File

@@ -0,0 +1,8 @@
;;; emacs/vc/autoload/evil.el -*- lexical-binding: t; -*-
;;;###if (featurep! :editor evil)
;;;###autoload (autoload '+vc:git-browse "emacs/vc/autoload/evil" nil t)
(evil-define-command +vc:git-browse (bang)
"Ex interface to `+vc/git-browse-region-or-line'."
(interactive "<!>")
(+vc/git-browse-region-or-line bang))

View File

@@ -0,0 +1,41 @@
;;; emacs/vc/autoload/hydra.el -*- lexical-binding: t; -*-
;;;###if (featurep! :ui hydra)
;;;###autoload (autoload '+vc/smerge-hydra/body "emacs/vc/autoload/hydra" nil t)
(defhydra +vc/smerge-hydra (:hint nil
:pre (if (not smerge-mode) (smerge-mode 1))
;; Disable `smerge-mode' when quitting hydra if
;; no merge conflicts remain.
:post (smerge-auto-leave))
"
[smerge]
Movement Keep Diff Other
╭─────────────────────────────────────────────────────────╯
^_g_^ [_b_] base [_<_] upper/base [_C_] Combine
^_C-k_^ [_u_] upper [_=_] upper/lower [_r_] resolve
^_k_ ↑^ [_l_] lower [_>_] base/lower [_R_] remove
^_j_ ↓^ [_a_] all [_H_] hightlight
^_C-j_^ [_RET_] current [_E_] ediff ╭──────────
^_G_^ │ [_q_] quit
"
("g" (progn (goto-char (point-min)) (smerge-next)))
("G" (progn (goto-char (point-max)) (smerge-prev)))
("C-j" smerge-next)
("C-k" smerge-prev)
("j" next-line)
("k" previous-line)
("b" smerge-keep-base)
("u" smerge-keep-upper)
("l" smerge-keep-lower)
("a" smerge-keep-all)
("RET" smerge-keep-current)
("\C-m" smerge-keep-current)
("<" smerge-diff-base-upper)
("=" smerge-diff-upper-lower)
(">" smerge-diff-base-lower)
("H" smerge-refine)
("E" smerge-ediff)
("C" smerge-combine-with-next)
("r" smerge-resolve)
("R" smerge-kill-current)
("q" nil :color blue))

View File

@@ -0,0 +1,43 @@
;;; emacs/vc/autoload/vc.el -*- lexical-binding: t; -*-
(autoload 'browse-at-remote--file-url "browse-at-remote")
;;;###autoload
(defun +vc/browse-at-remote-file-or-region ()
"Open the current file at remote in your browser.
If a selection is active, highlight them. Otherwise omits the #L<N> suffix in
the URL."
(interactive)
(if (or (use-region-p)
(ignore-errors (evil-visual-state-p)))
(browse-at-remote)
(browse-url (browse-at-remote--file-url (buffer-file-name)))))
;;;###autoload
(defun +vc/browse-at-remote-kill-file-or-region ()
"Copy the current file's remote URL to your clipboard.
If a selection is active, highlight them. Otherwise omits the #L<N> suffix in
the URL."
(interactive)
(if (or (use-region-p)
(ignore-errors (evil-visual-state-p)))
(browse-at-remote-kill)
(kill-new (browse-at-remote--file-url (buffer-file-name)))))
(defun +vc--remote-homepage ()
(or (let ((url (browse-at-remote--remote-ref)))
(cdr (browse-at-remote--get-url-from-remote (car url))))
(user-error "Can't find homepage for current project")))
;;;###autoload
(defun +vc/browse-at-remote-homepage ()
"Open homepage for current project in browser."
(interactive)
(browse-url (+vc--remote-homepage)))
;;;###autoload
(defun +vc/browse-at-remote-kill-homepage ()
"Copy homepage URL of current project to clipboard."
(interactive)
(kill-new (+vc--remote-homepage)))

View File

@@ -0,0 +1,73 @@
;;; emacs/vc/config.el -*- lexical-binding: t; -*-
(when IS-WINDOWS
(setenv "GIT_ASKPASS" "git-gui--askpass"))
(after! vc-annotate
(set-popup-rules!
'(("^\\vc-d" :select nil) ; *vc-diff*
("^\\vc-c" :select t))) ; *vc-change-log*
(set-evil-initial-state!
'(vc-annotate-mode vc-git-log-view-mode)
'normal)
;; Clean up after itself
(define-key vc-annotate-mode-map [remap quit-window] #'kill-current-buffer))
(after! git-timemachine
;; Sometimes I forget `git-timemachine' is enabled in a buffer, so instead of
;; showing revision details in the minibuffer, show them in
;; `header-line-format', which has better visibility.
(setq git-timemachine-show-minibuffer-details t)
(defadvice! +vc-update-header-line-a (revision)
"Show revision details in the header-line, instead of the minibuffer.
Sometimes I forget `git-timemachine' is enabled in a buffer. Putting revision
info in the `header-line-format' is a good indication."
:override #'git-timemachine--show-minibuffer-details
(let* ((date-relative (nth 3 revision))
(date-full (nth 4 revision))
(author (if git-timemachine-show-author (concat (nth 6 revision) ": ") ""))
(sha-or-subject (if (eq git-timemachine-minibuffer-detail 'commit) (car revision) (nth 5 revision))))
(setq header-line-format
(format "%s%s [%s (%s)]"
(propertize author 'face 'git-timemachine-minibuffer-author-face)
(propertize sha-or-subject 'face 'git-timemachine-minibuffer-detail-face)
date-full date-relative))))
(after! evil
;; rehash evil keybindings so they are recognized
(add-hook 'git-timemachine-mode-hook #'evil-normalize-keymaps))
(when (featurep! :tools magit)
(add-transient-hook! #'git-timemachine-blame (require 'magit-blame)))
(map! :map git-timemachine-mode-map
:n "C-p" #'git-timemachine-show-previous-revision
:n "C-n" #'git-timemachine-show-next-revision
:n "gb" #'git-timemachine-blame
:n "gtc" #'git-timemachine-show-commit))
(use-package! git-commit
:after-call after-find-file
:config
(global-git-commit-mode +1)
(set-yas-minor-mode! 'git-commit-mode)
;; Enforce git commit conventions.
;; See https://chris.beams.io/posts/git-commit/
(setq git-commit-summary-max-length 50
git-commit-style-convention-checks '(overlong-summary-line non-empty-second-line))
(setq-hook! 'git-commit-mode-hook fill-column 72)
(add-hook! 'git-commit-setup-hook
(defun +vc-start-in-insert-state-maybe-h ()
"Start git-commit-mode in insert state if in a blank commit message,
otherwise in default state."
(when (and (bound-and-true-p evil-mode)
(bobp) (eolp))
(evil-insert-state)))))

View File

@@ -0,0 +1,11 @@
;; -*- no-byte-compile: t; -*-
;;; emacs/vc/packages.el
(package! vc :built-in t)
(package! vc-annotate :built-in t)
(package! smerge-mode :built-in t)
(package! browse-at-remote)
(package! git-timemachine)
(package! gitconfig-mode)
(package! gitignore-mode)