267 lines
7.6 KiB
EmacsLisp
267 lines
7.6 KiB
EmacsLisp
|
;;; init-editing-utils.el --- Day-to-day editing helpers -*- lexical-binding: t -*-
|
|||
|
;;; Commentary:
|
|||
|
;;; Code:
|
|||
|
|
|||
|
(require-package 'unfill)
|
|||
|
|
|||
|
(when (fboundp 'electric-pair-mode)
|
|||
|
(add-hook 'after-init-hook 'electric-pair-mode))
|
|||
|
(add-hook 'after-init-hook 'electric-indent-mode)
|
|||
|
|
|||
|
(maybe-require-package 'list-unicode-display)
|
|||
|
|
|||
|
|
|||
|
;;; Some basic preferences
|
|||
|
|
|||
|
(setq-default
|
|||
|
blink-cursor-interval 0.4
|
|||
|
bookmark-default-file (locate-user-emacs-file ".bookmarks.el")
|
|||
|
buffers-menu-max-size 30
|
|||
|
case-fold-search t
|
|||
|
column-number-mode t
|
|||
|
ediff-split-window-function 'split-window-horizontally
|
|||
|
ediff-window-setup-function 'ediff-setup-windows-plain
|
|||
|
indent-tabs-mode nil
|
|||
|
create-lockfiles nil
|
|||
|
auto-save-default nil
|
|||
|
make-backup-files nil
|
|||
|
mouse-yank-at-point t
|
|||
|
save-interprogram-paste-before-kill t
|
|||
|
scroll-preserve-screen-position 'always
|
|||
|
set-mark-command-repeat-pop t
|
|||
|
tooltip-delay 1.5
|
|||
|
truncate-lines nil
|
|||
|
truncate-partial-width-windows nil)
|
|||
|
|
|||
|
(add-hook 'after-init-hook 'delete-selection-mode)
|
|||
|
|
|||
|
(add-hook 'after-init-hook 'global-auto-revert-mode)
|
|||
|
(setq global-auto-revert-non-file-buffers t
|
|||
|
auto-revert-verbose nil)
|
|||
|
(with-eval-after-load 'autorevert
|
|||
|
(diminish 'auto-revert-mode))
|
|||
|
|
|||
|
(add-hook 'after-init-hook 'transient-mark-mode)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;; Huge files
|
|||
|
|
|||
|
(when (fboundp 'so-long-enable)
|
|||
|
(add-hook 'after-init-hook 'so-long-enable))
|
|||
|
|
|||
|
(require-package 'vlf)
|
|||
|
|
|||
|
(defun ffap-vlf ()
|
|||
|
"Find file at point with VLF."
|
|||
|
(interactive)
|
|||
|
(let ((file (ffap-file-at-point)))
|
|||
|
(unless (file-exists-p file)
|
|||
|
(error "File does not exist: %s" file))
|
|||
|
(vlf file)))
|
|||
|
|
|||
|
|
|||
|
;;; A simple visible bell which works in all terminal types
|
|||
|
(require-package 'mode-line-bell)
|
|||
|
(add-hook 'after-init-hook 'mode-line-bell-mode)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;; Newline behaviour (see also electric-indent-mode, enabled above)
|
|||
|
|
|||
|
(defun sanityinc/newline-at-end-of-line ()
|
|||
|
"Move to end of line, enter a newline, and reindent."
|
|||
|
(interactive)
|
|||
|
(move-end-of-line 1)
|
|||
|
(newline-and-indent))
|
|||
|
|
|||
|
(global-set-key (kbd "S-<return>") 'sanityinc/newline-at-end-of-line)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(with-eval-after-load 'subword
|
|||
|
(diminish 'subword-mode))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(when (fboundp 'display-line-numbers-mode)
|
|||
|
(setq-default display-line-numbers-width 3)
|
|||
|
(add-hook 'prog-mode-hook 'display-line-numbers-mode))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(when (boundp 'display-fill-column-indicator)
|
|||
|
(setq-default indicate-buffer-boundaries 'left)
|
|||
|
(setq-default display-fill-column-indicator-character ?┊)
|
|||
|
(add-hook 'prog-mode-hook 'display-fill-column-indicator-mode))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(when (require-package 'rainbow-delimiters)
|
|||
|
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
|
|||
|
|
|||
|
|
|||
|
(when (maybe-require-package 'symbol-overlay)
|
|||
|
(dolist (hook '(prog-mode-hook html-mode-hook yaml-mode-hook conf-mode-hook))
|
|||
|
(add-hook hook 'symbol-overlay-mode))
|
|||
|
(with-eval-after-load 'symbol-overlay
|
|||
|
(diminish 'symbol-overlay-mode)
|
|||
|
(define-key symbol-overlay-mode-map (kbd "M-i") 'symbol-overlay-put)
|
|||
|
(define-key symbol-overlay-mode-map (kbd "M-I") 'symbol-overlay-remove-all)
|
|||
|
(define-key symbol-overlay-mode-map (kbd "M-n") 'symbol-overlay-jump-next)
|
|||
|
(define-key symbol-overlay-mode-map (kbd "M-p") 'symbol-overlay-jump-prev)))
|
|||
|
|
|||
|
|
|||
|
;;; Zap *up* to char is a handy pair for zap-to-char
|
|||
|
(global-set-key (kbd "M-Z") 'zap-up-to-char)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(require-package 'browse-kill-ring)
|
|||
|
(setq browse-kill-ring-separator "\f")
|
|||
|
(global-set-key (kbd "M-Y") 'browse-kill-ring)
|
|||
|
(with-eval-after-load 'browse-kill-ring
|
|||
|
(define-key browse-kill-ring-mode-map (kbd "C-g") 'browse-kill-ring-quit)
|
|||
|
(define-key browse-kill-ring-mode-map (kbd "M-n") 'browse-kill-ring-forward)
|
|||
|
(define-key browse-kill-ring-mode-map (kbd "M-p") 'browse-kill-ring-previous))
|
|||
|
(with-eval-after-load 'page-break-lines
|
|||
|
(add-to-list 'page-break-lines-modes 'browse-kill-ring-mode))
|
|||
|
|
|||
|
|
|||
|
;; Don't disable narrowing commands
|
|||
|
(put 'narrow-to-region 'disabled nil)
|
|||
|
(put 'narrow-to-page 'disabled nil)
|
|||
|
(put 'narrow-to-defun 'disabled nil)
|
|||
|
;; Don't disable case-change functions
|
|||
|
(put 'upcase-region 'disabled nil)
|
|||
|
(put 'downcase-region 'disabled nil)
|
|||
|
|
|||
|
|
|||
|
;; Show matching parens
|
|||
|
(add-hook 'after-init-hook 'show-paren-mode)
|
|||
|
|
|||
|
(when (fboundp 'repeat-mode)
|
|||
|
(add-hook 'after-init-hook 'repeat-mode))
|
|||
|
|
|||
|
|
|||
|
;;; Handy key bindings
|
|||
|
|
|||
|
(with-eval-after-load 'help
|
|||
|
(define-key help-map "A" 'describe-face))
|
|||
|
|
|||
|
(global-set-key (kbd "C-.") 'set-mark-command)
|
|||
|
(global-set-key (kbd "C-x C-.") 'pop-global-mark)
|
|||
|
|
|||
|
(when (maybe-require-package 'avy)
|
|||
|
(global-set-key (kbd "C-;") 'avy-goto-char-timer))
|
|||
|
|
|||
|
(require-package 'multiple-cursors)
|
|||
|
;; multiple-cursors
|
|||
|
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
|
|||
|
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
|
|||
|
(global-set-key (kbd "C-+") 'mc/mark-next-like-this)
|
|||
|
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
|
|||
|
|
|||
|
;; Train myself to use M-f and M-b instead
|
|||
|
(global-unset-key [M-left])
|
|||
|
(global-unset-key [M-right])
|
|||
|
|
|||
|
(defun kill-back-to-indentation ()
|
|||
|
"Kill from point back to the first non-whitespace character on the line."
|
|||
|
(interactive)
|
|||
|
(let ((prev-pos (point)))
|
|||
|
(back-to-indentation)
|
|||
|
(kill-region (point) prev-pos)))
|
|||
|
|
|||
|
(global-set-key (kbd "C-M-<backspace>") 'kill-back-to-indentation)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;; Page break lines
|
|||
|
|
|||
|
(when (maybe-require-package 'page-break-lines)
|
|||
|
(add-hook 'after-init-hook 'global-page-break-lines-mode)
|
|||
|
(with-eval-after-load 'page-break-lines
|
|||
|
(diminish 'page-break-lines-mode)))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;; Shift lines up and down with M-up and M-down. When paredit is enabled,
|
|||
|
;; it will use those keybindings. For this reason, you might prefer to
|
|||
|
;; use M-S-up and M-S-down, which will work even in lisp modes.
|
|||
|
|
|||
|
(require-package 'move-dup)
|
|||
|
(global-set-key [M-S-up] 'move-dup-move-lines-up)
|
|||
|
(global-set-key [M-S-down] 'move-dup-move-lines-down)
|
|||
|
|
|||
|
(global-set-key (kbd "C-c d") 'move-dup-duplicate-down)
|
|||
|
(global-set-key (kbd "C-c u") 'move-dup-duplicate-up)
|
|||
|
|
|||
|
|
|||
|
;;; Fix backward-up-list to understand quotes, see http://bit.ly/h7mdIL
|
|||
|
|
|||
|
(defun sanityinc/backward-up-sexp (arg)
|
|||
|
"Jump up to the start of the ARG'th enclosing sexp."
|
|||
|
(interactive "p")
|
|||
|
(let ((ppss (syntax-ppss)))
|
|||
|
(cond ((elt ppss 3)
|
|||
|
(goto-char (elt ppss 8))
|
|||
|
(sanityinc/backward-up-sexp (1- arg)))
|
|||
|
((backward-up-list arg)))))
|
|||
|
|
|||
|
(global-set-key [remap backward-up-list] 'sanityinc/backward-up-sexp) ; C-M-u, C-M-up
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;; Cut/copy the current line if no region is active
|
|||
|
(require-package 'whole-line-or-region)
|
|||
|
(add-hook 'after-init-hook 'whole-line-or-region-global-mode)
|
|||
|
(with-eval-after-load 'whole-line-or-region
|
|||
|
(diminish 'whole-line-or-region-local-mode))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;; M-^ is inconvenient, so also bind M-j
|
|||
|
(global-set-key (kbd "M-j") 'join-line)
|
|||
|
|
|||
|
|
|||
|
;; Random line sorting
|
|||
|
(defun sanityinc/sort-lines-random (beg end)
|
|||
|
"Sort lines in region from BEG to END randomly."
|
|||
|
(interactive "r")
|
|||
|
(save-excursion
|
|||
|
(save-restriction
|
|||
|
(narrow-to-region beg end)
|
|||
|
(goto-char (point-min))
|
|||
|
(let ;; To make `end-of-line' and etc. to ignore fields.
|
|||
|
((inhibit-field-text-motion t))
|
|||
|
(sort-subr nil 'forward-line 'end-of-line nil nil
|
|||
|
(lambda (s1 s2) (eq (random 2) 0)))))))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(require-package 'highlight-escape-sequences)
|
|||
|
(add-hook 'after-init-hook 'hes-mode)
|
|||
|
|
|||
|
|
|||
|
(require-package 'which-key)
|
|||
|
(add-hook 'after-init-hook 'which-key-mode)
|
|||
|
(setq-default which-key-idle-delay 1.5)
|
|||
|
(with-eval-after-load 'which-key
|
|||
|
(diminish 'which-key-mode))
|
|||
|
|
|||
|
|
|||
|
(defun sanityinc/disable-features-during-macro-call (orig &rest args)
|
|||
|
"When running a macro, disable features that might be expensive.
|
|||
|
ORIG is the advised function, which is called with its ARGS."
|
|||
|
(let (post-command-hook
|
|||
|
font-lock-mode
|
|||
|
(tab-always-indent (or (eq 'complete tab-always-indent) tab-always-indent)))
|
|||
|
(apply orig args)))
|
|||
|
|
|||
|
(advice-add 'kmacro-call-macro :around 'sanityinc/disable-features-during-macro-call)
|
|||
|
|
|||
|
|
|||
|
(provide 'init-editing-utils)
|
|||
|
;;; init-editing-utils.el ends here
|