.emacs.d/init.d/text/common.el

267 lines
11 KiB
EmacsLisp

;;; common.el --- Common settings for text files. -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(require 'basics/package-management)
(require 'basics/global-variables)
(use-package emacs
:straight (:type built-in)
:demand t
:custom ((require-final-newline t) ; Always add newline at end of file.
(fill-column 80) ; Documents are 80 chars wide by default.
(word-wrap t)) ; Wrap at word for continuation lines.
:bind (("C-r" . jump-to-register) ; Move point to location in register.
("C-S-r" . point-to-register); Store location of point in register.
("M-W" . copy-to-register) ; Store text in register.
("C-S-y" . insert-register) ; Insert text from register.
("M-<f7>" . list-registers) ; List all registers.
("C-c C-S-t" . toggle-truncate-lines))
:hook (text-mode . auto-fill-mode)) ; Enable word-wrapping at fill-column.
;; Quickly jump to next/previous register.
(use-package register-quicknav
:straight (register-quicknav
:type git
:repo "https://schlomp.space/tastytea/register-quicknav.git"
:branch "main")
;; ^^^^^^^ See <https://github.com/raxod502/straight.el/issues/279>.
;; Fix is in develop: <https://github.com/raxod502/straight.el/pull/630>.
:custom (register-quicknav-buffer-only t)
:bind (("C-<f5>" . register-quicknav-prev-register)
("C-<f6>" . register-quicknav-next-register)
("C-<f7>" . register-quicknav-point-to-unused-register)
("C-S-<f7>" . register-quicknav-clear-current-register)))
;; Save cursor position.
(use-package saveplace
:demand t
:config (save-place-mode t))
;; Ruler with fill-column marker.
(use-package ruler-mode
:straight (:type built-in)
:after (doom-themes display-line-numbers)
:demand t
:config (progn
(defun my/ruler-set-colors ()
(set-face-background 'ruler-mode-default
(face-foreground 'line-number))
(set-face-foreground 'ruler-mode-default
(face-background 'default))
(set-face-foreground 'ruler-mode-column-number
(face-background 'default))
(if (and (window-system)
(>= emacs-major-version 27))
(set-face-foreground 'ruler-mode-fill-column
(face-foreground
'fill-column-indicator nil t))
(set-face-foreground 'ruler-mode-fill-column
(face-foreground 'shadow)))
(set-face-foreground 'ruler-mode-comment-column
(face-foreground 'ruler-mode-fill-column))
(set-face-foreground 'ruler-mode-goal-column
(face-foreground 'ruler-mode-fill-column))
(set-face-foreground 'ruler-mode-current-column
(face-foreground 'line-number-current-line)))
(my/ruler-set-colors)
(defun my/ruler-on ()
"Turn `ruler-mode' on."
(unless (bound-and-true-p lsp-mode)
;; lsp-mode has this breadcrumb thingie instead.
(ruler-mode 1))))
:custom-face (ruler-mode-default ((t (:inherit·default
:box·nil))))
:hook ((find-file . my/ruler-on)
(text-mode . my/ruler-on) ; For the scratch buffer.
(server-after-make-frame . my/ruler-set-colors)))
;; Show a fill-column indicator vertically across the buffer.
(when (>= emacs-major-version 27)
(use-package display-fill-column-indicator
:hook ((find-file . display-fill-column-indicator-mode)
(text-mode . display-fill-column-indicator-mode))))
;; spell checking.
(use-package ispell
:straight (:type built-in)
;; Use hunspell if possible and configure multiple dictionaries.
;; <https://200ok.ch/posts/2020-08-22_setting_up_spell_checking_with_multiple_dictionaries.html>
:config (when (executable-find "hunspell")
(customize-set-variable 'ispell-program-name
(executable-find "hunspell"))
(ispell-set-spellchecker-params)
(ispell-hunspell-add-multi-dic "en_US,de_DE")
(ispell-hunspell-add-multi-dic "en_GB,de_DE")
(ispell-hunspell-add-multi-dic "de_DE,de_AT,de_CH")))
;; Interactive spell checking.
(use-package flyspell
:if (and (not slow-computer)
(or (executable-find "aspell")
(executable-find "hunspell")
(executable-find "ispell")))
:diminish flyspell-mode
:custom ((flyspell-default-dictionary "en_GB"))
:config (progn
(defun my/toggle-flyspell ()
"Toggle flyspell-mode and run flyspell-buffer after activating."
(interactive)
(if (bound-and-true-p flyspell-mode)
(flyspell-mode 0)
(flyspell-mode)
(flyspell-buffer)))
(defun my/flyspell-german ()
"Set dictionary to german."
(interactive)
(ispell-change-dictionary "de_DE")))
:bind (("<f8>" . my/toggle-flyspell)
(:map flyspell-mode-map
("C-;" . nil) ; iedit needs C-;.
("C-M-i" . nil) ; imenu-anywhere needs it.
("C-c ." . flyspell-auto-correct-word))) ; C-. doesn't work in TUI.
:hook ((prog-mode . flyspell-prog-mode) ; Spellcheck comments.
(text-mode . flyspell-mode) ; Spellcheck text documents ↓.
(LaTeX-mode . my/flyspell-german)
(LaTeX-mode . flyspell-mode)
(adoc-mode . flyspell-mode)
(markdown-mode . flyspell-mode)
(git-commit-mode . flyspell-mode))
:mode ("COMMIT_EDITMSG\\'" . flyspell-mode))
;; The string Time-stamp: <> in the first 8 lines of the file will be updated
;; with the current timestamp.
(use-package time-stamp
:config (progn
(if (>= emacs-major-version 27)
(setq time-stamp-format "%Y-%02m-%02dT%02H:%02M:%02S%5z")
;; Set to UTC since ISO 8601 is not supported.
(setq time-stamp-format "%Y-%02m-%02dT%02H:%02M:%02S+0000")
(setq time-stamp-time-zone t)))
:hook (before-save . time-stamp))
;; A template system.
(use-package yasnippet
:after (company)
:defines (company-candidates)
:functions (yas-reload-all yas-expand-snippet)
:diminish yas-minor-mode
:config (progn
(defun my/tab-yas-or-company ()
"Complete with company if possible, jump to next field otherwise."
(interactive)
(if company-candidates
(company-complete-selection)
(yas-next-field)))
(yas-reload-all)
(defun my/string-to-var (string)
"Replace characters that usually are illegal in variable names in STRING with _."
(interactive)
(replace-regexp-in-string
"[[:space:]]" "_"
(replace-regexp-in-string "[^[:ascii:]]" "_" string))))
:bind (:map yas-keymap
("<tab>" . my/tab-yas-or-company)
("TAB" . my/tab-yas-or-company))
:hook ((prog-mode . yas-minor-mode)
(org-mode . yas-minor-mode)
(nxml-mode . yas-minor-mode)))
;; Install snippet-collection but don't use it.
(use-package yasnippet-snippets
:demand t
:after (yasnippet)
;; Don't add the snippets.
:config (delete 'yasnippet-snippets-dir yas-snippet-dirs))
;; Automatically insert text in new files.
(use-package autoinsert
:after (yasnippet)
:init (progn
(defun my/autoinsert-yas-expand ()
"Replace text in yasnippet template."
(yas-minor-mode t)
(yas-expand-snippet (buffer-string) (point-min) (point-max))))
:custom ((auto-insert-directory (concat user-emacs-directory "auto-insert"))
(auto-insert-query nil)) ; Don't ask before inserting.
:config (progn
(add-to-list
'auto-insert-alist '(("\\.c\\(pp\\|c\\|xx\\|\\+\\+\\)$" .
"C++ program") .
["cpp" my/autoinsert-yas-expand]))
(add-to-list
'auto-insert-alist '(("\\.h\\(pp\\|h\\|xx\\|\\+\\+\\)$" .
"C++ header") .
["hpp" my/autoinsert-yas-expand]))
(add-to-list
'auto-insert-alist '(("\\.[1-9]\\.adoc$" . "AsciiDoc manpage") .
["manpage.adoc" my/autoinsert-yas-expand]))
(add-to-list
'auto-insert-alist '(("\\.user.js$" . "Userscript") .
["user.js" my/autoinsert-yas-expand]))
(add-to-list
'auto-insert-alist '(("metadata\\.xml$" . "Gentoo pkg metadata") .
["metadata.xml" my/autoinsert-yas-expand])))
:hook (find-file . auto-insert))
;; Better search.
(use-package swiper
:after (ivy)
:functions (swiper)
:bind ("C-s" . swiper))
;; Calls whitespace-cleanup before saving the current buffer, but only if the
;; whitespace in the buffer was initially clean.
(use-package whitespace-cleanup-mode
:after (whitespace)
:config (global-whitespace-cleanup-mode)
:hook (change-major-mode-hook
. (lambda () (when (not my/reformat-save)
(setq-local whitespace-cleanup-mode nil)))))
;; ripgrep.
(use-package rg
:bind ("C-c s" . rg-menu))
;; Insert pseudo latin text.
(use-package lorem-ipsum)
;; Translate ANSI escape color codes.
(use-package ansi-color
:config (progn
(defun my/apply-ansi-colors-on-buffer ()
"Apply ANSI colors in the current buffer."
(interactive)
(let ((inhibit-read-only t))
(ansi-color-apply-on-region (point-min) (point-max))))
(defun my/apply-ansi-colors-compilation ()
"Apply ANSI colors in the compilation window."
(let ((inhibit-read-only t))
(ansi-color-apply-on-region compilation-filter-start (point)))))
:mode ("\\.log$" . my/apply-ansi-colors-on-buffer)
:hook (compilation-filter . my/apply-ansi-colors-compilation))
;; Colorize color names.
(use-package rainbow-mode
:demand t
:diminish rainbow-mode)
;; Tries to find points of interest in buffer and jumps to them.
(use-package imenu
:custom (imenu-auto-rescan t))
;; Tries to find points of interest in all open buffers and jumps to them.
(use-package imenu-anywhere
:after (imenu ivy)
:bind ("C-M-i" . ivy-imenu-anywhere))
(provide 'text/common)
;;; common.el ends here