summary refs log tree commit diff stats
path: root/basics.el
diff options
context:
space:
mode:
Diffstat (limited to 'basics.el')
-rw-r--r--basics.el376
1 files changed, 376 insertions, 0 deletions
diff --git a/basics.el b/basics.el new file mode 100644 index 0000000..06f5ece --- /dev/null +++ b/basics.el
@@ -0,0 +1,376 @@
1;;; basics.el --- Super basic Emacs settings -*- lexical-binding: t -*-
2
3;;; Commentary:
4
5;; These are the settings that I literally cannot live without. Basic
6;; settings, built-in packages, that kind of stuff. Everything else
7;; goes in init.el.
8
9;;; Code:
10
11;;; Directories
12
13(defmacro defdir (name directory &optional docstring makedir)
14 "Define a variable and a function NAME expanding to DIRECTORY.
15DOCSTRING is applied to the variable; its default is DIRECTORY's
16path. If MAKEDIR is non-nil, the directory and its parents will
17be created."
18 (declare (indent 2) (doc-string 3))
19 `(progn
20 (defvar ,name (expand-file-name ,directory)
21 ,(concat (or docstring (format "%s" directory)) "\n"
22 "Defined by `defdir'."))
23 (defun ,name (file &optional mkdir)
24 ,(concat "Expand FILE relative to variable `" (symbol-name name) "'.\n"
25 "If MKDIR is non-nil, parent directories are created.\n"
26 "Defined by `defdir'.")
27 (let ((file-name (expand-file-name
28 (convert-standard-filename file) ,name)))
29 (when mkdir
30 (make-directory (file-name-directory file-name) :parents))
31 file-name))
32 ,(if makedir
33 `(make-directory ,directory :parents)
34 `(unless (file-exists-p ,directory)
35 (warn "Directory `%s' doesn't exist." ,directory)))))
36
37(defdir etc/ (locate-user-emacs-file "etc/")
38 "Where various Emacs files are placed."
39 :makedir)
40
41(defdir lisp/ (locate-user-emacs-file "lisp/")
42 "My bespoke elisp files."
43 :makedir)
44(push lisp/ load-path)
45
46(defdir sync/ "~/Sync/"
47 "My Syncthing directory."
48 :makedir)
49
50(defdir private/ (sync/ "emacs/private/")
51 "Private files and stuff."
52 :makedir)
53(push private/ load-path)
54
55(use-package no-littering
56 :ensure t :demand t
57 :preface
58 (setq-default no-littering-etc-directory etc/
59 no-littering-var-directory etc/))
60
61;;; Settings
62
63;; Async
64(setq-default async-shell-command-buffer 'new-buffer
65 async-shell-command-display-buffer nil)
66
67;; Scrolling
68(setq-default auto-hscroll-mode t
69 auto-window-vscroll nil
70 fast-but-imprecise-scrolling t
71 hscroll-margin 1
72 hscroll-step 1
73 scroll-conservatively 25
74 scroll-margin 0
75 scroll-preserve-screen-position 1
76 scroll-step 1)
77(scroll-bar-mode -1)
78(horizontal-scroll-bar-mode -1)
79(pixel-scroll-precision-mode)
80
81;; Cursor
82(setq-default cursor-in-non-selected-windows 'hollow
83 cursor-type 'bar
84 blink-cursor-blinks 1
85 blink-cursor-interval 0.25
86 blink-cursor-delay 0.25)
87(blink-cursor-mode)
88
89;; Mouse
90(setq-default mouse-drag-copy-region t
91 mouse-wheel-progressive-speed nil
92 mouse-yank-at-point t)
93
94;; Dialogs
95(unless (boundp 'use-short-answers)
96 (fset 'yes-or-no-p 'y-or-n-p))
97
98(setq-default read-answer-short t
99 use-dialog-box nil
100 use-file-dialog nil
101 use-short-answers t)
102
103;; Minibuffer
104(setq-default completion-ignore-case t
105 read-buffer-completion-ignore-case t
106 read-file-name-completion-ignore-case t
107 completions-detailed t
108 enable-recursive-minibuffers t
109 file-name-shadow-properties '(invisible t intangible t)
110 minibuffer-eldef-shorten-default t
111 minibuffer-prompt-properties '( read-only t
112 cursor-intangible t
113 face minibuffer-prompt))
114(file-name-shadow-mode)
115(minibuffer-electric-default-mode)
116
117(require 'savehist)
118(setq-default history-length 1024
119 history-delete-duplicates t
120 ;; savehist-file (etc/ "savehist.el")
121 savehist-save-minibuffer-history t
122 savehist-autosave-interval 30)
123(savehist-mode)
124
125;; Undo
126(setq-default undo-limit (* 10 1024 1024))
127
128;; Killing and yanking
129(setq-default kill-do-not-save-duplicates t
130 kill-read-only-ok t
131 save-interprogram-paste-before-kill t
132 yank-pop-change-selection t)
133(delete-selection-mode)
134
135;; Notifying the user
136(setq-default echo-keystrokes 0.01
137 ring-bell-function #'ignore)
138
139;; Point and mark
140(setq-default set-mark-command-repeat-pop t)
141
142;; The system
143(setq-default read-process-output-max (* 10 1024 1024))
144
145;; Startup
146(setq-default inhibit-startup-screen t
147 initial-buffer-choice t
148 initial-scratch-message nil)
149
150;; (menu-bar-mode -1)
151(tool-bar-mode -1)
152(tooltip-mode -1)
153
154;; Text editing
155(setq-default fill-column 80
156 sentence-end-double-space t
157 tab-width 8)
158(global-so-long-mode)
159
160(setq-default show-paren-delay 0.01
161 show-paren-style 'parenthesis
162 show-paren-when-point-in-periphery t
163 show-paren-when-point-inside-paren t)
164(show-paren-mode)
165(electric-pair-mode)
166
167;; Encodings
168(set-language-environment "UTF-8")
169(setq-default buffer-file-coding-system 'utf-8-unix
170 coding-system-for-read 'utf-8-unix
171 coding-system-for-write 'utf-8-unix
172 default-process-coding-system '(utf-8-unix . utf-8-unix)
173 locale-coding-system 'utf-8-unix)
174(set-charset-priority 'unicode)
175(prefer-coding-system 'utf-8-unix)
176(set-default-coding-systems 'utf-8-unix)
177(set-terminal-coding-system 'utf-8-unix)
178(set-keyboard-coding-system 'utf-8-unix)
179(pcase system-type
180 ((or 'ms-dos 'windows-nt)
181 (set-clipboard-coding-system 'utf-16-le)
182 (set-selection-coding-system 'utf-16-le))
183 (_
184 (set-selection-coding-system 'utf-8)
185 (set-clipboard-coding-system 'utf-8)))
186
187;; Abbrev
188(setq-default abbrev-file-name (sync/ "abbrev.el")
189 save-abbrevs 'silently)
190
191;; Files
192(setq-default auto-revert-verbose nil
193 global-auto-revert-non-file-buffers t
194 create-lockfiles nil
195 find-file-visit-truename t
196 mode-require-final-newline t
197 view-read-only t
198 save-silently t)
199(global-auto-revert-mode)
200
201(setq-default auto-save-default nil
202 auto-save-interval 1
203 auto-save-no-message t
204 auto-save-timeout 1
205 auto-save-visited-interval 1)
206(add-to-list 'auto-save-file-name-transforms
207 `(".*" ,(etc/ "auto-save/" t) t))
208(auto-save-visited-mode)
209
210(setq-default backup-by-copying t
211 version-control t
212 kept-new-versions 8
213 kept-old-versions 8
214 delete-old-versions t)
215
216(require 'recentf)
217(setq-default ;; recentf-save-file (etc/ "recentf" t)
218 recentf-max-menu-items 500
219 recentf-max-saved-items nil ; Save the whole list
220 recentf-auto-cleanup 'mode)
221(add-to-list 'recentf-exclude etc/)
222(add-to-list 'recentf-exclude "-autoloads.el\\'")
223(add-hook 'buffer-list-update-hook #'recentf-track-opened-file)
224(recentf-mode)
225
226(require 'saveplace)
227(setq-default ;; save-place-file (etc/ "places.el")
228 save-place-forget-unreadable-files (eq system-type
229 'gnu/linux))
230(save-place-mode)
231
232(require 'uniquify)
233(setq uniquify-after-kill-buffer-p t
234 uniquify-buffer-name-style 'forward
235 uniquify-ignore-buffers-re "^\\*"
236 uniquify-separator path-separator)
237
238(setq-local vc-follow-symlinks t
239 vc-make-backup-files t)
240
241;; Native compilation
242(setq-default native-comp-async-report-warnings-errors 'silent
243 native-comp-deferred-compilation t
244 native-compile-target-directory (etc/ "eln" t))
245(add-to-list 'native-comp-eln-load-path native-compile-target-directory)
246(when (fboundp 'startup-redirect-eln-cache)
247 (startup-redirect-eln-cache native-compile-target-directory))
248
249;; Custom file
250(setq-default custom-file (sync/ "emacs/custom.el"))
251(define-advice package--save-selected-packages (:around (orig &rest args) no-custom)
252 "Don't save `package-selected-packages' to `custom-file'."
253 (let ((custom-file null-device))
254 (apply orig args)))
255
256;; Goto Address
257(if (fboundp 'global-goto-address-mode)
258 (global-goto-address-mode)
259 (add-hook 'after-change-major-mode-hook #'goto-address-mode))
260
261;; Winner
262(winner-mode)
263
264;;; Keybindings
265
266(defun other-window|switch-buffer (arg)
267 "Call `other-window' or `switch-buffer' depending on windows.
268When called with prefix ARG, unconditionally switch buffer."
269 (interactive "P")
270 (if (or arg (one-window-p))
271 (switch-to-buffer (other-buffer) nil t)
272 (other-window 1)))
273
274(defun delete-window|bury-buffer ()
275 "Delete the current window, or bury the current buffer.
276If the current window is the only window, bury the buffer."
277 (interactive)
278 (condition-case e
279 (delete-window)
280 (t (bury-buffer))))
281
282(defun +cycle-spacing (&optional n)
283 ;; `cycle-spacing' is wildly different in 29.1 over 28.
284 "Negate N argument on `cycle-spacing'.
285That is, with a positive N, deletes newlines as well, leaving -N
286spaces. If N is negative, it will not delete newlines and leave
287N spaces."
288 (interactive "*p")
289 (cycle-spacing (- n)))
290
291(global-set-key [remap eval-expression] #'pp-eval-expression)
292(global-set-key (kbd "M-o") #'other-window|switch-buffer)
293(global-set-key (kbd "C-x 0") #'delete-window|bury-buffer)
294(global-set-key (kbd "M-SPC") #'+cycle-spacing)
295(global-set-key (kbd "C-x C-k") #'kill-this-buffer)
296
297;;; Hooks
298
299(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
300(add-hook 'find-file-not-found-functions
301 (defun create-missing-directories ()
302 "Automatically create missing directories."
303 (let ((target-dir (file-name-directory buffer-file-name)))
304 (unless (file-exists-p target-dir)
305 (make-directory target-dir :parents)))))
306(add-hook 'find-file-hook
307 (defun vc-remote-off ()
308 "Turn VC off when remote."
309 (when (file-remote-p (buffer-file-name))
310 (setq-local vc-handled-backends nil))))
311
312;;; Advice
313
314(define-advice switch-to-buffer (:after (&rest _) normal-mode)
315 "Automatically determine the mode for non-file buffers."
316 (when-let ((_ (and (eq major-mode 'fundamental-mode)))
317 (buffer-file-name (buffer-name)))
318 (normal-mode)))
319
320(define-advice canonically-space-region
321 (:around (orig &rest args) double-space-sentences)
322 "Always double-space sentences canonically."
323 (let ((sentence-end-double-space t))
324 (apply orig args)))
325
326;; With region or ...
327(defun advise-region-or-buffer (&rest _)
328 "`:before' advice to work on the active region or whole buffer.
329See also `with-region-or-buffer'."
330 (interactive (if mark-active
331 (list (region-beginning) (region-end))
332 (list (point-min) (point-max)))))
333
334(defun advise-region-or-line (&rest _)
335 "`:before' advice to work on the active region or whole line.
336See also `with-region-or-line'."
337 (interactive (if mark-active
338 (list (region-beginning) (region-end))
339 (list (line-beginning-position) (line-end-position)))))
340
341(defun advise-region-or-to-eol (&rest _)
342 "`:before' advice to work on the active region or to end of line.
343See also `with-region-or-to-eol'."
344 (INTERACTIVE (if mark-active
345 (list (region-beginning) (region-end))
346 (list (point) (line-end-position)))))
347
348(defmacro with-region-or-buffer (&rest funcs)
349 "Advise FUNCS with `advise-region-or-buffer'."
350 `(progn
351 ,@(cl-loop for fn in funcs
352 collect
353 `(advice-add ',fn :before #'advise-region-or-buffer))))
354
355(defmacro with-region-or-line (&rest funcs)
356 "Advise FUNCS with `advise-region-or-line'."
357 `(progn
358 ,@(cl-loop for fn in funcs
359 collect
360 `(advice-add ',fn :before #'advise-region-or-line))))
361
362(defmacro with-region-or-to-eol (&rest funcs)
363 "Advise FUNCS with `advise-region-or-to-eol'."
364 `(progn
365 ,@(cl-loop for fn in funcs
366 collect
367 `(advice-add ',fn :before #'advise-region-or-to-eol))))
368
369(with-region-or-buffer indent-region)
370
371;;; Packages
372
373(use-package _acdw
374 :load-path private/)
375
376;;; basics.el ends here