;;; common.el --- Common settings for text files. -*- lexical-binding: t; -*- ;; Time-stamp: <2020-02-05T19:58:53+0100> ;;; Commentary: ;;; Code: (require 'basics/global-variables) (use-package emacs :ensure nil :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. :hook (text-mode . auto-fill-mode) ; Enable word-wrapping at fill-column. ) ;; Save cursor position. (use-package saveplace :config (save-place-mode t) ) ;; Ruler with fill-column marker. (use-package ruler-mode :config (defun my/ruler-on () "Turn `ruler-mode' on." (ruler-mode 1) ;; Show a fill-column indicator vertically across the buffer. (when (>= emacs-major-version 27) (display-fill-column-indicator-mode)) ) :custom-face (ruler-mode-default ((t (:inherit default :background "gray18" :foreground "dim gray" :box nil)))) (ruler-mode-column-number ((t (:inherit ruler-mode-default :foreground "dark gray")))) :hook (find-file . my/ruler-on) (text-mode . my/ruler-on) ; For the scratch buffer. ) ;; Spell checking. (unless slow-computer (use-package flyspell :if (or (executable-find "aspell") (executable-find "hunspell") (executable-find "ispell")) :custom (ispell-dictionary "english") :config (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 "german")) ;; Allow setting the language in file/dir local variables. (put 'ispell-dictionary 'safe-local-variable #'stringp) :bind ("" . my/toggle-flyspell) (:map flyspell-mode-map ("C-;" . nil)) ; iedit needs C-;. :hook ;; Spellcheck comments. (prog-mode . flyspell-prog-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) ) ) ; unless slow-computer. ;; The string Time-stamp: <> in the first 8 lines of the file will be updated ;; with the current timestamp. (use-package time-stamp :config (if (>= emacs-major-version 27) (setq time-stamp-format "%Y-%02m-%02dT%02H:%02M:%02S%5z") (progn (setq time-stamp-format "%Y-%02m-%02dT%02H:%02M:%02S+00:00") (setq time-stamp-time-zone t))) ; Set to UTC since ISO 8601 is not supported. :hook (before-save . time-stamp) ) ;; A template system. (use-package yasnippet :after (company) :defines (company-candidates) :functions (yas-reload-all yas-expand-snippet) :config (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) :bind (:map yas-keymap ("" . my/tab-yas-or-company) ("TAB" . my/tab-yas-or-company) ) :hook (prog-mode . yas-minor-mode) ) ;; Install snippet-collection but don't use it. (use-package yasnippet-snippets :defer t :config (delete 'yasnippet-snippets-dir yas-snippet-dirs) ; Don't add snippets. ) ;; Automatically insert text in new files. (use-package autoinsert :after (yasnippet) :init (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 (add-to-list 'auto-insert-alist '(("\\.\\(cpp\\|cc\\|cxx\\|c\\+\\+\\)$" . "C++ program") . ["cpp" my/autoinsert-yas-expand])) (add-to-list 'auto-insert-alist '(("\\.\\(hpp\\|hh\\|hxx\\|h\\+\\+\\)$" . "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])) :hook (find-file . auto-insert) ) ;; Better search. (use-package swiper :after (ivy) :functions (swiper) :bind ("C-s" . 'swiper) ) ;; Visualize and transform whitespace. (use-package whitespace :after (company) :functions (my/whitespace-mode-enabled-p my/on-off-whitespace-before-company) :custom (whitespace-line-column nil) ; Set to fill-column. :config (delete 'newline-mark whitespace-style) ; Don't paint $ at eol. (delete 'lines whitespace-style) ; Don't mark whole overly long lines. (when (< emacs-major-version 27) ; Mark end of overly long lines. (add-to-list 'whitespace-style 'lines-tail)) ;; Workaround to not show dots in popup menus. (defun my/whitespace-mode-enabled-p () (symbol-value 'whitespace-mode)) (defvar-local my/ws-enabled nil) ;; company: (defun my/on-off-whitespace-before-company(command) (when (string= "show" command) (setq-local my/ws-enabled (my/whitespace-mode-enabled-p)) (if my/ws-enabled (whitespace-mode -1))) (when (string= "hide" command) (if my/ws-enabled (whitespace-mode t)))) (advice-add 'company-call-frontends :before #'my/on-off-whitespace-before-company) (defun my/whitespace-mode-off () (setq-local my/ws-enabled (my/whitespace-mode-enabled-p)) (if my/ws-enabled (whitespace-mode -1))) (defun my/whitespace-mode-on () (if my/ws-enabled (whitespace-mode t))) ;; popup: (defadvice popup-create (before my/popup-suppress-whitespace-mode activate) "Suspend whitespace-mode while popups are visible." (my/whitespace-mode-off)) (defadvice popup-delete (after my/popup-restore-whitespace-mode activate) "Restore whitespace-mode when all popups have closed." (my/whitespace-mode-on)) (if (display-graphic-p) (custom-set-faces '(whitespace-line ((t (:inherit whitespace-line :weight normal :foreground nil :background nil :box (:line-width 1 :color "dark red") ;; :underline (:color "dark red") ))))) (custom-set-faces ; else '(whitespace-line ((t (:inherit whitespace-line :background nil :underline t ))))) ) (defun my/ws-load-local-vars-first () "Loads local variables (fill-column) before enabling whitespace-mode." (when (< emacs-major-version 27) ; We don't use 'lines-tail in Emacs >= 27. (hack-local-variables)) (whitespace-mode) ) (defvar my/no-ws-cleanup nil "Do not cleanup whitespace if t.") (make-variable-buffer-local 'my/no-ws-cleanup) (put 'my/no-ws-cleanup 'safe-local-variable #'booleanp) ; Mark as safe. (defun my/ws-maybe-cleanup () "Run `whitespace-cleanup' if `my/no-ws-cleanup' is not t." (unless my/no-ws-cleanup (whitespace-cleanup)) ) :bind ("C-x w" . whitespace-mode) :hook (prog-mode . my/ws-load-local-vars-first) (conf-mode . my/ws-load-local-vars-first) (text-mode . my/ws-load-local-vars-first) (before-save . my/ws-maybe-cleanup) :custom-face (whitespace-space ((nil :foreground "gray18"))) ) (use-package ripgrep) (provide 'text/common) ;;; common.el ends here