about summary refs log tree commit diff stats
path: root/emacs
diff options
context:
space:
mode:
Diffstat (limited to 'emacs')
-rw-r--r--emacs647
1 files changed, 647 insertions, 0 deletions
diff --git a/emacs b/emacs new file mode 100644 index 0000000..e1df5dc --- /dev/null +++ b/emacs
@@ -0,0 +1,647 @@
1;;; ~/.emacs -*- lexical-binding: t; -*-
2;; Author Case Duckworth <acdw@acdw.net>
3;; Bankruptcy: 12
4
5;;; Initialization -- see also ~/.emacs.d/early-init.el
6
7(setopt custom-file (locate-user-emacs-file "custom.el"))
8(load custom-file :no-error)
9
10(defvar private-file (locate-user-emacs-file "private.el")
11 "Private customizations")
12(load private-file :no-error) ; might as well do this now
13
14;; (load-theme 'modus-operandi :no-confirm)
15
16(define-advice startup-echo-area-message (:override ())
17 (if (get-buffer "*Warnings*")
18 ";_;"
19 "^_^"))
20
21(defun create-missing-directories ()
22 "Automatically create missing directories."
23 (let ((target-dir (file-name-directory buffer-file-name)))
24 (unless (file-exists-p target-dir)
25 (make-directory target-dir :parents))))
26
27(defun delete-trailing-whitespace-except-current-line ()
28 (save-excursion
29 (delete-trailing-whitespace (point-min)
30 (line-beginning-position))
31 (delete-trailing-whitespace (line-end-position)
32 (point-max))))
33
34(defun run-after-frame-init (func)
35 "Run FUNC after the first frame is initialized.
36If already so, run FUNC immediately."
37 (cond
38 ((daemonp)
39 (add-hook 'server-after-make-frame-hook func)
40 (advice-add func :after (lambda ()
41 (remove-hook 'server-after-make-frame-hook
42 func)
43 (advice-remove func
44 'after-frame-init-removing-advice))
45
46
47 '((name . after-frame-init-removing-advice))))
48 ((not after-init-time)
49 (add-hook 'after-init-hook func))
50 (:else (funcall func))))
51
52(defun first-found-font (&rest cands)
53 "Return the first font of CANDS that is installed, or nil."
54 (cl-loop with ffl = (font-family-list)
55 for font in cands
56 if (member font ffl)
57 return font))
58
59(defun setup-faces ()
60 "Setup Emacs faces."
61 (set-face-attribute 'variable-pitch nil
62 :family (first-found-font "Public Sans")
63 :height 1.0)
64 (set-face-attribute 'fixed-pitch-serif nil
65 :inherit 'default)
66
67 ;; Emojis
68 (cl-loop with ffl = (font-family-list)
69 for font in '("Noto Emoji" "Noto Color Emoji"
70 "Segoe UI Emoji" "Apple Color Emoji"
71 "FreeSans" "FreeMono" "FreeSerif"
72 "Unifont" "Symbola")
73 if (member font ffl)
74 do (set-fontset-font t 'symbol font))
75
76 ;; International fonts
77 (cl-loop with ffl = (font-family-list)
78 for (charset . font)
79 in '((latin . "Noto Sans")
80 (han . "Noto Sans CJK SC Regular")
81 (kana . "Noto Sans CJK JP Regular")
82 (hangul . "Noto Sans CJK KR Regular")
83 (cjk-misc . "Noto Sans CJK KR Regular")
84 (khmer . "Noto Sans Khmer")
85 (lao . "Noto Sans Lao")
86 (burmese . "Noto Sans Myanmar")
87 (thai . "Noto Sans Thai")
88 (ethiopic . "Noto Sans Ethiopic")
89 (hebrew . "Noto Sans Hebrew")
90 (arabic . "Noto Sans Arabic")
91 (gujarati . "Noto Sans Gujarati")
92 (devanagari . "Noto Sans Devanagari")
93 (kannada . "Noto Sans Kannada")
94 (malayalam . "Noto Sans Malayalam")
95 (oriya . "Noto Sans Oriya")
96 (sinhala . "Noto Sans Sinhala")
97 (tamil . "Noto Sans Tamil")
98 (telugu . "Noto Sans Telugu")
99 (tibetan . "Noto Sans Tibetan"))
100 if (member font ffl)
101 do (set-fontset-font t charset font)))
102
103(defun cancel-colors ()
104 (mapatoms
105 (lambda (atom)
106 (when (facep atom)
107 (set-face-attribute atom nil
108 :foreground 'unspecified
109 :background 'unspecified
110 :weight 'unspecified
111 :slant 'unspecified
112 :underline 'unspecified
113 :overline 'unspecified
114 :strike-through 'unspecified
115 :box 'unspecified
116 :inverse-video nil
117 :stipple nil
118 :extend nil)))))
119
120(defun set-faces (faces)
121 (dolist (face faces)
122 (apply #'set-face-attribute (car face) nil (cdr face))))
123
124(font-lock-mode -1)
125(cancel-colors)
126(run-after-frame-init
127 (defun uncancel-colors ()
128 (set-faces `((font-lock-comment-face :italic t)
129 (font-lock-comment-delimiter-face :italic t)
130 (font-lock-doc-face :italic t)
131 (font-lock-keyword-face :bold t)
132 (bold :bold t) (italic :italic t) (underline :underline t)
133 (mode-line-active :box t :background "light goldenrod")
134 (mode-line-inactive :box "pale goldenrod"
135 :background "pale goldenrod")
136 (link :foreground "navy" :underline t)
137 (completions-annotations :inherit 'italic)
138 (highlight :background "wheat")
139 (match :background "wheat")
140 (isearch :background "sea green" :foreground "white")
141 (isearch-fail :background "tomato")
142 (lazy-highlight :background "dark sea green")
143 (region :background "papaya whip")
144 (query-replace :background "wheat")
145 (shadow :foreground "orchid")
146 (show-paren-match :background "goldenrod")
147 (success :foreground "sea green" :italic t)
148 (warning :foreground "brown" :italic t)
149 (error :foreground "red" :italic t)
150 (trailing-whitespace :background "tomato")
151 (vertical-border :foreground "gray")
152 (completions-highlight :background "wheat")))))
153
154(defun recancel-colors ()
155 (interactive)
156 (cancel-colors)
157 (uncancel-colors))
158
159(defmacro inhibit-messages (&rest body)
160 "Inhibit all messages in BODY."
161 (declare (indent defun))
162 `(cl-letf (((symbol-function 'message) #'ignore))
163 ,@body))
164
165(defun kill-buffer-dwim (&optional buffer-or-name)
166 "Kill BUFFER-OR-NAME or the current buffer."
167 (interactive "P")
168 (cond
169 ((bufferp buffer-or-name)
170 (kill-buffer buffer-or-name))
171 ((null buffer-or-name)
172 (kill-current-buffer))
173 (:else
174 (kill-buffer (read-buffer "Kill: " nil :require-match)))))
175
176(defun other-window-dwim (&optional arg)
177 "Switch to another window/buffer.
178Calls `other-window', which see, unless
179- the current window is alone on its frame
180- `other-window-dwim' is called with \\[universal-argument]
181In these cases, switch to the last-used buffer."
182 (interactive "P")
183 (if (or arg (one-window-p))
184 (switch-to-buffer (other-buffer) nil t)
185 (other-window 1)))
186
187(defun delete-window-dwim ()
188 "Delete the current window or bury its buffer.
189If the current window is alone in its frame, bury the buffer
190instead."
191 (interactive)
192 (unless (ignore-errors (delete-window) t)
193 (bury-buffer)))
194
195(defun cycle-spacing* (&optional n)
196 "Negate N argument on `cycle-spacing'."
197 (interactive "*p")
198 (cycle-spacing (- n)))
199
200(defun find-user-init-file (&optional arg)
201 "Edit `user-init-file' in current window.
202With ARG, edit in other window."
203 (interactive "P")
204 (funcall (if arg #'find-file-other-window #'find-file)
205 user-init-file))
206
207(defun find-user-private-file (&optional arg)
208 "Edit `private-file'.
209With ARG, edit in other window."
210 (interactive "P")
211 (funcall (if arg #'find-file-other-window #'find-file)
212 private-file))
213
214(defun package-ensure (pkg)
215 "Install PKG if it's not already installed."
216 (unless (package-installed-p pkg)
217 (package-install pkg)))
218
219;;; Basic settings
220
221(tooltip-mode -1)
222
223;; Dialogs
224(setopt use-dialog-box nil)
225(setopt use-file-dialog nil)
226(setopt read-answer-short t)
227(setopt use-short-answers t)
228(setopt echo-keystrokes 0.01)
229
230;; Cursor
231(blink-cursor-mode -1)
232
233;; Fonts
234(setopt x-underline-at-descent-line t)
235(run-after-frame-init #'setup-faces)
236
237;;; Look and feel
238
239;; Whitespace
240(setopt whitespace-style '(face trailing tabs tab-mark))
241(global-whitespace-mode)
242(add-hook 'before-save-hook #'delete-trailing-whitespace-except-current-line)
243(set-face-attribute 'whitespace-tab nil :background nil :foreground "#888")
244(setf (alist-get 'tab-mark whitespace-display-mappings)
245 '(9 [?· 9] [?» 9] [?\\ 9]))
246
247;;; Completions
248
249(setopt tab-always-indent 'complete)
250(setopt completion-styles '(basic partial-completion substring flex))
251
252(setopt completion-ignore-case t)
253(setopt read-buffer-completion-ignore-case t)
254(setopt read-file-name-completion-ignore-case t)
255(setopt completion-flex-nospace t)
256
257(setopt completion-show-help nil)
258(setopt completions-detailed t)
259(setopt completions-group t)
260(setopt completion-auto-help 'visible)
261(setopt completion-auto-select 'second-tab)
262(setopt completions-header-format nil)
263(setopt completions-format 'one-column)
264(setopt completions-max-height 10)
265
266(keymap-set minibuffer-local-map "C-p" #'minibuffer-previous-completion)
267(keymap-set minibuffer-local-map "C-n" #'minibuffer-next-completion)
268
269(setopt enable-recursive-minibuffers t)
270(setopt minibuffer-default-prompt-format " [%s]")
271(minibuffer-depth-indicate-mode)
272(minibuffer-electric-default-mode)
273
274(setopt file-name-shadow-properties '(invisible t intangible t))
275(file-name-shadow-mode)
276
277(setopt history-length t)
278(setopt history-delete-duplicates t)
279(setopt savehist-save-minibuffer-history t)
280(setopt savehist-autosave-interval 5)
281(savehist-mode)
282
283(define-minor-mode truncate-lines-local-mode
284 "Toggle `truncate-lines' in the current buffer."
285 :lighter ""
286 (setq-local truncate-lines truncate-lines-local-mode))
287
288(add-hook 'completion-list-mode-hook #'truncate-lines-local-mode)
289(add-hook 'minibuffer-setup-hook #'truncate-lines-local-mode)
290
291;; Consult/Marginalia
292
293(package-ensure 'consult)
294(require 'consult)
295(keymap-global-set "C-x b" #'consult-buffer)
296(keymap-global-set "C-x 4 b" #'consult-buffer-other-window)
297(keymap-global-set "C-x 5 b" #'consult-buffer-other-frame)
298(keymap-global-set "C-x r b" #'consult-bookmark)
299(keymap-global-set "M-y" #'consult-yank-pop)
300(keymap-global-set "M-g g" #'consult-goto-line)
301(keymap-global-set "M-g M-g" #'consult-goto-line)
302(keymap-global-set "M-g o" #'consult-outline)
303(keymap-global-set "M-g m" #'consult-mark)
304(keymap-global-set "M-g i" #'consult-imenu)
305(keymap-global-set "M-s d" #'consult-find)
306(keymap-global-set "M-s D" #'consult-locate)
307(keymap-global-set "M-s l" #'consult-line)
308(keymap-global-set "M-s k" #'consult-keep-lines)
309(keymap-global-set "M-s u" #'consult-focus-lines)
310(keymap-global-set "M-s e" #'consult-isearch-history)
311(keymap-set isearch-mode-map "M-e" #'consult-isearch-history)
312(keymap-set isearch-mode-map "M-s e" #'consult-isearch-history)
313(keymap-set isearch-mode-map "M-s l" #'consult-line)
314(setopt xref-show-xrefs-function #'consult-xref)
315(setopt xref-show-definitions-function
316 #'xref-show-definitions-completing-read)
317(setopt consult-preview-key "M-.")
318
319(package-ensure 'marginalia)
320(marginalia-mode)
321
322;;; Files
323
324(setopt auto-revert-verbose nil)
325(setopt global-auto-revert-non-file-buffers t)
326(global-auto-revert-mode)
327
328(setopt create-lockfiles nil)
329(setopt mode-require-final-newline t)
330(setopt view-read-only t)
331(setopt save-silently t)
332(setopt delete-by-moving-to-trash t)
333(setopt auto-save-default nil)
334(setopt auto-save-no-message t)
335(setopt auto-save-interval 2)
336(setopt auto-save-timeout 2)
337(setopt auto-save-visited-interval 2)
338(setopt remote-file-name-inhibit-auto-save t)
339(setopt remote-file-name-inhibit-auto-save-visited t)
340(add-to-list 'auto-save-file-name-transforms
341 `(".*" ,(locate-user-emacs-file "auto-save/") t))
342(auto-save-visited-mode)
343
344(setopt backup-by-copying t)
345(setopt version-control t)
346(setopt kept-new-versions 3)
347(setopt kept-old-versions 3)
348(setopt delete-old-versions t)
349(add-to-list 'backup-directory-alist '("^/dev/shm/" . nil))
350(add-to-list 'backup-directory-alist '("^/tmp/" . nil))
351(when-let ((xrd (getenv "XDG_RUNTIME_DIR")))
352 (add-to-list 'backup-directory-alist (cons xrd nil)))
353(add-to-list 'backup-directory-alist
354 (cons "." (locate-user-emacs-file "backup/"))
355 :append)
356
357(setopt recentf-max-menu-items 100)
358(setopt recentf-max-saved-items nil)
359(setopt recentf-case-fold-search t)
360(with-eval-after-load 'recentf
361 (add-to-list 'recentf-exclude "-autoloads.el\\'"))
362(add-hook 'buffer-list-update-hook #'recentf-track-opened-file)
363(add-hook 'after-save-hook #'recentf-save-list)
364(recentf-mode)
365
366(setopt save-place-forget-unreadable-files (eq system-type 'gnu/linux))
367(save-place-mode)
368
369(add-hook 'find-file-not-found-functions #'create-missing-directories)
370
371;;; Buffers
372
373(setopt uniquify-buffer-name-style 'forward)
374
375;; Encodings
376(set-language-environment "UTF-8")
377(setopt buffer-file-coding-system 'utf-8-unix)
378(setopt coding-system-for-read 'utf-8-unix)
379(setopt coding-system-for-write 'utf-8-unix)
380(setopt default-process-coding-system '(utf-8-unix . utf-8-unix))
381(setopt locale-coding-system 'utf-8-unix)
382(set-charset-priority 'unicode)
383(prefer-coding-system 'utf-8-unix)
384(set-default-coding-systems 'utf-8-unix)
385(set-terminal-coding-system 'utf-8-unix)
386(set-keyboard-coding-system 'utf-8-unix)
387(pcase system-type
388 ((or 'ms-dos 'windows-nt)
389 (set-clipboard-coding-system 'utf-16-le)
390 (set-selection-coding-system 'utf-16-le))
391 (_
392 (set-selection-coding-system 'utf-8)
393 (set-clipboard-coding-system 'utf-8)))
394
395;;; Search
396
397(setopt isearch-lazy-count t)
398(setopt isearch-regexp-lax-whitespace t)
399(setopt isearch-wrap-pause 'no)
400(setopt search-default-mode t)
401(setopt search-whitespace-regexp ".*?") ; swiper-style
402(setopt search-ring-max 256)
403(setopt regexp-search-ring-max 256)
404
405(define-advice isearch-cancel (:before () add-to-history)
406 "Add search string to history when canceling isearch."
407 (unless (string-equal "" isearch-string)
408 (isearch-update-ring isearch-string isearch-regexp)))
409
410(package-ensure 'isearch-mb)
411(with-eval-after-load 'isearch-mb
412 (with-eval-after-load 'consult
413 (add-to-list 'isearch-mb--with-buffer #'consult-isearch-history)
414 (keymap-set isearch-mb-minibuffer-map "M-r" #'consult-isearch-history)
415 (add-to-list 'isearch-mb--after-exit #'consult-line)
416 (keymap-set isearch-mb-minibuffer-map "M-s l" #'consult-line)))
417(isearch-mb-mode)
418
419;;; Keybinds
420
421(keymap-global-set "C-x C-c" #'save-buffers-kill-terminal)
422(keymap-global-set "C-x C-k" #'kill-buffer-dwim)
423(keymap-global-set "M-o" #'other-window-dwim)
424(keymap-global-set "C-x o" #'other-window-dwim)
425(keymap-global-set "C-x 0" #'delete-window-dwim)
426(keymap-global-set "M-SPC" #'cycle-spacing*)
427(keymap-global-set "C-x C-b" #'ibuffer)
428(keymap-global-set "M-/" #'hippie-expand)
429(keymap-global-set "M-u" #'universal-argument)
430(keymap-set universal-argument-map "M-u" #'universal-argument-more)
431(keymap-global-set "C-c i" #'find-user-init-file)
432(keymap-global-set "C-c p" #'find-user-private-file)
433(keymap-global-set "C-c s" #'eshell)
434
435(keymap-global-set "C-c t"
436 (defun insert-current-iso8601 ()
437 (interactive)
438 (insert (format-time-string "%FT%TZ" (current-time) t))))
439
440(keymap-global-set "C-M-\\"
441 (defun indent-buffer ()
442 (interactive)
443 (save-mark-and-excursion
444 (indent-region (point-min) (point-max)))))
445
446;; Un-keybinds
447(keymap-global-unset "C-<wheel-down>" t)
448(keymap-global-unset "C-<wheel-up>" t)
449;; I only ever fat-finger this key and never want to change encoding
450(keymap-global-unset "C-\\" t)
451(keymap-global-unset "C-z" t)
452
453;; Key settings
454(setopt set-mark-command-repeat-pop t)
455
456;;; Writing
457
458(add-hook 'text-mode-hook #'visual-line-mode)
459
460;;; Hungry delete
461;; I was using the hungry-delete package, but it turns out I can get *most* of
462;; the features with just these functions.
463
464(defun %hungry-delete (skip-fn del-key)
465 (let ((here (point)))
466 (funcall skip-fn " \t")
467 (if (or (= (point) here)
468 (apply 'derived-mode-p
469 '(eshell-mode ; add other modes to skip here.
470 nim-mode
471 pyton-mode)))
472 (call-interactively (keymap-lookup (list (current-local-map)
473 (current-global-map))
474 del-key))
475 (delete-region (point) here))))
476
477(defun hungry-delete-forward ()
478 "Delete forward, hungrily."
479 (interactive)
480 (%hungry-delete #'skip-chars-forward "C-d"))
481
482(defun hungry-delete-backward ()
483 "Delete backward, hungrily."
484 (interactive)
485 (%hungry-delete #'skip-chars-backward "DEL"))
486
487(define-minor-mode hungry-delete-mode
488 "Hungrily delete stuff."
489 :global t
490 :lighter " h"
491 :keymap (define-keymap
492 "DEL" #'hungry-delete-backward
493 "C-d" #'hungry-delete-forward))
494
495(hungry-delete-mode)
496
497;;; Programming
498
499(add-hook 'prog-mode-hook #'electric-pair-local-mode)
500(setopt tab-width 8)
501(setopt sh-basic-offset tab-width)
502(setopt perl-indent-level tab-width)
503(setopt c-basic-offset tab-width)
504
505;; Elisp
506(defun pulse@eval (start end &rest _)
507 (pulse-momentary-highlight-region start end))
508
509(keymap-set emacs-lisp-mode-map "C-c C-c" #'eval-defun)
510(keymap-set emacs-lisp-mode-map "C-c C-b"
511 (defun eval-buffer@pulse () (interactive)
512 (eval-buffer)
513 (pulse@eval (point-min) (point-max))))
514(advice-add 'eval-region :after #'pulse@eval)
515
516(defvar space-indent-modes '(emacs-lisp-mode
517 lisp-interaction-mode
518 lisp-mode
519 scheme-mode
520 python-mode
521 haskell-mode
522 text-mode
523 web-mode
524 css-mode)
525 "Modes to indent with spaces, not tabs.")
526
527(defun indent-tabs-mode-maybe ()
528 (setq indent-tabs-mode
529 (if (apply #'derived-mode-p space-indent-modes) nil t)))
530(add-hook 'prog-mode-hook #'indent-tabs-mode-maybe)
531
532;; Makefile
533(setopt makefile-backslash-align nil)
534(setopt makefile-cleanup-continuations t)
535
536(add-hook 'makefile-mode-hook
537 (defun makefile-stop-complaining ()
538 (remove-hook 'write-file-functions
539 'makefile-warn-suspicious-lines t)
540 (remove-hook 'write-file-functions
541 'makefile-warn-continuations t)))
542
543;; Scheme -- CHICKEN
544(setopt scheme-program-name (or (executable-find "csi")))
545(add-to-list 'auto-mode-alist '("\\.egg\\'" . scheme-mode))
546
547;; Scheme Indentation
548(defun scheme-module-indent (state indent-point normal-indent) 0)
549(put 'module 'scheme-indent-function 'scheme-module-indent)
550(put 'and-let* 'scheme-indent-function 1)
551(put 'parameterize 'scheme-indent-function 1)
552(put 'handle-exceptions 'scheme-indent-function 1)
553(put 'when 'scheme-indent-function 1)
554(put 'unless 'scheme-indent-function 1)
555(put 'match 'scheme-indent-function 1)
556
557;; Geiser
558(package-ensure 'geiser)
559(package-ensure 'geiser-chicken)
560(setopt geiser-mode-auto-p nil)
561(setopt geiser-repl-history-filename "~/.emacs.d/geiser-history")
562(setopt geiser-chicken-init-file "~/.csirc")
563(add-hook 'scheme-mode-hook #'geiser-mode)
564(add-hook 'geiser-repl-mode-hook #'electric-pair-local-mode)
565(advice-add 'geiser-eval-region :after #'pulse@eval)
566
567;; VC
568(add-hook 'vc-dir-mode-hook #'hl-line-mode)
569(defun vc-jump ()
570 (interactive)
571 (vc-dir default-directory))
572(keymap-global-set "C-x v j" #'vc-jump)
573
574;;; Compilation
575
576(setopt compilation-always-kill t)
577(setopt compilation-ask-about-save nil)
578
579;;; Miscellaneous settings
580
581(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
582(add-hook 'prog-mode-hook #'auto-fill-mode)
583(add-hook 'prog-mode-hook #'display-fill-column-indicator-mode)
584(add-hook 'prog-mode-hook #'electric-pair-local-mode)
585(delete-selection-mode)
586(global-so-long-mode)
587(setopt display-fill-column-indicator-character ?·)
588(setopt disabled-command-function nil)
589(setopt electric-pair-skip-whitespace 'chomp)
590(setopt fill-column 80)
591(setopt recenter-positions '(top middle bottom))
592(setopt show-paren-delay 0.01)
593(setopt show-paren-style 'parenthesis)
594(setopt show-paren-when-point-in-periphery t)
595(setopt show-paren-when-point-inside-paren t)
596(show-paren-mode)
597
598(with-eval-after-load 'ibuffer
599 (add-hook 'ibuffer-mode-hook #'hl-line-mode))
600
601(with-eval-after-load 'proced
602 (add-hook 'proced-mode-hook #'hl-line-mode))
603
604;;; RCIRC
605
606(setopt rcirc-kill-channel-buffers t)
607(setopt rcirc-display-server-buffer nil)
608
609(defun run-rcirc ()
610 (interactive)
611 (shell-command "chat up")
612 (call-interactively #'rcirc))
613
614(add-hook 'rcirc-mode-hook
615 (defun @rcirc-mode ()
616 (whitespace-mode -1)))
617
618(add-hook 'rcirc-mode-hook #'rcirc-track-minor-mode)
619(add-hook 'rcirc-mode-hook #'rcirc-omit-mode)
620(add-hook 'rcirc-mode-hook #'visual-line-mode)
621(add-hook 'rcirc-mode-hook
622 (lambda () (whitespace-mode -1)))
623
624;;; Eshell
625
626(setopt eshell-prompt-function
627 (defun @eshell-prompt ()
628 (concat "* " (abbreviate-file-name (eshell/pwd))
629 (if (zerop (user-uid)) " # " " $ "))))
630
631;;; Browsing
632
633;; Dired (files)
634(with-eval-after-load 'dired
635 (setopt dired-dwim-target t)
636 (setopt dired-listing-switches "-alF")
637 (setopt dired-ls-F-marks-symlinks t)
638 (keymap-set dired-mode-map "C-j" #'dired-up-directory)
639 (add-hook 'dired-mode-hook #'hl-line-mode))
640
641;; Elpher (gemini/gopher)
642(package-ensure 'elpher)
643
644;; Browse-url (http)
645(setopt browse-url-new-window-flag t)
646(setopt browse-url-firefox-arguments '("--new-tab"))
647(setopt browse-url-firefox-new-window-is-tab t)