957 lines
30 KiB
Org Mode
957 lines
30 KiB
Org Mode
#+TITLE: Emacs Config
|
|
#+AUTHOR: Joseph Ferano
|
|
#+PROPERTY: header-args:emacs-lisp :tangle ./init.el
|
|
#+STARTUP: overview
|
|
#+TOC: true
|
|
|
|
** Early Init
|
|
|
|
*** Garbage Collection
|
|
|
|
The default Garbage Collector is triggered at 800 KB, way too conservative, let's bump to 512 MB.
|
|
Garbage collection is a big contributor to startup times. This fends it off, then is reset later by enabling `gcmh-mode'. Not resetting it will cause stuttering/freezes.
|
|
|
|
#+begin_src emacs-lisp :tangle ./early-init.el
|
|
;; -*- lexical-binding: t -*-
|
|
(defvar default-file-name-handler-alist file-name-handler-alist)
|
|
(setq file-name-handler-alist nil)
|
|
(setq gc-cons-threshold (expt 2 32))
|
|
|
|
(add-hook 'emacs-startup-hook
|
|
(lambda ()
|
|
"Restore defalut values after init."
|
|
(setq file-name-handler-alist default-file-name-handler-alist)
|
|
(if (boundp 'after-focus-change-function)
|
|
(add-function :after after-focus-change-function
|
|
(lambda ()
|
|
(unless (frame-focus-state)
|
|
(garbage-collect))))
|
|
(add-hook 'focus-out-hook 'garbage-collect))))
|
|
|
|
(setq native-comp-async-report-warnings-errors nil)
|
|
(setq native-comp-deferred-compilation t)
|
|
#+end_src
|
|
|
|
Disabling these classic visual options during early-init seems to net a 0.04 ms boost in init time
|
|
|
|
#+begin_src emacs-lisp :tangle ./early-init.el
|
|
(setq max-specpdl-size 1200)
|
|
(setq max-lisp-eval-depth 800)
|
|
|
|
(scroll-bar-mode -1)
|
|
(tool-bar-mode -1)
|
|
(menu-bar-mode -1)
|
|
(tooltip-mode -1)
|
|
#+end_src
|
|
|
|
*** Straight.el Prep
|
|
|
|
Disable package.el, since we will be using straight.el. According to the straight.el
|
|
documentation;
|
|
|
|
#+BEGIN_QUOTE
|
|
While it is technically possible to use both package.el and straight.el at the same time, there is no real reason to, and it might result in oddities like packages getting loaded more than once.
|
|
#+END_QUOTE
|
|
|
|
Either way, if you need to quickly install a package for testing, you can just run
|
|
=(straight-use-package)= interactively.
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle ./early-init.el
|
|
(setq package-enable-at-startup nil)
|
|
#+END_SRC
|
|
|
|
*** Enhancements
|
|
Prioritize old byte-compiled source files over newer sources. It saves us a little IO time to skip all the mtime checks on each lookup.
|
|
|
|
#+begin_src emacs-lisp :tangle ./early-init.el
|
|
(setq load-prefer-newer nil)
|
|
|
|
(setq safe-local-variable-values
|
|
'((eval add-hook 'after-save-hook
|
|
'(lambda nil
|
|
(org-babel-tangle))
|
|
nil t)))
|
|
|
|
#+end_src
|
|
|
|
*** UTF-8 Support
|
|
#+begin_src emacs-lisp :tangle ./early-init.el
|
|
(setq default-input-method nil)
|
|
(setq utf-translate-cjk-mode nil) ; disable CJK coding/encoding (Chinese/Japanese/Korean characters)
|
|
(set-language-environment 'utf-8)
|
|
(set-keyboard-coding-system 'utf-8-mac) ; For old Carbon emacs on OS X only
|
|
(setq locale-coding-system 'utf-8)
|
|
(set-default-coding-systems 'utf-8)
|
|
(set-terminal-coding-system 'utf-8)
|
|
(set-selection-coding-system 'utf-8)
|
|
(prefer-coding-system 'utf-8)
|
|
;;; early-init.el ends here
|
|
#+end_src
|
|
|
|
** Straight.el
|
|
|
|
For now, use [[https://github.com/radian-software/straight.el][straight.el]] until [[https://github.com/progfolio/elpaca
|
|
][elpaca]] is ready for production use.
|
|
|
|
Then bootstrap
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar bootstrap-version)
|
|
(let ((bootstrap-file
|
|
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
|
|
(bootstrap-version 6))
|
|
(unless (file-exists-p bootstrap-file)
|
|
(with-current-buffer
|
|
(url-retrieve-synchronously
|
|
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
|
|
'silent 'inhibit-cookies)
|
|
(goto-char (point-max))
|
|
(eval-print-last-sexp)))
|
|
(load bootstrap-file nil 'nomessage))
|
|
#+END_SRC
|
|
|
|
** Benchmarking
|
|
|
|
This is commented out since it adds ever so slightly to init time, but keep it around in case we
|
|
need to benchmark slow init times later.
|
|
|
|
#+begin_src emacs-lisp :tangle no
|
|
(straight-use-package 'benchmark-init)
|
|
(require 'benchmark-init)
|
|
(add-hook 'after-init-hook 'benchmark-init/deactivate)
|
|
#+end_src
|
|
|
|
** Misc Stuff
|
|
|
|
#+begin_SRC emacs-lisp
|
|
(setq default-directory "/home/joe/")
|
|
(setq vc-follow-symlinks t) ; Visit real file when editing a symlink without prompting.
|
|
(global-auto-revert-mode t) ; Revert buffer's file when the file changes on disk
|
|
|
|
;; (setq confirm-kill-emacs 'y-or-n-p)
|
|
|
|
(require 'recentf)
|
|
(setq recentf-auto-cleanup 'never)
|
|
(setq recentf-keep '(file-remote-p file-readable-p))
|
|
|
|
#+end_src
|
|
|
|
Don't let emacs add customised settings to init.el, which in our case is worse since we have a
|
|
literate file.
|
|
|
|
#+begin_src emacs-lisp
|
|
|
|
#+end_src
|
|
|
|
This avoids those annoying *#backup#* files that get added and eventually slow down loading the file again.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq auto-save-default nil)
|
|
(setq create-lockfiles nil)
|
|
#+end_src
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq use-dialog-box nil)
|
|
(fset 'yes-or-no-p 'y-or-n-p)
|
|
(setq large-file-warning-threshold 100000000)
|
|
(setq backup-directory-alist `((".*" . ,(expand-file-name "backups" user-emacs-directory))))
|
|
(setq backup-by-copying t
|
|
delete-old-versions t
|
|
kept-new-versions 6
|
|
kept-old-versions 2
|
|
version-control t)
|
|
#+END_SRC
|
|
|
|
I don't even know how you resume from GUI mode, we'll find a use for this keybinding later on
|
|
|
|
#+begin_src emacs-lisp
|
|
(when (display-graphic-p)
|
|
(global-unset-key (kbd "C-z")))
|
|
#+end_src
|
|
|
|
** Visuals
|
|
*** Dashboard
|
|
|
|
Use Dashboard.el. First load `all-the-icons` for nicer rendering
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'all-the-icons)
|
|
(straight-use-package 'dashboard)
|
|
(dashboard-setup-startup-hook)
|
|
|
|
(setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))
|
|
(setq dashboard-items '((recents . 8)
|
|
(bookmarks . 8)))
|
|
(setq dashboard-startup-banner 'logo)
|
|
(setq dashboard-center-content t)
|
|
(setq dashboard-set-file-icons t)
|
|
(setq dashboard-set-navigator t)
|
|
(setq dashboard-set-heading-icons t)
|
|
(add-hook 'dashboard-mode-hook (lambda () (setq-local line-spacing 12)))
|
|
#+end_src
|
|
|
|
*** Olivetti
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'olivetti)
|
|
(require 'olivetti)
|
|
(setq olivetti-minimum-body-width 100)
|
|
(global-set-key (kbd "C-x x o") 'olivetti-mode)
|
|
#+end_src
|
|
|
|
*** Themes
|
|
|
|
sanityinc-tomorrow-light is really good
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'doom-themes)
|
|
(straight-use-package 'color-theme-sanityinc-tomorrow)
|
|
(setq custom-safe-themes t)
|
|
#+end_src
|
|
|
|
Save the last used theme when exiting emacs and then reload it.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
|
|
(load custom-file)
|
|
|
|
(defun joe/save-current-theme ()
|
|
(customize-save-variable 'custom-enabled-themes custom-enabled-themes))
|
|
(add-hook 'kill-emacs-hook #'joe/save-current-theme)
|
|
#+end_src
|
|
|
|
|
|
*** Other
|
|
|
|
Setup other stuff
|
|
|
|
#+begin_src emacs-lisp
|
|
(add-hook 'text-mode-hook (lambda () (setq fill-column 100) (turn-on-auto-fill)))
|
|
|
|
(setq-default display-line-numbers 'relative)
|
|
(make-variable-buffer-local 'global-hl-line-mode)
|
|
|
|
(dolist (mode '( dashboard-mode-hook org-mode-hook term-mode-hook eww-mode-hook vterm-mode-hook
|
|
eshell-mode-hook dired-mode-hook shell-mode-hook magit-mode-hook compilation-mode-hook))
|
|
(add-hook mode (lambda () (display-line-numbers-mode 0))))
|
|
|
|
(set-window-margins nil 0)
|
|
(setq-default right-fringe-width 10)
|
|
(setq scroll-margin 0
|
|
scroll-conservatively 100000
|
|
scroll-preserve-screen-position 1)
|
|
|
|
(global-hl-line-mode +1)
|
|
(column-number-mode +1)
|
|
|
|
(modify-all-frames-parameters
|
|
'((right-divider-width . 5)
|
|
(internal-border-width . 12)))
|
|
|
|
(when (>= emacs-major-version 29)
|
|
(pixel-scroll-precision-mode t))
|
|
|
|
(setq inhibit-startup-screen t)
|
|
|
|
(straight-use-package 'ligature)
|
|
(global-ligature-mode)
|
|
|
|
(straight-use-package 'highlight-quoted)
|
|
(add-hook 'emacs-lisp-mode-hook 'highlight-quoted-mode)
|
|
|
|
(straight-use-package 'nano-modeline)
|
|
(nano-modeline-mode)
|
|
#+end_src
|
|
|
|
** Text
|
|
#+begin_src emacs-lisp
|
|
(set-face-attribute 'default nil :font "Fira Code Nerd Font" :height 105)
|
|
|
|
(setq-default c-basic-offset 4) ;; This is annoying
|
|
(setq-default indent-tabs-mode nil)
|
|
(setq-default tab-width 4)
|
|
(setq-default line-spacing 5)
|
|
(setq indent-line-function 'insert-tab)
|
|
(set-default 'truncate-lines nil)
|
|
(set-default 'truncate-partial-width-windows nil)
|
|
|
|
(add-hook 'before-save-hook 'whitespace-cleanup)
|
|
#+end_src
|
|
|
|
** Buffers
|
|
#+begin_src emacs-lisp
|
|
(defun joe/kill-this-buffer-or-popup ()
|
|
(interactive)
|
|
"Kill the buffer normally, but if it's a popper popup, call the popper version"
|
|
(with-current-buffer (current-buffer)
|
|
(if (or (eq popper-popup-status nil)
|
|
(eq popper-popup-status 'raised))
|
|
(kill-this-buffer)
|
|
(popper-kill-latest-popup))))
|
|
|
|
(global-set-key (kbd "C-x k") #'joe/kill-this-buffer-or-popup)
|
|
(global-set-key (kbd "C-x M-k") #'kill-buffer)
|
|
(straight-use-package 'all-the-icons-ibuffer)
|
|
(add-hook 'ibuffer-mode-hook #'all-the-icons-ibuffer-mode)
|
|
(global-set-key [remap list-buffers] 'ibuffer)
|
|
(global-set-key (kbd "C-x B") 'ibuffer)
|
|
(global-set-key (kbd "C-x b") 'consult-project-buffer)
|
|
(global-set-key (kbd "C-x C-b") 'consult-buffer)
|
|
|
|
(defun joe/switch-other-buffer ()
|
|
"Switch to other buffer"
|
|
(interactive)
|
|
(switch-to-buffer (other-buffer)))
|
|
|
|
(global-set-key (kbd "C-x l") 'joe/switch-other-buffer)
|
|
|
|
(save-place-mode t)
|
|
(setq save-place-file (expand-file-name "places" user-emacs-directory))
|
|
#+end_src
|
|
|
|
The theme of `C-x 4` bindings is that they operate on other windows, so this function matches that behavior.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun joe/kill-other-buffer-and-window ()
|
|
"Kill other buffer and window"
|
|
(interactive)
|
|
(other-window 1)
|
|
(kill-buffer-and-window))
|
|
(global-set-key (kbd "C-x 4 0") 'joe/kill-other-buffer-and-window)
|
|
(global-set-key (kbd "C-x C-0") 'kill-buffer-and-window)
|
|
|
|
#+end_src
|
|
|
|
** Windows
|
|
|
|
*** Popper
|
|
|
|
#+begin_src emacs-lisp
|
|
(add-hook 'after-init-hook (lambda () (winner-mode t)))
|
|
|
|
|
|
(straight-use-package 'rotate)
|
|
(setq joe/popper-side-toggle 'right)
|
|
|
|
(defun joe/window-split-vertical () (interactive) (set 'joe/popper-side-toggle 'right) (rotate:main-horizontal))
|
|
(defun joe/window-split-horizontal () (interactive) (set 'joe/popper-side-toggle 'below) (rotate:main-vertical))
|
|
|
|
(define-key ctl-x-4-map (kbd "|") #'joe/window-split-vertical)
|
|
(define-key ctl-x-4-map (kbd "-") #'joe/window-split-horizontal)
|
|
(straight-use-package 'popper)
|
|
(require 'popper)
|
|
(setq popper-reference-buffers
|
|
'("\\*compilation\\*" compilation-mode
|
|
"^\\*vterm\\*" vterm-mode
|
|
"^\\*Flymake.*" flymake-mode
|
|
;; "^\\*ansi-term\\*$" term-mode
|
|
("^\\*Warnings\\*$" . hide)
|
|
help-mode
|
|
helpful-mode))
|
|
|
|
(global-set-key (kbd "C-`") 'popper-toggle-latest)
|
|
(global-set-key (kbd "M-`") 'popper-cycle)
|
|
(global-set-key (kbd "C-M-`") 'popper-toggle-type)
|
|
(require 'popper-echo)
|
|
(popper-echo-mode t)
|
|
|
|
(defun joe/get-popper-dir ()
|
|
(with-current-buffer (current-buffer)
|
|
(if (or (> (window-width) 170) (eq olivetti-mode t))
|
|
joe/popper-side-toggle
|
|
'below)))
|
|
|
|
;; TODO Consider adding checks for vertical splits and only popup on right if so
|
|
(defun joe/popper-display-func (buffer &optional _alist)
|
|
(display-buffer-in-direction
|
|
buffer
|
|
`((window-height . 0.4)
|
|
(window-width . 0.4)
|
|
(direction . ,(joe/get-popper-dir))
|
|
(body-function . ,#'select-window))))
|
|
|
|
(setq popper-display-function #'joe/popper-display-func)
|
|
|
|
(popper-mode t)
|
|
#+end_src
|
|
|
|
*** Scrolling
|
|
#+begin_src emacs-lisp
|
|
(require 'pixel-scroll)
|
|
(setq pixel-scroll-precision-large-scroll-height 10.0)
|
|
(setq pixel-scroll-precision-interpolation-factor 30)
|
|
|
|
(defun joe/smooth-scroll-half-page-down ()
|
|
"Smooth scroll down"
|
|
(interactive)
|
|
(let ((half-height (/ (window-height) 2)))
|
|
(pixel-scroll-precision-interpolate (* 5 (- half-height)))))
|
|
|
|
(defun joe/smooth-scroll-half-page-up ()
|
|
"Smooth scroll down"
|
|
(interactive)
|
|
(let ((half-height (/ (window-height) 2)))
|
|
(pixel-scroll-precision-interpolate (* 5 half-height))))
|
|
|
|
(defun joe/smooth-scroll-short-down ()
|
|
"Smooth scroll down"
|
|
(interactive)
|
|
(let ((half-height (/ (window-height) 6)))
|
|
(pixel-scroll-precision-interpolate (* 5 (- half-height)))))
|
|
|
|
(defun joe/smooth-scroll-short-up ()
|
|
"Smooth scroll down"
|
|
(interactive)
|
|
(let ((half-height (/ (window-height) 6)))
|
|
(pixel-scroll-precision-interpolate (* 5 half-height))))
|
|
|
|
;; scroll-up-command
|
|
(global-set-key (kbd "C-v") #'joe/smooth-scroll-half-page-down)
|
|
(global-set-key (kbd "M-v") #'joe/smooth-scroll-half-page-up)
|
|
#+end_src
|
|
|
|
** Org Mode
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'org-bullets)
|
|
(defun joe/org-init ()
|
|
(setq org-todo-keywords '((sequence "TODO" "IN-PROGRESS" "|" "DONE" "BACKLOG")))
|
|
(setq org-agenda-files '("~/todo.org"))
|
|
|
|
(require 'org-tempo)
|
|
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
|
|
(setq org-edit-src-content-indentation 0))
|
|
(with-eval-after-load 'org (joe/org-init))
|
|
|
|
(defun joe/org-hook ()
|
|
(local-set-key (kbd "C-. C-i") 'consult-org-heading)
|
|
(org-bullets-mode)
|
|
(org-indent-mode))
|
|
(add-hook 'org-mode-hook 'joe/org-hook)
|
|
#+end_src
|
|
|
|
** VEMCO
|
|
|
|
Vertico Embark Marginalia Consult Orderless
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'all-the-icons-completion)
|
|
(straight-use-package '(vertico :files (:defaults "extensions/*") :includes (vertico-directory vertico-reverse)))
|
|
;; :bind (:map vertico-map
|
|
;; ("\M-G" . vertico-multiform-mode)
|
|
;; ("\M-e" . embark-act)))
|
|
|
|
|
|
(vertico-mode)
|
|
(straight-use-package 'vertico-posframe)
|
|
(vertico-posframe-mode t)
|
|
(setq vertico-posframe-parameters
|
|
'((left-fringe . 100)
|
|
(right-fringe . 100)))
|
|
|
|
(setq vertico-posframe-border-width 5)
|
|
(setq vertico-posframe-min-height 20)
|
|
(defun posframe-poshandler-slightly-below-top (info)
|
|
(cons (/ (- (plist-get info :parent-frame-width)
|
|
(plist-get info :posframe-width))
|
|
2)
|
|
150))
|
|
(setq vertico-posframe-poshandler #'posframe-poshandler-slightly-below-top)
|
|
|
|
(setq vertico-count 17
|
|
vertico-resize nil
|
|
vertico-cycle t)
|
|
|
|
(require 'savehist)
|
|
(savehist-mode)
|
|
(straight-use-package 'vertico-directory)
|
|
;; :bind (:map vertico-map
|
|
;; ("RET" . vertico-directory-enter)
|
|
;; ("DEL" . vertico-directory-delete-char)
|
|
;; ("M-DEL" . vertico-directory-delete-word))
|
|
;; :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
|
|
|
|
(straight-use-package 'embark)
|
|
(straight-use-package 'embark-consult)
|
|
|
|
(straight-use-package 'marginalia)
|
|
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
|
|
(marginalia-mode)
|
|
(require 'all-the-icons-completion)
|
|
(all-the-icons-completion-mode)
|
|
(all-the-icons-completion-marginalia-setup)
|
|
|
|
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)
|
|
|
|
(straight-use-package 'orderless)
|
|
(setq completion-styles '(orderless basic)
|
|
completion-category-overrides '((file (styles basic partial-completion))))
|
|
#+end_src
|
|
|
|
*** Consult
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'consult)
|
|
(global-set-key (kbd "C-. C-l") 'consult-line)
|
|
(global-set-key (kbd "C-. C-i") 'consult-imenu)
|
|
(global-set-key (kbd "C-. C-t") 'consult-theme)
|
|
(global-set-key (kbd "C-. C-r") 'consult-recent-file)
|
|
(global-set-key (kbd "C-. C-y") 'consult-yank-from-kill-ring)
|
|
#+end_src
|
|
|
|
** Avy
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'avy)
|
|
(setq avy-case-fold-search nil) ;; case sensitive makes selection easier
|
|
(define-key global-map (kbd "C-;") 'avy-goto-char-2) ;; I use this most frequently
|
|
(define-key global-map (kbd "C-'") 'avy-goto-line) ;; Consistent with ivy-avy
|
|
(define-key global-map (kbd "M-g c") 'avy-goto-char)
|
|
(define-key global-map (kbd "M-g e") 'avy-goto-word-0) ;; lots of candidates
|
|
(define-key global-map (kbd "M-g g") 'avy-goto-line) ;; digits behave like goto-line
|
|
(define-key global-map (kbd "M-g w") 'avy-goto-word-1) ;; first character of the word
|
|
(define-key global-map (kbd "M-g P") 'avy-pop-mark)
|
|
#+end_src
|
|
|
|
** Helpful
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'helpful)
|
|
(global-set-key (kbd "C-h f") #'helpful-callable)
|
|
(global-set-key (kbd "C-h v") #'helpful-variable)
|
|
(global-set-key (kbd "C-h k") #'helpful-key)
|
|
(global-set-key (kbd "C-h C-d") #'helpful-at-point)
|
|
(global-set-key (kbd "C-h F") #'helpful-function)
|
|
(global-set-key (kbd "C-h C") #'helpful-command)
|
|
#+end_src
|
|
|
|
** Dirvish/Dired
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'dirvish)
|
|
(with-eval-after-load 'dirvish
|
|
(dirvish-override-dired-mode)
|
|
(setq delete-by-moving-to-trash t)
|
|
(setq dired-dwim-target t)
|
|
(setq dirvish-reuse-session nil)
|
|
|
|
(dirvish-define-preview exa (file)
|
|
"Use `exa' to generate directory preview."
|
|
:require ("exa") ; tell Dirvish to check if we have the executable
|
|
(when (file-directory-p file) ; we only interest in directories here
|
|
`(shell . ("exa" "--icons" "--color=always" "--no-user" "-al" "--group-directories-first" ,file))))
|
|
(add-to-list 'dirvish-preview-dispatchers 'exa)
|
|
|
|
(setq dired-listing-switches "-l --sort=version --almost-all --human-readable --time-style=long-iso --group-directories-first --no-group")
|
|
(setq dirvish-preview-dispatchers (cl-substitute 'pdf-preface 'pdf dirvish-preview-dispatchers))
|
|
(setq dirvish-attributes '(all-the-icons file-size collapse subtree-state))
|
|
|
|
(defun joe/dirvish-find-directory (dir)
|
|
(interactive "FDirvish Directory:")
|
|
(dirvish-dwim dir))
|
|
|
|
|
|
(setq dirvish-quick-access-entries
|
|
'(("h" "~/" "Home")
|
|
("d" "~/Downloads/" "Downloads")
|
|
("D" "~/Documents/" "Documents")
|
|
("b" "~/Documents/Books/" "Books")
|
|
("p" "~/Development/" "Dev")
|
|
("B" "~/pCloudDrive/" "pCloud")))
|
|
|
|
(define-key dirvish-mode-map (kbd "C-c f") #'dirvish-fd)
|
|
(define-key dirvish-mode-map (kbd "a" ) #'dirvish-quick-access)
|
|
(define-key dirvish-mode-map (kbd "f" ) #'dirvish-file-info-menu)
|
|
(define-key dirvish-mode-map (kbd "y" ) #'dirvish-yank-menu)
|
|
(define-key dirvish-mode-map (kbd "N" ) #'dirvish-narrow)
|
|
(define-key dirvish-mode-map (kbd "^" ) #'dired-up-directory)
|
|
(define-key dirvish-mode-map (kbd "h" ) #'dirvish-history-jump)
|
|
(define-key dirvish-mode-map (kbd "s" ) #'dirvish-quicksort)
|
|
(define-key dirvish-mode-map (kbd "v" ) #'dirvish-vc-menu)
|
|
(define-key dirvish-mode-map (kbd "TAB" ) #'dirvish-subtree-toggle)
|
|
(define-key dirvish-mode-map (kbd "M-f" ) #'dirvish-history-go-forward)
|
|
(define-key dirvish-mode-map (kbd "M-b" ) #'dirvish-history-go-backward)
|
|
(define-key dirvish-mode-map (kbd "M-l" ) #'dirvish-ls-switches-menu)
|
|
(define-key dirvish-mode-map (kbd "M-m" ) #'dirvish-mark-menu)
|
|
(define-key dirvish-mode-map (kbd "M-t" ) #'dirvish-layout-toggle)
|
|
(define-key dirvish-mode-map (kbd "M-s" ) #'dirvish-setup-menu)
|
|
(define-key dirvish-mode-map (kbd "M-e" ) #'dirvish-emerge-menu)
|
|
(define-key dirvish-mode-map (kbd "M-j" ) #'dirvish-fd-jump))
|
|
|
|
(global-set-key (kbd "C-x d") #'dirvish-dwim)
|
|
(global-set-key (kbd "C-x C-d") #'joe/dirvish-find-directory)
|
|
|
|
#+end_src
|
|
|
|
** Terminals/Shells
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'vterm)
|
|
|
|
(setq vterm-shell "/bin/fish")
|
|
(setq vterm-timer-delay 0.01)
|
|
(setq vterm-buffer-name-string "VTerm - %s")
|
|
(setq vterm-max-scrollback 100000)
|
|
(setq vterm-kill-buffer-on-exit t)
|
|
|
|
(defun joe/close-popup-buffer (vterm-buf event-msg)
|
|
(unless (or (eq popper-popup-status nil)
|
|
(eq popper-popup-status 'raised))
|
|
(popper-close-latest)))
|
|
|
|
(setq vterm-exit-functions '(joe/close-popup-buffer))
|
|
|
|
(defun joe/vterm-here ()
|
|
(interactive)
|
|
(let ((vterm-buf (vterm--internal #'switch-to-buffer)))
|
|
(with-current-buffer vterm-buf
|
|
(setq popper-popup-status 'raised))))
|
|
|
|
(global-set-key (kbd "C-c t") #'vterm)
|
|
(global-set-key (kbd "C-c T") #'joe/vterm-here)
|
|
|
|
(add-hook 'vterm-mode-hook (lambda () (setq-local global-hl-line-mode nil)))
|
|
#+end_src
|
|
|
|
We need this require so we can call `vterm--internal in the joe/vterm-here function, but that slows
|
|
down init time because vterm is loading TRAMP which is slow.
|
|
|
|
#+begin_src emacs-lisp
|
|
(run-with-idle-timer 2 nil (lambda () (require 'vterm)))
|
|
#+end_src
|
|
|
|
** Undo Tree
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'undo-tree)
|
|
|
|
(add-hook 'after-init-hook (lambda ()
|
|
(global-undo-tree-mode)
|
|
(setq undo-tree-visualizer-diff t)
|
|
(setq undo-tree-history-directory-alist `(("." . ,(expand-file-name "undo" user-emacs-directory))))))
|
|
#+end_src
|
|
|
|
** Which Key
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'which-key)
|
|
(setq which-key-idle-delay 0.3)
|
|
(add-hook 'after-init-hook (lambda () (which-key-mode)))
|
|
#+end_src
|
|
|
|
** Text Editor
|
|
|
|
Emacs is an great operating system, if only it had a good text editor...
|
|
|
|
*** Text editing
|
|
#+begin_src emacs-lisp
|
|
(global-set-key (kbd "M-z") #'zap-up-to-char)
|
|
(global-set-key (kbd "M-Z") #'zap-to-char)
|
|
;; (setq explicit-shell-file-name "~/Development/fell/fell")
|
|
|
|
(defun joe/duplicate-line-comment ()
|
|
(interactive)
|
|
(let ((col (current-column)))
|
|
(duplicate-line)
|
|
(comment-line 1)
|
|
(move-to-column col)))
|
|
|
|
(global-set-key (kbd "C-c d") 'duplicate-line)
|
|
(global-set-key (kbd "C-c C-;") 'joe/duplicate-line-comment)
|
|
|
|
#+end_src
|
|
|
|
*** Hydra
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'hydra)
|
|
|
|
(defhydra hydra-navigate (global-map "<f2>")
|
|
"Window Navigation"
|
|
("d" joe/smooth-scroll-half-page-down "half page down")
|
|
("u" joe/smooth-scroll-half-page-up "half page up")
|
|
("e" joe/smooth-scroll-short-down "line down")
|
|
("y" joe/smooth-scroll-short-up "line up")
|
|
("n" next-line "line down")
|
|
("p" previous-line "line up")
|
|
("M-r" move-to-window-line-top-bottom "Reposition cursor"))
|
|
#+end_src
|
|
|
|
*** Multiple Cursors
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'multiple-cursors)
|
|
#+end_src
|
|
|
|
*** Meow
|
|
#+begin_src emacs-lisp :tangle no
|
|
(straight-use-package 'meow)
|
|
(require 'meow)
|
|
(defun meow-setup ()
|
|
(setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
|
|
(meow-motion-overwrite-define-key
|
|
'("j" . meow-next)
|
|
'("k" . meow-prev)
|
|
'("<escape>" . ignore))
|
|
(meow-leader-define-key
|
|
;; SPC j/k will run the original command in MOTION state.
|
|
'("j" . "H-j")
|
|
'("k" . "H-k")
|
|
;; Use SPC (0-9) for digit arguments.
|
|
'("1" . meow-digit-argument)
|
|
'("2" . meow-digit-argument)
|
|
'("3" . meow-digit-argument)
|
|
'("4" . meow-digit-argument)
|
|
'("5" . meow-digit-argument)
|
|
'("6" . meow-digit-argument)
|
|
'("7" . meow-digit-argument)
|
|
'("8" . meow-digit-argument)
|
|
'("9" . meow-digit-argument)
|
|
'("0" . meow-digit-argument)
|
|
'("/" . meow-keypad-describe-key)
|
|
'("?" . meow-cheatsheet))
|
|
(meow-normal-define-key
|
|
'("0" . meow-expand-0)
|
|
'("9" . meow-expand-9)
|
|
'("8" . meow-expand-8)
|
|
'("7" . meow-expand-7)
|
|
'("6" . meow-expand-6)
|
|
'("5" . meow-expand-5)
|
|
'("4" . meow-expand-4)
|
|
'("3" . meow-expand-3)
|
|
'("2" . meow-expand-2)
|
|
'("1" . meow-expand-1)
|
|
'("-" . negative-argument)
|
|
'(";" . meow-reverse)
|
|
'("," . meow-inner-of-thing)
|
|
'("." . meow-bounds-of-thing)
|
|
'("[" . meow-beginning-of-thing)
|
|
'("]" . meow-end-of-thing)
|
|
'("a" . meow-append)
|
|
'("A" . meow-open-below)
|
|
'("b" . meow-back-word)
|
|
'("B" . meow-back-symbol)
|
|
'("c" . meow-change)
|
|
'("d" . meow-delete)
|
|
'("D" . meow-backward-delete)
|
|
'("e" . meow-next-word)
|
|
'("E" . meow-next-symbol)
|
|
'("f" . meow-find)
|
|
'("g" . meow-cancel-selection)
|
|
'("G" . meow-grab)
|
|
'("h" . meow-left)
|
|
'("H" . meow-left-expand)
|
|
'("i" . meow-insert)
|
|
'("I" . meow-open-above)
|
|
'("j" . meow-next)
|
|
'("J" . meow-next-expand)
|
|
'("k" . meow-prev)
|
|
'("K" . meow-prev-expand)
|
|
'("l" . meow-right)
|
|
'("L" . meow-right-expand)
|
|
'("m" . meow-join)
|
|
'("n" . meow-search)
|
|
'("o" . meow-block)
|
|
'("O" . meow-to-block)
|
|
'("p" . meow-yank)
|
|
'("q" . meow-quit)
|
|
'("Q" . meow-goto-line)
|
|
'("r" . meow-replace)
|
|
'("R" . meow-swap-grab)
|
|
'("s" . meow-kill)
|
|
'("t" . meow-till)
|
|
'("u" . meow-undo)
|
|
'("U" . meow-undo-in-selection)
|
|
'("v" . meow-visit)
|
|
'("w" . meow-mark-word)
|
|
'("W" . meow-mark-symbol)
|
|
'("x" . meow-line)
|
|
'("X" . meow-goto-line)
|
|
'("y" . meow-save)
|
|
'("Y" . meow-sync-grab)
|
|
'("z" . meow-pop-selection)
|
|
'("'" . repeat)
|
|
'("<escape>" . ignore)))
|
|
(meow-setup)
|
|
(meow-global-mode t)
|
|
#+end_src
|
|
|
|
*** Boon
|
|
#+begin_src emacs-lisp :tangle no
|
|
(straight-use-package 'boon)
|
|
(require 'boon-qwerty)
|
|
(boon-mode)
|
|
#+end_src
|
|
|
|
*** Kakoune.el
|
|
|
|
#+begin_src emacs-lisp :tangle no
|
|
(straight-use-package 'kakoune)
|
|
(require 'kakoune)
|
|
(defun ryo-enter () "Enter normal mode" (interactive) (ryo-modal-mode 1))
|
|
(defun my/kakoune-setup ()
|
|
"Call kakoune-setup-keybinds and then add some personal config."
|
|
(kakoune-setup-keybinds)
|
|
(setq ryo-modal-cursor-type 'box)
|
|
(add-hook 'prog-mode-hook #'ryo-enter)
|
|
(define-key ryo-modal-mode-map (kbd "SPC h") 'help-command)
|
|
;; Access all C-x bindings easily
|
|
(define-key ryo-modal-mode-map (kbd "z") ctl-x-map)
|
|
(ryo-modal-keys
|
|
("," save-buffer)
|
|
("P" counsel-yank-pop)
|
|
("m" mc/mark-next-like-this)
|
|
("M" mc/skip-to-next-like-this)
|
|
("n" mc/mark-previous-like-this)
|
|
("N" mc/skip-to-previous-like-this)
|
|
("M-m" mc/edit-lines)
|
|
("*" mc/mark-all-like-this)
|
|
("v" er/expand-region)
|
|
("C-v" set-rectangular-region-anchor)
|
|
("M-s" mc/split-region)
|
|
(";" (("q" delete-window)
|
|
("v" split-window-horizontally)
|
|
("s" split-window-vertically)))
|
|
("C-h" windmove-left)
|
|
("C-j" windmove-down)
|
|
("C-k" windmove-up)
|
|
("C-l" windmove-right)
|
|
("C-u" scroll-down-command :first '(deactivate-mark))
|
|
("C-d" scroll-up-command :first '(deactivate-mark))))
|
|
(add-hook 'after-init-hook 'my/kakoune-setup)
|
|
|
|
#+end_src
|
|
|
|
** IDE Features
|
|
*** LSP/Company
|
|
|
|
#+begin_src emacs-lisp
|
|
;; (straight-use-package 'yasnippet)
|
|
(straight-use-package 'markdown-mode)
|
|
(straight-use-package 'lsp-mode)
|
|
|
|
(setq lsp-keymap-prefix "C-c l")
|
|
;; (require 'lsp)
|
|
;; (straight-use-package 'eglot)
|
|
;; (setq completion-in-region-function (kind-icon-enhance-completion completion-in-region-function))
|
|
|
|
|
|
(setq completion-in-region-function #'consult-completion-in-region)
|
|
(global-set-key [remap dabbrev-expand] 'hippie-expand)
|
|
|
|
;; (straight-use-package 'cape)
|
|
;; (add-to-list 'completion-at-point-functions #'cape-symbol)
|
|
;; (add-to-list 'completion-at-point-functions #'cape-file)
|
|
;; (add-to-list 'completion-at-point-functions #'cape-dabbrev)
|
|
;; (straight-use-package 'kind-icon)
|
|
;; (require 'kind-icon)
|
|
|
|
(straight-use-package 'company)
|
|
;; (require 'company)
|
|
;; (setq company-transformers '())
|
|
(add-to-list 'completion-at-point-functions #'elisp-completion-at-point)
|
|
(with-eval-after-load 'company
|
|
(define-key company-active-map (kbd "C-n") nil)
|
|
(define-key company-active-map (kbd "C-p") nil)
|
|
(define-key company-active-map (kbd "<return>") nil)
|
|
(define-key company-active-map (kbd "C-f") #'company-complete-selection)
|
|
(define-key company-active-map [tab] #'company-complete-common-or-cycle)
|
|
(define-key company-active-map (kbd "<backtab>") (lambda () (interactive) (company-complete-common-or-cycle -1)))
|
|
(setq company-idle-delay 0
|
|
company-tooltip-idle-delay 10
|
|
company-require-match nil
|
|
company-frontends '(company-preview-frontend company-echo-metadata-frontend)
|
|
;; company-frontends '(company-text-icons-margin company-echo-metadata-frontend)
|
|
company-backends '((company-capf company-files)))
|
|
(setq company-transformers '(company-sort-by-occurrence)))
|
|
(add-hook 'after-init-hook (lambda () (global-company-mode)))
|
|
|
|
;; (delete 'elisp-completion-at-point completion-at-point-functions)
|
|
;; (delete 'cape-symbol completion-at-point-functions)
|
|
|
|
;; (straight-use-package 'corfu)
|
|
;; (global-corfu-mode)
|
|
;; (setq
|
|
;; corfu-cycle t ;; Enable cycling for `corfu-next/previous'
|
|
;; corfu-auto t ;; Enable auto completion
|
|
;; corfu-separator ?\s ;; Orderless field separator
|
|
;; corfu-quit-at-boundary nil ;; Never quit at completion boundary
|
|
;; corfu-quit-no-match nil ;; Never quit, even if there is no match
|
|
;; corfu-preview-current t ;; Disable current candidate preview
|
|
;; corfu-preselect-first t ;; Disable candidate preselection
|
|
;; corfu-on-exact-match nil ;; Configure handling of exact matches
|
|
;; corfu-echo-documentation t ;; Disable documentation in the echo area
|
|
;; corfu-scroll-margin 5) ;; Use scroll margin
|
|
;; (setq corfu-preview-current t)
|
|
;; (straight-use-package
|
|
;; (setq-local corfu-auto t
|
|
;; corfu-auto-delay 0.1
|
|
;; corfu-auto-prefix 1
|
|
;; completion-styles '(orderless basic))
|
|
|
|
|
|
;; (global-set-key (kbd "<tab>")
|
|
;; (lambda ()
|
|
;; (interactive)
|
|
;; (let ((company-tooltip-idle-delay 0.0))
|
|
;; (company-complete)
|
|
;; (and company-candidates
|
|
;; (company-call-frontends 'post-command)))))
|
|
;; Enable fancy-dabbrev previews everywhere:
|
|
;; (global-fancy-dabbrev-mode)
|
|
;; (global-set-key [tab] #'fancy-dabbrev-expand-or-indent)
|
|
;; (global-set-key (kbd "<backtab>") 'fancy-dabbrev-backward)
|
|
;; (require 'yasnippet)
|
|
;; (yas-global-mode 1)
|
|
#+end_src
|
|
|
|
*** C
|
|
|
|
Design some basic functions for compiling. There's also a hook to close the popper window if there
|
|
are no warnings or errors. It will check if we are still in the compilation buffer as well as
|
|
whether the point hasn't been moved. This way, if I switched to another popper buffer, like vterm,
|
|
it doesn't close it.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun joe/c-mode-hook ()
|
|
(local-set-key (kbd "C-x c r") (defun joe/make-run () (interactive) (compile "make run")))
|
|
(local-set-key (kbd "C-x c c") (defun joe/make () (interactive) (compile "make"))))
|
|
(add-hook 'c-mode-hook #'joe/c-mode-hook)
|
|
|
|
(defun joe/close-compilation-if-no-warn-err (buffer string)
|
|
"Bury a compilation buffer if succeeded without warnings "
|
|
(if (and
|
|
(string-match "compilation" (buffer-name buffer))
|
|
(string-match "finished" string)
|
|
(not
|
|
(with-current-buffer (current-buffer)
|
|
(search-forward "warning" nil t))))
|
|
(run-with-timer 1 nil
|
|
(lambda ()
|
|
(and (eq (point) 1)
|
|
(string-match "compilation" (buffer-name (current-buffer)))
|
|
(popper-close-latest))))))
|
|
(add-hook 'compilation-finish-functions 'joe/close-compilation-if-no-warn-err)
|
|
#+end_src
|
|
|
|
** Magit
|
|
|
|
The best git porcelain/client I've ever used. Also kill stray magit buffers left over as explained [[https://manueluberti.eu/emacs/2018/02/17/magit-bury-buffer/][here]]
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'magit)
|
|
|
|
(defun joe/magit-kill-buffers (param)
|
|
"Restore window configuration and kill all Magit buffers."
|
|
(let ((buffers (magit-mode-get-buffers)))
|
|
(magit-restore-window-configuration)
|
|
(mapc #'kill-buffer buffers)))
|
|
|
|
(setq magit-bury-buffer-function #'joe/magit-kill-buffers)
|
|
|
|
#+end_src
|
|
|
|
** Restclient
|
|
|
|
#+begin_src emacs-lisp
|
|
(straight-use-package 'restclient)
|
|
#+end_src
|
|
|
|
|
|
* COMMENT Local variables
|
|
;; Local Variables:
|
|
;; eval: (add-hook 'after-save-hook '(lambda () (org-babel-tangle)) nil t)
|
|
;; End:
|