;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; start emacs server (daemon) via real client so org-mode and other 'workspaces' can be setup as faux daemonized emacs ; (server-start) ;; critical built in for tuning startup (setq kmn/is-dayjob (string= "PCE" (getenv "USERDOMAIN")) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Packages related (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) ; this goes in chemacs2 init -- DO NOT UNCOMMENT (package-initialize) ; this goes in chemacs2 init -- DO NOT UNCOMMENT (add-to-list 'package-selected-packages '(centaur-tabs scratch persistent-scratch persp-mode rainbow-mode rainbow-delimiters markdown-mode focus zoom popwin dired-single diredfl doominhibitinhibit-modeline helpful helm helm-org dired-rainbow dired-rainbow-listing dired-single dash s origami modus-themes use-package) ) (when (not kmn/is-dayjob) (add-to-list 'package-selected-packages '(devdocs devdocs-browser magit helm-ls-git xclip) ) ) (require 'use-package) ; helper functions (require 'subr-x) (setq kmn/is-termux (string-suffix-p "Android" (string-trim (shell-command-to-string "uname -a")))) ; ensure elisp plugins are compiled (require 'dash) (require 'f) (defun was-compiled-p (path) "Does the directory at PATH contain any .elc files?" (--any-p (f-ext? it "elc") (f-files path))) (defun ensure-packages-compiled () "If any packages installed with package.el aren't compiled yet, compile them." (--each (f-directories package-user-dir) (unless (was-compiled-p it) (byte-recompile-directory it 0)))) (ensure-packages-compiled) (unless (was-compiled-p "~/.emacs.d.profiles/common") (byte-recompile-directory "~/.emacs.d.profiles/common" 0)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; fix opening urls inside termux (when kmn/is-termux (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "/data/data/com.termux/files/usr/bin/termux-open")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; backups (defconst kmn/backup-dir (expand-file-name "backups/" user-emacs-directory)) (unless (file-exists-p kmn/backup-dir) (make-directory kmn/backup-dir)) (setq backup-directory-alist `((".*" . ,kmn/backup-dir))) (setq auto-save-list-file-prefix kmn/backup-dir) (setq auto-save-file-name-transforms `(("\\(?:[^/]*/\\)*\\(.*\\)" ,(concat kmn/backup-dir "\\1") t))) (setq backup-by-copying t) ; safest form of backup file creation ; Config backups so we have *more*, not less (setq delete-old-versions t kept-new-versions 1 kept-old-versions 3 version-control t ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; dired adjustments (with-eval-after-load 'dired (require 'dired-x) ;; Set dired-x global variables here. For example: ;; (setq dired-x-hands-off-my-keys nil) ) (require 'dired-single) (setq dired-single-use-magic-buffer t) (setq dired-single-magic-buffer-name "dired - main") ; open dirs in same dired window + open files in main window ; facilitates static file browser sidebar (defun my/dired-open() (interactive) (setq file (dired-get-file-for-visit)) (if (equal (file-directory-p file) t) (progn (dired-single-buffer) ) (progn (dired-find-file-other-window) ) ) ) (defun my/dired-init () "Bunch of stuff to run for dired, either immediately or when it's loaded." ;; (define-key dired-mode-map [remap dired-find-file] 'my/dired-open) (define-key dired-mode-map [remap dired-mouse-find-file-other-window] 'my/dired-open) (define-key dired-mode-map [remap dired-up-directory] 'dired-single-up-directory)) ;; if dired's already loaded, then the keymap will be bound (if (boundp 'dired-mode-map) ;; we're good to go; just add our bindings (my/dired-init) ;; it's not loaded yet, so add our bindings to the load-hook (add-hook 'dired-load-hook 'my/dired-init)) ; icons / colors / line tunes (add-hook 'dired-mode-hook (lambda () (interactive) (all-the-icons-dired-mode 1) (hl-line-mode 1))) (use-package diredfl :commands diredfl-global-mode :init (diredfl-global-mode)) ; hide dired details by default, use `(` to toggle (add-hook 'dired-mode-hook 'dired-hide-details-mode) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; coding general (in case its ever on) (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; markdown config (used by kmn all over everything) (use-package markdown-mode :ensure t :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :init (setq markdown-command "multimarkdown")) (when (not kmn/is-dayjob) (use-package markdown-preview-mode :ensure t :if (boundp 'mdcommand) :init ;(setq markdown-preview-auto-open nil) :custom (markdown-preview-ws-port 9697) (markdown-preview-http-port 9696) (markdown-preview-host "127.0.0.1") (markdown-preview-http-host "127.0.0.1")) (setq markdown-preview-stylesheets (list "https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css")) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; origami config (use-package origami :demand :config (define-prefix-command 'origami-mode-map) (define-key ctl-x-map (kbd "z") 'origami-mode-map) (global-origami-mode) :bind (:map origami-mode-map ("o" . origami-open-node) ("O" . origami-open-node-recursively) ("c" . origami-close-node) ("C" . origami-close-node-recursively) ("a" . origami-toggle-node) ("t" . origami-recursively-toggle-node) ("R" . origami-open-all-nodes) ("M" . origami-close-all-nodes) ("v" . origami-show-only-node) ("k" . origami-previous-fold) ("j" . origami-forward-fold) ("x" . origami-reset))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Setup global keys (cua-mode 1) (windmove-default-keybindings 'meta) (global-set-key (kbd "") 'keyboard-escape-quit) (global-set-key (kbd "M-g") 'keyboard-quit) (global-set-key (kbd "M-m") 'menu-bar-open) (global-set-key (kbd "") 'delete-frame) (global-set-key (kbd "C-x C-z") nil) (global-set-key (kbd "C-g") 'goto-line) (global-set-key (kbd "C-c u") 'toggle-truncate-lines) (global-set-key (kbd "C-o") 'helm-find-files) (global-set-key (kbd "C-k") 'kmn/dired-default-directory-on-left) (global-set-key (kbd "M-a") 'mark-whole-buffer) (global-set-key (kbd "C-a") 'kmn/smart-beginning-of-line) (global-set-key (kbd "C-e") 'kmn/smart-end-of-line) (global-set-key (kbd "C-c w") (lambda () (interactive) (whitespace-mode) (whitespace-newline-mode) ) ) (global-set-key (kbd "M-k") 'delete-window) (global-set-key (kbd "M-\"") 'split-window-below) (global-set-key (kbd "M-#") 'split-window-right) ;; Lookup the current symbol at point. C-c C-d is a common keybinding ;; for this in lisp modes. (global-set-key (kbd "M-h") 'describe-bindings) (global-set-key (kbd "C-c C-d") #'helpful-at-point) (bind-key* "M-%" 'query-replace-region-or-from-top) (global-set-key (kbd "C-h") 'query-replace-region-or-from-top) ; more vscode/gui styled find/replace (global-set-key (kbd "C-s") 'isearch-forward) (global-set-key (kbd "C-f") 'isearch-forward) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Set some global config (setq inhibit-splash-screen t) ; why do you need to tell me things i know by default (setq inhibit-startup-screen t) (setq inhibit-startup-echo-area-message t) (setq-default tab-width 4) ; sanity! (electric-indent-mode 0) ; return should NOT fuck with the indentation of the previous line ;; make typing delete/overwrites selected text (delete-selection-mode 1) (setq frame-inhibit-implied-resize t) (setq pixel-scroll-precision-mode t) ;; UTF-8 as default encoding (set-default-coding-systems 'utf-8) (set-language-environment "UTF-8") (set-default-coding-systems 'utf-8-unix) ; auto revert when files/dired changes (setq global-auto-revert-non-file-buffers t) (global-auto-revert-mode 1) ; Clipboard integration (when (not kmn/is-dayjob) (use-package xclip :config (xclip-mode 1)) ) ;; use y or n instead of yes or no (fset 'yes-or-no-p 'y-or-n-p) ; org mode syntax highlight code blocks (setq org-src-fontify-natively t) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; set font for emoji -- DOES NOT WORK ON MOBILE (when (eq system-type 'windows-nt) (set-fontset-font t '(#x1f300 . #x1fad0) (cond ((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji") ((member "Noto Emoji" (font-family-list)) "Noto Emoji") ((member "Segoe UI Emoji" (font-family-list)) "Segoe UI Emoji") ((member "Symbola" (font-family-list)) "Symbola") ((member "Apple Color Emoji" (font-family-list)) "Apple Color Emoji")) ;; Apple Color Emoji should be before Symbola, but Richard Stallman skum disabled it. ;; GNU Emacs Removes Color Emoji Support on the Mac ;; http://ergoemacs.org/misc/emacs_macos_emoji.html ;; ) (custom-theme-set-faces 'user '(default ((t ( :family "MonoLisa Variable" :height 100)))) '(variable-pitch ((t (:family "Atkinson Hyperlegible" :height 120)))) '(fixed-pitch ((t ( :family "MonoLisa Variable" :height 120)))) ) ; (custom-theme-set-faces ; 'user ; '(org-agenda ((t (:inherit fixed-pitch)))) ; '(org-block ((t (:inherit fixed-pitch)))) ; '(org-code ((t (:inherit (shadow fixed-pitch))))) ; '(org-document-info ((t (:inherit fixed-pitch)))) ; '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch))))) ; '(org-indent ((t (:inherit (org-hide fixed-pitch))))) ; '(org-link ((t (:inherit (shadow fixed-pitch))))) ; '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch))))) ; '(org-property-value ((t (:inherit fixed-pitch))) t) ; '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch))))) ; '(org-table ((t (:inherit fixed-pitch)))) ; '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8)))) ; '(org-verbatim ((t (:inherit (shadow fixed-pitch))))) ;) ;(add-hook 'org-mode-hook 'variable-pitch-mode) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; line numbers ; find major mode : M-x eval-expression [enter] major-mode (require 'display-line-numbers) (defcustom display-line-numbers-exempt-modes '(org-mode org-agenda-mode) "Major modes on which to disable the linum mode, exempts them from global requirement" :group 'display-line-numbers :type 'list :version "green") (defun display-line-numbers--turn-on () "turn on line numbers but excempting certain majore modes defined in `display-line-numbers-exempt-modes'" (if (and (not (member major-mode display-line-numbers-exempt-modes)) (not (minibufferp))) (display-line-numbers-mode))) (global-display-line-numbers-mode) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; whitespace (progn ;; Make whitespace-mode with very basic background coloring for whitespaces. ;; http://xahlee.info/emacs/emacs/whitespace-mode.html (setq whitespace-style (quote (face spaces tabs newline space-mark tab-mark newline-mark ))) ;; Make whitespace-mode and whitespace-newline-mode use “¶” for end of line char and “▷” for tab. (setq whitespace-display-mappings ;; all numbers are unicode codepoint in decimal. e.g. (insert-char 182 1) '( (space-mark 32 [183] [46]) ; SPACE 32 「 」, 183 MIDDLE DOT 「·」, 46 FULL STOP 「.」 (newline-mark 10 [8629 10]) ; LINE FEED, (tab-mark 9 [8594 9] [92 9]) ; tab ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; modus-themes setup and enable (require-theme 'modus-themes) (setq modus-themes-region '(no-extend) modus-themes-fringes 'subtle modus-themes-scale-headings t ) (load-theme 'modus-vivendi :no-confirm) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; focus on text (turn on as desired/needed ; off by default (require 'focus) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; helm (setq completion-styles '(flex)) (require 'helm-color) (require 'helm-ls-git) (require 'helm-bookmark) (helm-autoresize-mode 1) (setq helm-display-header-line nil helm-autoresize-max-height 30 helm-autoresize-min-height 30) (setq helm-split-window-in-side-p t ; open helm buffer inside current window, not occupy whole other window helm-ff-file-name-history-use-recentf t helm-echo-input-in-header-line t) (global-set-key (kbd "C-x C-d") 'helm-browse-project) (global-set-key (kbd "C-x b") 'list-buffers) (global-set-key (kbd "C-x f") 'focus-mode) (global-set-key (kbd "C-x c") 'focus-read-only-mode) (define-key global-map [remap find-file] 'helm-find-files) (define-key global-map [remap occur] 'helm-occur) (define-key global-map [remap list-buffers] 'helm-buffers-list) (define-key global-map [remap dabbrev-expand] 'helm-dabbrev) (define-key global-map [remap execute-extended-command] 'helm-M-x) (define-key global-map [remap apropos-command] 'helm-apropos) (define-key global-map [remap bookmark-jump] 'helm-filtered-bookmarks) (unless (boundp 'completion-in-region-function) (define-key lisp-interaction-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point) (define-key emacs-lisp-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point)) (add-hook 'kill-emacs-hook #'(lambda () (and (file-exists-p "$CONF_FILE") (delete-file "$CONF_FILE")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; activate helm after its fully configured ;(helm-mode 1) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; diminish config ; https://melpa.org/#/manage-minor-mode ; M-x: manage-minor-mode ; ; M-x: describe-mode ;(require 'diminish) ;(diminish 'rainbow-mode) ; Hide lighter from mode-line ;(diminish 'org-habit) ; im well aware i have org-habit enabled globally. thanks ;(diminish 'helm-mode) ;(diminish 'eldoc-mode) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; doom-modeline (require 'doom-modeline) (setq all-the-icons-color-icons nil) (setq find-file-visit-truename t) (doom-modeline-mode 1) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; flyspell (when (not kmn/is-dayjob) (require 'flyspell) (setenv "LANG" "en_US") (setq ispell-program-name "hunspell") (setq ispell-dictionary "en_US") (use-package flyspell :demand t :config (use-package flyspell-correct-helm) (defun flyspell-most-modes() (add-hook 'text-mode-hook (lambda () (flyspell-mode 1) )) (add-hook 'prog-mode-hook (lambda () (flyspell-mode 1) )) (dolist (hook '(change-log-mode-hook log-edit-mode-hook org-agenda)) (add-hook hook (lambda () (flyspell-mode -1))))) (flyspell-most-modes) ) (defun flyspell-on-for-buffer-type () "Enable Flyspell appropriately for the major mode of the current buffer. Uses `flyspell-prog-mode' for modes derived from `prog-mode', so only strings and comments get checked. All other buffers get `flyspell-mode' to check all text. If flyspell is already enabled, does nothing." (interactive) (if (not (symbol-value flyspell-mode)) ; if not already on (progn (if (derived-mode-p 'prog-mode) (progn (message "Flyspell on (code)") (flyspell-prog-mode)) ;; else (progn (message "Flyspell on (text)") (flyspell-mode 1))) ))) (defun flyspell-toggle () "Turn Flyspell on if it is off, or off if it is on. When turning on, it uses `flyspell-on-for-buffer-type' so code-vs-text is handled appropriately." (interactive) (if (symbol-value flyspell-mode) (progn ; flyspell is on, t it off (message "Flyspell off") (flyspell-mode -1)) ; else - flyspell is off, turn it on (flyspell-on-for-buffer-type))) ; flyspell keyboard shortcuts (global-set-key (kbd "C-x y") 'flyspell-toggle) (global-set-key (kbd "C-x w") 'flyspell-correct-wrapper) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; zoom (replaces golden-ratio) (require 'zoom) (setq zoom-size '(0.618 . 0.618)) (zoom-mode t) (global-set-key (kbd "C-x +") 'zoom) ; zoom-mode can be bound to a key for toggle purposes (custom-set-variables '(zoom-ignored-major-modes '(dired-mode)) '(temp-buffer-resize-mode t)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; popup windows (use-package popwin :bind ( :map popwin:keymap ("h" . popwin:close-popup-window) ("q" . kmn/popwin-quick-ref)) :config (global-set-key (kbd "C-w") popwin:keymap) (push "_quick_reference.org" popwin:special-display-config)) (popwin-mode 1) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; devdocs (when (not kmn/is-dayjob) (require 'devdocs) (require 'devdocs-browser) ; devdocs (setq devdocs-data-dir "~/devdocs.el") (global-set-key (kbd "C-x m") 'devdocs-lookup) ; devdocs-browser (setq devdocs-browser-cache-directory "~/devdocs-browser") (global-set-key (kbd "C-x n") 'devdocs-browser-open) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; tabs-bar ;(tab-bar-mode t) ;(burly-tabs-mode 1) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; tab line via centaur tabs (require 'centaur-tabs) (setq centaur-tabs-set-bar 'under) (setq centaur-tabs-set-close-button nil) (setq centaur-tabs-set-modified-marker t) (setq centaur-tabs-set-icons t) (setq centaur-tabs-plain-icons t) (setq centaur-tabs-cycle-scope 'tabs) (setq centaur-tabs-show-new-tab-button nil) (add-hook 'dired-mode-hook 'centaur-tabs-local-mode) (add-hook 'org-agenda-mode 'centaur-tabs-local-mode) (global-set-key (kbd "C-c t i") 'centaur-tabs-backward) (global-set-key (kbd "C-c t ") 'centaur-tabs-backward) (global-set-key (kbd "C-c t e") 'centaur-tabs-forward) (global-set-key (kbd "C-c t ") 'centaur-tabs-forward) (global-set-key (kbd "C-c t y") 'centaur-tabs-local-mode) (global-set-key (kbd "C-c t ") 'centaur-tabs-local-mode) (global-set-key (kbd "C-c t ") 'centaur-tabs-local-mode) (defun centaur-tabs-buffer-groups () "`centaur-tabs-buffer-groups' control buffers' group rules. Group centaur-tabs with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode'. All buffer name start with * will group to \"Emacs\". Other buffer group by `centaur-tabs-get-group-name' with project name." (list (cond ((string-equal "*" (substring (buffer-name) 0 1)) (memq major-mode '(magit-process-mode magit-status-mode magit-diff-mode magit-log-mode magit-file-mode magit-blob-mode magit-blame-mode )) "Misc") ((derived-mode-p 'dired-mode) "Dired") ((memq major-mode '(helpful-mode help-mode)) "Help") (t (centaur-tabs-get-group-name (current-buffer)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; persp-mode (setq persp-auto-resume-time -1.0) (with-eval-after-load "persp-mode-autoloads" (setq wg-morph-on nil) ;; switch off animation (setq persp-autokill-buffer-on-remove 'kill-weak) (add-hook 'window-setup-hook #'(lambda () (persp-mode 1)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; scratch buffer ; set mode options -- borrowed from : https://emacsredux.com/blog/2014/07/25/configure-the-scratch-buffers-mode/ ; fundamental-mode / text-mode / org-mode (setq initial-major-mode 'text-mode) (setq initial-scratch-message "original scratch buffer") ; persistent-scratch (melpa) (persistent-scratch-autosave-mode 0) (global-set-key (kbd "C-c r S") 'persistent-scratch-save) (global-set-key (kbd "C-c r r") 'persistent-scratch-restore) (global-set-key (kbd "C-c r w") 'persistent-scratch-save-to-file) (global-set-key (kbd "C-c r l") 'persistent-scratch-restore-from-file) ; scratch.el (multi-scratch / melpa) (global-set-key (kbd "C-c r s") #'scratch) ; C-u C-c s s for mode prompt