2021-02-26 17:31:50 +00:00
|
|
|
;;; init.el -*- lexical-binding: t; coding: utf-8 -*-
|
2021-03-01 05:58:57 +00:00
|
|
|
;; Copyright (C) 2020-2021 Case Duckworth
|
|
|
|
;;
|
2021-02-26 17:31:50 +00:00
|
|
|
;; Author: Case Duckworth <acdw@acdw.net>
|
2021-03-01 05:58:57 +00:00
|
|
|
;; Created: Sometime during Covid-19, 2020
|
2021-02-26 17:31:50 +00:00
|
|
|
;; Keywords: configuration
|
2021-03-01 05:58:57 +00:00
|
|
|
;; URL https://tildegit.org/acdw/emacs
|
|
|
|
;;
|
|
|
|
;; This file is NOT part of GNU Emacs.
|
|
|
|
;;
|
|
|
|
;;; License:
|
|
|
|
;;
|
|
|
|
;; Everyone is permitted to do whatever with this software, without
|
|
|
|
;; limitation. This software comes without any warranty whatsoever,
|
|
|
|
;; but with two pieces of advice:
|
|
|
|
;; - Don't hurt yourself.
|
|
|
|
;; - Make good choices.
|
|
|
|
;;
|
|
|
|
;;; Comentary:
|
|
|
|
;;
|
2021-03-04 23:37:17 +00:00
|
|
|
;;; Research:
|
|
|
|
;; (map! :leader (:prefix "w" :desc "Toggle full screen buffer" "f"
|
|
|
|
;; #'toggle-maximize-buffer))
|
|
|
|
;;
|
2021-03-01 05:58:57 +00:00
|
|
|
;;; Code:
|
2021-02-26 17:31:50 +00:00
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
;; User information
|
|
|
|
(setq user-full-name "Case Duckworth"
|
|
|
|
user-mail-address "acdw@acdw.net"
|
|
|
|
calendar-location-name "Baton Rouge, LA"
|
|
|
|
calendar-latitude 30.4
|
|
|
|
calendar-longitude -91.1
|
2021-03-01 20:44:43 +00:00
|
|
|
calendar-date-style 'iso
|
|
|
|
custom-file (expand-file-name "custom.el" acdw/etc-dir))
|
2021-02-26 17:31:50 +00:00
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
;; Load newer files first
|
|
|
|
(setq-default load-prefer-newer t)
|
2021-02-26 17:31:50 +00:00
|
|
|
|
2021-03-01 20:44:43 +00:00
|
|
|
;; No littering
|
|
|
|
(use-package no-littering
|
|
|
|
:demand
|
|
|
|
:init (setq no-littering-etc-directory acdw/etc-dir
|
|
|
|
no-littering-var-directory acdw/var-dir))
|
2021-02-26 17:31:50 +00:00
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
(defun when-unfocused (func &rest args)
|
|
|
|
"Run FUNC with ARGS iff all frames are out of focus."
|
|
|
|
(when (seq-every-p #'null (mapcar #'frame-focus-state (frame-list)))
|
|
|
|
(apply func args)))
|
|
|
|
|
2021-03-01 20:44:43 +00:00
|
|
|
(define-minor-mode acdw/reading-mode
|
|
|
|
"Make reading comfier."
|
|
|
|
:lighter " Read"
|
|
|
|
(if acdw/reading-mode
|
|
|
|
(progn ;; turn on
|
2021-03-01 22:57:55 +00:00
|
|
|
;; (text-scale-increase +1)
|
2021-03-01 20:44:43 +00:00
|
|
|
(display-fill-column-indicator-mode -1)
|
2021-03-01 22:57:55 +00:00
|
|
|
(setq cursor-type 'hbar)
|
2021-03-01 20:44:43 +00:00
|
|
|
(dolist (func '(visual-fill-column-mode
|
|
|
|
iscroll-mode))
|
|
|
|
(when (fboundp func)
|
|
|
|
(funcall func +1))))
|
|
|
|
(progn ;; turn off
|
2021-03-01 22:57:55 +00:00
|
|
|
;; (text-scale-increase 0)
|
|
|
|
(setq cursor-type 'bar)
|
2021-03-01 20:44:43 +00:00
|
|
|
(display-fill-column-indicator-mode +1)
|
|
|
|
(dolist (func '(visual-fill-column-mode
|
|
|
|
iscroll-mode))
|
|
|
|
(when (fboundp func)
|
|
|
|
(funcall func -1))))))
|
|
|
|
|
2021-03-01 22:57:55 +00:00
|
|
|
(defun hook--read-only-cursor ()
|
|
|
|
(setq cursor-type (if buffer-read-only 'hbar 'bar)))
|
|
|
|
(add-hook 'read-only-mode-hook #'hook--read-only-cursor)
|
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
;; Dialogs & alerts
|
|
|
|
(setq-default use-dialog-box nil) ; Don't use a dialog box
|
|
|
|
(fset 'yes-or-no-p #'y-or-n-p)
|
|
|
|
|
|
|
|
(defun flash-mode-line ()
|
|
|
|
(ding)
|
|
|
|
(invert-face 'mode-line)
|
|
|
|
(run-with-timer 0.2 nil #'invert-face 'mode-line))
|
|
|
|
|
|
|
|
(setq-default visible-bell nil ; Don't use a visible bell
|
|
|
|
ring-bell-function #'flash-mode-line)
|
|
|
|
|
|
|
|
(defun hook--gc-when-unfocused ()
|
|
|
|
(when-unfocused #'garbage-collect))
|
|
|
|
|
|
|
|
(add-function :after after-focus-change-function
|
|
|
|
#'hook--gc-when-unfocused)
|
|
|
|
|
|
|
|
;; Minibuffer
|
|
|
|
(setq-default
|
|
|
|
minibuffer-prompt-properties '(read-only t
|
2021-03-01 18:13:28 +00:00
|
|
|
cursor-intangible t
|
|
|
|
face minibuffer-prompt)
|
2021-03-01 05:58:57 +00:00
|
|
|
enable-recursive-minibuffers t
|
|
|
|
file-name-shadow-properties '(invisible t))
|
|
|
|
(file-name-shadow-mode +1)
|
|
|
|
(minibuffer-depth-indicate-mode +1)
|
|
|
|
|
|
|
|
(use-package savehist
|
2021-03-01 18:13:28 +00:00
|
|
|
:straight nil
|
|
|
|
:init
|
|
|
|
(setq-default
|
|
|
|
savehist-file (expand-file-name "history" acdw/var-dir)
|
|
|
|
savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
|
|
|
|
history-length t
|
|
|
|
history-delete-duplicates t
|
|
|
|
savehist-autosave-interval 60)
|
|
|
|
:config (savehist-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; Backups
|
|
|
|
(setq-default backup-by-copying t
|
|
|
|
delete-old-versions -1 ; Don't delete old versions
|
|
|
|
version-control t ; Make numeric backups
|
|
|
|
vc-make-backup-files t ; Backup version-controlled files
|
|
|
|
)
|
|
|
|
|
|
|
|
(let ((dir (expand-file-name "backup" acdw/var-dir)))
|
|
|
|
(make-directory dir 'parents)
|
|
|
|
(setq-default backup-directory-alist
|
|
|
|
`((".*" . ,dir))))
|
|
|
|
|
|
|
|
;; Lockfiles
|
|
|
|
(setq-default create-lockfiles nil) ; Are these necessary?
|
|
|
|
|
|
|
|
;; Autosaves
|
2021-03-01 18:13:28 +00:00
|
|
|
(setq auto-save-default nil ; Don't use `auto-save' system
|
|
|
|
)
|
2021-03-01 05:58:57 +00:00
|
|
|
(use-package super-save
|
2021-03-01 18:13:28 +00:00
|
|
|
:defer 5 ; This package can wait
|
|
|
|
:init
|
|
|
|
(setq-default
|
|
|
|
super-save-remote-files nil ; Don't save remote files
|
|
|
|
super-save-exclude '(".gpg") ; Wouldn't work anyway
|
|
|
|
super-save-auto-save-when-idle t)
|
|
|
|
:config
|
|
|
|
(super-save-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; Auto-revert
|
|
|
|
(global-auto-revert-mode +1) ; Automatically revert a file
|
|
|
|
; to its on-disk contents
|
|
|
|
|
|
|
|
(use-package saveplace
|
2021-03-01 18:13:28 +00:00
|
|
|
:straight nil
|
|
|
|
:init
|
|
|
|
(setq-default
|
|
|
|
save-place-file (expand-file-name "places" acdw/var-dir)
|
|
|
|
save-place-forget-unreadable-files (eq acdw/system :home))
|
|
|
|
:config (save-place-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(use-package recentf
|
2021-03-01 18:13:28 +00:00
|
|
|
:straight nil
|
|
|
|
:init
|
|
|
|
(setq recentf-save-file (expand-file-name "recentf" acdw/var-dir)
|
|
|
|
recentf-max-menu-items 100
|
|
|
|
recentf-max-saved-items nil
|
|
|
|
recentf-auto-cleanup 'never)
|
|
|
|
(defun maybe-save-recentf ()
|
|
|
|
"Save `recentf-file' every five minutes, but only when out of focus."
|
|
|
|
(defvar recentf--last-save (time-convert nil 'integer)
|
|
|
|
"When we last saved the `recentf-save-list'.")
|
|
|
|
|
|
|
|
(when (> (time-convert (time-since recentf--last-save) 'integer)
|
|
|
|
(* 60 5))
|
|
|
|
(setq-default recentf--last-save (time-convert nil 'integer))
|
|
|
|
(when-unfocused #'recentf-save-list)))
|
|
|
|
:config
|
|
|
|
(recentf-mode +1)
|
|
|
|
(add-to-list 'recentf-exclude acdw/var-dir)
|
|
|
|
(add-to-list 'recentf-exclude acdw/etc-dir)
|
|
|
|
(add-function :after after-focus-change-function
|
|
|
|
#'maybe-save-recentf))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
;; Uniquify
|
|
|
|
(use-package uniquify
|
2021-03-01 18:13:28 +00:00
|
|
|
:straight nil
|
|
|
|
:init
|
|
|
|
(setq-default
|
|
|
|
uniquify-buffer-name-style 'forward ; bubble 'up' the directory tree
|
|
|
|
uniquify-separator "/" ; separate path elements
|
|
|
|
uniquify-after-kill-buffer-p t ; hook into buffer kills
|
|
|
|
uniquify-ignore-buffers-re "^\\*" ; don't worry about special buffers
|
|
|
|
))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; Scratch
|
|
|
|
(setq-default
|
|
|
|
inhibit-startup-screen t ; Don't show the splash screen
|
|
|
|
initial-buffer-choice t ; Start on *scratch*
|
|
|
|
initial-scratch-message
|
|
|
|
(concat ";; Howdy, "
|
|
|
|
(nth 0 (split-string user-full-name)) "!"
|
|
|
|
" Welcome to GNU Emacs.\n\n"))
|
|
|
|
|
|
|
|
(defun immortal-scratch ()
|
|
|
|
"Don't kill *scratch* when asked to by `kill-buffer'."
|
|
|
|
(if (not (eq (current-buffer) (get-buffer "*scratch*")))
|
|
|
|
t
|
|
|
|
(bury-buffer)
|
|
|
|
nil))
|
|
|
|
(add-hook 'kill-buffer-query-functions #'immortal-scratch)
|
|
|
|
|
|
|
|
;; Easier buffer-killing
|
|
|
|
(defun kill-a-buffer (&optional prefix)
|
|
|
|
"Kill a buffer and its window, prompting only on unsaved changes.
|
|
|
|
|
|
|
|
`kill-a-buffer' uses the PREFIX argument to determine which buffer(s) to kill:
|
|
|
|
0 => Kill THIS buffer & window
|
|
|
|
4 (C-u) => Kill OTHER buffer & window
|
|
|
|
16 (C-u C-u) => Run the default `kill-buffer'."
|
|
|
|
(interactive "P")
|
|
|
|
(pcase (or (car prefix) 0)
|
|
|
|
(0 (kill-current-buffer)
|
|
|
|
(unless (one-window-p) (delete-window)))
|
|
|
|
(4 (other-window 1)
|
|
|
|
(kill-current-buffer)
|
|
|
|
(unless (one-window-p) (delete-window)))
|
|
|
|
(16 (let ((current-prefix-arg nil))
|
|
|
|
(kill-buffer)))))
|
|
|
|
|
|
|
|
(bind-key "C-x k" #'kill-a-buffer)
|
|
|
|
|
|
|
|
;; UTF-8 with LF line endings
|
|
|
|
(set-charset-priority 'unicode)
|
|
|
|
(set-language-environment "UTF-8")
|
|
|
|
|
|
|
|
(prefer-coding-system 'utf-8-unix)
|
|
|
|
(set-default-coding-systems 'utf-8-unix)
|
|
|
|
(set-terminal-coding-system 'utf-8-unix)
|
|
|
|
(set-keyboard-coding-system 'utf-8-unix)
|
|
|
|
(set-selection-coding-system 'utf-8-unix)
|
|
|
|
|
|
|
|
(setq-default
|
|
|
|
locale-coding-system 'utf-8-unix
|
|
|
|
coding-system-for-read 'utf-8-unix
|
|
|
|
coding-system-for-write 'utf-8-unix
|
|
|
|
buffer-file-coding-system 'utf-8-unix
|
|
|
|
|
|
|
|
org-export-coding-system 'utf-8-unix
|
|
|
|
org-html-coding-system 'utf-8-unix ; doesn't take from above
|
|
|
|
|
|
|
|
default-process-coding-system '(utf-8-unix . utf-8-unix)
|
|
|
|
x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
|
|
|
|
|
|
|
|
(defun ewiki/no-junk-please-were-unixish ()
|
|
|
|
"Convert line endings to UNIX, dammit."
|
|
|
|
(let ((coding-str (symbol-name buffer-file-coding-system)))
|
|
|
|
(when (string-match "-\\(?:dos\\|mac\\)$" coding-str)
|
|
|
|
(set-buffer-file-coding-system 'unix))))
|
|
|
|
|
|
|
|
(add-hook 'find-file-hook #'ewiki/no-junk-please-were-unixish)
|
|
|
|
(add-hook 'before-save-hook #'ewiki/no-junk-please-were-unixish)
|
|
|
|
|
|
|
|
;; Cursor
|
|
|
|
(setq-default cursor-type 'bar
|
|
|
|
cursor-in-non-selected-windows nil)
|
|
|
|
(blink-cursor-mode 0)
|
|
|
|
|
|
|
|
;; Filling text
|
|
|
|
(setq-default fill-column 80)
|
|
|
|
(global-display-fill-column-indicator-mode +1)
|
|
|
|
|
|
|
|
(bind-key "C-x f" #'find-file) ; I don't set `fill-column', ever
|
|
|
|
|
|
|
|
(setq-default comment-auto-fill-only-comments t)
|
|
|
|
;; Enable `auto-fill-mode' everywhere
|
|
|
|
(add-hook 'text-mode-hook #'auto-fill-mode)
|
|
|
|
(add-hook 'prog-mode-hook #'auto-fill-mode)
|
|
|
|
;; Also enable `visual-line-mode' everywhere
|
|
|
|
(global-visual-line-mode +1)
|
|
|
|
;; "Fix" `visual-line-mode' in `org-mode'
|
|
|
|
(defun hook--visual-line-fix-org-keys ()
|
|
|
|
(when (derived-mode-p 'org-mode)
|
|
|
|
(local-set-key (kbd "C-a") #'org-beginning-of-line)
|
|
|
|
(local-set-key (kbd "C-e") #'org-end-of-line)
|
|
|
|
(local-set-key (kbd "C-k") #'org-kill-line)))
|
|
|
|
(add-hook 'visual-line-mode-hook #'hook--visual-line-fix-org-keys)
|
|
|
|
|
2021-03-01 20:44:57 +00:00
|
|
|
(dolist (margin '(right-margin left-margin))
|
|
|
|
(dolist (button '(mouse-1 mouse-2 mouse-3))
|
|
|
|
(global-set-key (vector margin button)
|
|
|
|
(global-key-binding (vector button)))))
|
|
|
|
|
|
|
|
(mouse-wheel-mode +1)
|
|
|
|
|
|
|
|
(when (bound-and-true-p mouse-wheel-mode)
|
|
|
|
(dolist (margin '(right-margin left-margin))
|
|
|
|
(dolist (event '(mouse-wheel-down-event
|
|
|
|
mouse-wheel-up-event
|
|
|
|
wheel-down
|
|
|
|
wheel-up
|
|
|
|
mouse-4
|
|
|
|
mouse-5))
|
|
|
|
(global-set-key (vector margin event) #'mwheel-scroll))))
|
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
(use-package visual-fill-column
|
2021-03-01 18:13:28 +00:00
|
|
|
:init (setq-default visual-fill-column-center-text t)
|
2021-03-01 20:44:57 +00:00
|
|
|
(add-hook 'visual-fill-column-mode-hook #'visual-line-mode)
|
2021-03-01 18:13:28 +00:00
|
|
|
:config
|
|
|
|
(advice-add 'text-scale-adjust :after #'visual-fill-column-adjust))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(when (fboundp 'global-so-long-mode)
|
|
|
|
(global-so-long-mode +1))
|
|
|
|
|
|
|
|
;; Whitespace
|
|
|
|
(setq-default whitespace-style '(empty ; remove blank lines at buffer edges
|
|
|
|
indentation ; clean up indentation
|
|
|
|
;; mixed tabs & spaces
|
|
|
|
space-before-tab
|
|
|
|
space-after-tab))
|
|
|
|
(add-hook 'before-save-hook #'whitespace-cleanup)
|
|
|
|
|
|
|
|
(setq-default indent-tabs-mode t
|
|
|
|
tab-width 8)
|
|
|
|
|
|
|
|
(use-package smart-tabs-mode
|
2021-03-01 18:13:28 +00:00
|
|
|
:config
|
2021-03-01 05:58:57 +00:00
|
|
|
(smart-tabs-insinuate 'c 'c++ 'java 'javascript 'cperl 'python 'ruby 'nxml))
|
|
|
|
|
|
|
|
;; Window layouts
|
|
|
|
(setq-default
|
|
|
|
split-width-threshold 100 ; minimum width for window splits
|
|
|
|
split-height-threshold 50 ; minimum height for window splits
|
|
|
|
display-buffer-alist ; how to display buffers
|
|
|
|
'((".*" . (display-buffer-reuse-window display-buffer-same-window)))
|
|
|
|
display-buffer-reuse-frames t ; allow reuse of frames
|
|
|
|
even-window-sizes nil ; avoid resizing windows to even them
|
|
|
|
help-window-select t ; select *Help* window when opened
|
|
|
|
)
|
|
|
|
|
|
|
|
(defun vsplit-other-window ()
|
|
|
|
"Split the window vertically and switch to the new window."
|
|
|
|
(interactive)
|
|
|
|
(split-window-vertically)
|
|
|
|
(other-window 1 nil))
|
|
|
|
|
|
|
|
(defun hsplit-other-window ()
|
|
|
|
"Split the window horizontally and switch to the new window."
|
|
|
|
(interactive)
|
|
|
|
(split-window-horizontally)
|
|
|
|
(other-window 1 nil))
|
|
|
|
|
|
|
|
(bind-key "C-x 2" #'vsplit-other-window)
|
|
|
|
(bind-key "C-x 3" #'hsplit-other-window)
|
|
|
|
|
|
|
|
;; Theming
|
|
|
|
|
|
|
|
(use-package form-feed
|
2021-03-04 15:07:36 +00:00
|
|
|
:demand
|
2021-03-01 18:13:28 +00:00
|
|
|
:config (global-form-feed-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(use-package modus-themes
|
2021-03-01 18:13:28 +00:00
|
|
|
:straight (:host gitlab :repo "protesilaos/modus-themes")
|
|
|
|
:demand
|
|
|
|
:init
|
|
|
|
(setq-default modus-themes-slanted-constructs t
|
|
|
|
modus-themes-bold-constructs t
|
|
|
|
modus-themes-region 'bg-only
|
|
|
|
modus-themes-org-blocks 'grayscale
|
|
|
|
modus-themes-headings '((1 . section)
|
|
|
|
(t . no-color))
|
|
|
|
modus-themes-scale-headings nil
|
|
|
|
modus-themes-mode-line nil)
|
|
|
|
:custom-face
|
|
|
|
(modus-theme-heading-1
|
|
|
|
((t (:inherit (modus-theme-heading-1 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-2
|
|
|
|
((t (:inherit (modus-theme-heading-2 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-3
|
|
|
|
((t (:inherit (modus-theme-heading-3 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-4
|
|
|
|
((t (:inherit (modus-theme-heading-4 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-5
|
|
|
|
((t (:inherit (modus-theme-heading-5 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-6
|
|
|
|
((t (:inherit (modus-theme-heading-6 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-7
|
|
|
|
((t (:inherit (modus-theme-heading-7 fixed-pitch bold)))))
|
|
|
|
(modus-theme-heading-8
|
|
|
|
((t (:inherit (modus-theme-heading-8 fixed-pitch bold))))))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; Change themes based on time of day
|
|
|
|
|
|
|
|
(defun acdw/run-with-sun (sunrise-command sunset-command)
|
|
|
|
"Run commands at sunrise and sunset."
|
|
|
|
(let* ((times-regex (rx (* nonl)
|
|
|
|
(: (any ?s ?S) "unrise") " "
|
|
|
|
(group (repeat 1 2 digit) ":"
|
|
|
|
(repeat 1 2 digit)
|
|
|
|
(: (any ?a ?A ?p ?P) (any ?m ?M)))
|
|
|
|
(* nonl)
|
|
|
|
(: (any ?s ?S) "unset") " "
|
|
|
|
(group (repeat 1 2 digit) ":"
|
|
|
|
(repeat 1 2 digit)
|
|
|
|
(: (any ?a ?A ?p ?P) (any ?m ?M)))
|
|
|
|
(* nonl)))
|
|
|
|
(ss (sunrise-sunset))
|
|
|
|
(_m (string-match times-regex ss))
|
|
|
|
(sunrise-time (match-string 1 ss))
|
|
|
|
(sunset-time (match-string 2 ss)))
|
|
|
|
(run-at-time sunrise-time (* 60 60 24) sunrise-command)
|
|
|
|
(run-at-time sunset-time (* 60 60 24) sunset-command)
|
|
|
|
(run-at-time "0:00" (* 60 60 24) sunset-command)))
|
|
|
|
|
|
|
|
(acdw/run-with-sun #'modus-themes-load-operandi
|
|
|
|
#'modus-themes-load-vivendi)
|
|
|
|
|
|
|
|
(use-package minions
|
2021-03-01 18:13:28 +00:00
|
|
|
:config (minions-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(use-package which-key
|
2021-03-01 18:13:28 +00:00
|
|
|
:config (which-key-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(delete-selection-mode +1)
|
|
|
|
|
|
|
|
(setq-default
|
|
|
|
save-interprogram-paste-before-kill t ; save existing text before replacing
|
|
|
|
yank-pop-change-selection t ; update X selection when rotating ring
|
|
|
|
x-select-enable-clipboard t ; Enable X clipboards
|
|
|
|
x-select-enable-primary t
|
|
|
|
mouse-drag-copy-region t ; Copy a region when mouse-selected
|
|
|
|
kill-do-not-save-duplicates t ; Don't append the same thing twice
|
|
|
|
)
|
|
|
|
|
|
|
|
(use-package smartscan
|
2021-03-01 18:13:28 +00:00
|
|
|
:config (global-smartscan-mode +1))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(when (fboundp 'global-goto-address-mode)
|
|
|
|
(global-goto-address-mode +1))
|
|
|
|
|
|
|
|
(use-package flyspell
|
2021-03-01 18:13:28 +00:00
|
|
|
:init
|
2021-03-01 05:58:57 +00:00
|
|
|
(setenv "LANG" "en_US")
|
|
|
|
(setq-default ispell-program-name "hunspell"
|
|
|
|
ispell-dictionary "en_US"
|
|
|
|
ispell-personal-dictionary "~/.hunspell_personal")
|
|
|
|
:hook
|
|
|
|
(text-mode . flyspell-mode)
|
|
|
|
(prog-mode . flyspell-prog-mode)
|
|
|
|
:config
|
|
|
|
(ispell-set-spellchecker-params)
|
|
|
|
(unless (file-exists-p ispell-personal-dictionary)
|
|
|
|
(write-region "" nil ispell-personal-dictionary nil 0)))
|
|
|
|
|
|
|
|
(use-package flyspell-correct
|
2021-03-04 15:07:36 +00:00
|
|
|
:after flyspell
|
2021-03-04 15:15:13 +00:00
|
|
|
:bind (:map flyspell-mode-map
|
|
|
|
("C-;" . flyspell-correct-wrapper)))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(setq-default show-paren-delay 0
|
|
|
|
show-paren-style 'mixed
|
|
|
|
show-paren-when-point-inside-paren t
|
|
|
|
show-paren-when-point-in-periphery t)
|
|
|
|
(show-paren-mode +1)
|
|
|
|
|
|
|
|
(add-hook 'prog-mode-hook #'electric-pair-local-mode)
|
|
|
|
|
|
|
|
(setq-default prettify-symbols-unprettify-at-point 'right-edge)
|
|
|
|
(add-hook 'prog-mode-hook #'prettify-symbols-mode)
|
|
|
|
|
|
|
|
(add-hook 'after-save-hook
|
|
|
|
#'executable-make-buffer-file-executable-if-script-p)
|
|
|
|
|
|
|
|
(setq-default compilation-ask-about-save nil ; just save the buffer
|
|
|
|
compilation-always-kill t ; kill the processes without asking
|
|
|
|
compilation-scroll-output 'first-error)
|
|
|
|
|
|
|
|
(use-package reformatter
|
2021-03-01 18:13:28 +00:00
|
|
|
:demand)
|
2021-03-01 05:58:57 +00:00
|
|
|
|
2021-03-04 15:09:04 +00:00
|
|
|
(setq-default smie-indent-basic 8)
|
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
;; Shell scripts
|
|
|
|
(setq-default sh-basic-offset 8
|
2021-03-04 15:09:04 +00:00
|
|
|
;; try to indent like shfmt
|
|
|
|
sh-indent-after-case 0
|
|
|
|
sh-indent-for-case-alt '+
|
|
|
|
sh-indent-for-case-label 0)
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(use-package flymake-shellcheck
|
2021-03-01 18:13:28 +00:00
|
|
|
:when (executable-find "shellcheck")
|
2021-03-04 23:58:44 +00:00
|
|
|
:hook (sh-mode . flymake-shellcheck-load))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(when (executable-find "shfmt")
|
|
|
|
(reformatter-define sh-format
|
2021-03-01 18:13:28 +00:00
|
|
|
:program "shfmt"
|
|
|
|
:lighter "Shfmt")
|
2021-03-01 05:58:57 +00:00
|
|
|
(add-hook 'sh-mode-hook #'sh-format-on-save-mode))
|
|
|
|
|
|
|
|
(bind-key "M-/" #'hippie-expand)
|
|
|
|
|
|
|
|
;; Tabs
|
|
|
|
(setq-default
|
|
|
|
tab-bar-show 1 ; show the tab bar when more than one
|
|
|
|
tab-bar-new-tab-choice "*scratch*" ; what to show on a new tab
|
|
|
|
tab-bar-tab-name-function ; how to name a new tab
|
|
|
|
#'tab-bar-tab-name-current-with-count
|
|
|
|
tab-bar-history-limit 25 ; how many tabs to save in history
|
|
|
|
)
|
|
|
|
|
|
|
|
(tab-bar-history-mode +1)
|
|
|
|
|
|
|
|
;; Smart hungry delete
|
|
|
|
(use-package smart-hungry-delete
|
2021-03-01 18:13:28 +00:00
|
|
|
:defer nil
|
|
|
|
:bind (("<backspace>" . smart-hungry-delete-backward-char)
|
|
|
|
("C-d" . smart-hungry-delete-forward-char))
|
|
|
|
:config (smart-hungry-delete-add-default-hooks))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; Enable all commands
|
|
|
|
(setq-default disabled-command-function nil)
|
|
|
|
|
|
|
|
;; Magit
|
|
|
|
(use-package magit
|
2021-03-01 20:45:31 +00:00
|
|
|
:bind ("C-x g" . magit-status)
|
|
|
|
:init (when (eq acdw/system :work)
|
2021-03-01 22:30:28 +00:00
|
|
|
(setenv "GIT_ASKPASS" "git-gui--askpass"))
|
|
|
|
(defun magit-display-buffer-same-window (buffer)
|
|
|
|
"Show `magit' in the same buffer, like god intended."
|
|
|
|
(display-buffer buffer '(display-buffer-same-window)))
|
|
|
|
(setq magit-display-buffer-function 'magit-display-buffer-same-window
|
|
|
|
magit-popup-display-buffer-action '((display-buffer-same-window))))
|
2021-03-01 20:45:31 +00:00
|
|
|
(use-package forge
|
|
|
|
:after magit)
|
|
|
|
(use-package gitattributes-mode
|
|
|
|
:mode "\\.gitattributes\\'")
|
|
|
|
(use-package gitconfig-mode
|
|
|
|
:mode "\\.gitconfig\\'")
|
|
|
|
(use-package gitignore-mode
|
|
|
|
:mode "\\.gitignore\\'")
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; crux
|
|
|
|
(use-package crux
|
2021-03-01 18:13:28 +00:00
|
|
|
:straight (:host github :repo "bbatsov/crux")
|
|
|
|
:bind
|
|
|
|
("M-o" . crux-other-window-or-switch-buffer)
|
|
|
|
:config
|
|
|
|
(crux-with-region-or-line kill-ring-save)
|
|
|
|
(crux-with-region-or-line kill-region)
|
|
|
|
(crux-with-region-or-line comment-or-uncomment-region))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
;; Completion and... stuff
|
|
|
|
(setq-default
|
|
|
|
completion-ignore-case t
|
|
|
|
read-buffer-completion-ignore-case t
|
2021-03-01 20:46:08 +00:00
|
|
|
read-file-name-completion-ignore-case t
|
|
|
|
minibuffer-eldef-shorten-default t)
|
|
|
|
|
|
|
|
(minibuffer-electric-default-mode +1)
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(use-package icomplete-vertical
|
2021-03-01 18:13:28 +00:00
|
|
|
:demand
|
2021-03-01 05:58:57 +00:00
|
|
|
:init
|
|
|
|
(setq-default
|
|
|
|
icomplete-delay-completions-threshold 0
|
|
|
|
icomplete-max-delay-chars 0
|
|
|
|
icomplete-compute-delay 0
|
|
|
|
icomplete-show-matches-on-no-input t
|
|
|
|
icomplete-hide-common-prefix nil
|
|
|
|
icomplete-with-completion-tables t
|
|
|
|
icomplete-in-buffer t)
|
|
|
|
:bind (:map icomplete-minibuffer-map
|
|
|
|
("<down>" . icomplete-forward-completions)
|
|
|
|
("C-n" . icomplete-forward-completions)
|
|
|
|
("<up>" . icomplete-backward-completions)
|
|
|
|
("C-p" . icomplete-backward-completions)
|
|
|
|
("C-v" . icomplete-vertical-toggle))
|
|
|
|
:config
|
|
|
|
(fido-mode -1)
|
|
|
|
(icomplete-mode +1)
|
|
|
|
(icomplete-vertical-mode +1))
|
|
|
|
|
|
|
|
(use-package orderless
|
2021-03-01 18:13:28 +00:00
|
|
|
:after icomplete
|
|
|
|
:init (setq-default completion-styles '(orderless)))
|
2021-03-01 05:58:57 +00:00
|
|
|
|
|
|
|
(use-package marginalia
|
2021-03-01 18:13:28 +00:00
|
|
|
:after icomplete
|
|
|
|
:init (setq-default marginalia-annotators
|
|
|
|
'(marginalia-annotators-heavy
|
|
|
|
marginalia-annotators-light))
|
|
|
|
:config (marginalia-mode +1))
|
2021-02-26 17:31:50 +00:00
|
|
|
|
2021-03-01 05:58:57 +00:00
|
|
|
(use-package consult
|
2021-03-01 18:13:28 +00:00
|
|
|
:after icomplete
|
|
|
|
:bind (;; C-c bindings (mode-specific-map)
|
|
|
|
("C-c h" . consult-history)
|
|
|
|
("C-c m" . consult-mode-command)
|
|
|
|
("C-c b" . consult-bookmark)
|
|
|
|
("C-c k" . consult-kmacro)
|
|
|
|
;; C-x bindings (ctl-x-map)
|
2021-03-01 20:46:28 +00:00
|
|
|
("C-x M-:" . consult-complex-command)
|
|
|
|
("C-x b" . consult-buffer)
|
|
|
|
("C-x 4 b" . consult-buffer-other-window)
|
|
|
|
("C-x 5 b" . consult-buffer-other-frame)
|
2021-03-01 18:13:28 +00:00
|
|
|
;; Custom M-# bindings for fast register access
|
|
|
|
("M-#" . consult-register-load)
|
2021-03-01 20:46:28 +00:00
|
|
|
("M-'" . consult-register-store)
|
2021-03-01 18:13:28 +00:00
|
|
|
("C-M-#" . consult-register)
|
|
|
|
;; Other custom bindings
|
2021-03-01 20:46:28 +00:00
|
|
|
("M-y" . consult-yank-pop)
|
|
|
|
("<help> a" . consult-apropos)
|
2021-03-01 18:13:28 +00:00
|
|
|
;; M-g bindings (goto-map)
|
|
|
|
("M-g e" . consult-compile-error)
|
2021-03-01 20:46:28 +00:00
|
|
|
("M-g g" . consult-goto-line)
|
|
|
|
("M-g M-g" . consult-goto-line)
|
2021-03-01 18:13:28 +00:00
|
|
|
("M-g o" . consult-outline)
|
|
|
|
("M-g m" . consult-mark)
|
|
|
|
("M-g k" . consult-global-mark)
|
|
|
|
("M-g i" . consult-imenu)
|
|
|
|
("M-g I" . consult-project-imenu)
|
|
|
|
;; M-s bindings (search-map)
|
|
|
|
("M-s f" . consult-find)
|
|
|
|
("M-s L" . consult-locate)
|
|
|
|
("M-s g" . consult-grep)
|
|
|
|
("M-s G" . consult-git-grep)
|
|
|
|
("M-s r" . consult-ripgrep)
|
|
|
|
("M-s l" . consult-line)
|
|
|
|
("M-s m" . consult-multi-occur)
|
|
|
|
("M-s k" . consult-keep-lines)
|
|
|
|
("M-s u" . consult-focus-lines)
|
|
|
|
;; Isearch integration
|
|
|
|
("M-s e" . consult-isearch)
|
|
|
|
:map isearch-mode-map
|
2021-03-01 20:46:28 +00:00
|
|
|
("M-e" . consult-isearch)
|
|
|
|
("M-s e" . consult-isearch)
|
|
|
|
("M-s l" . consult-line))
|
2021-03-01 18:13:28 +00:00
|
|
|
:init
|
|
|
|
(setq register-preview-delay 0
|
|
|
|
register-preview-function #'consult-register-format)
|
|
|
|
(advice-add #'register-preview :override #'consult-register-window)
|
|
|
|
(setq xref-show-xrefs-function #'consult-xref
|
|
|
|
xref-show-definitions-function #'consult-xref)
|
|
|
|
:config
|
|
|
|
;; (setq consult-preview-key 'any)
|
|
|
|
;; (setq consult-preview-key (kbd "M-p"))
|
|
|
|
(setq consult-narrow-key "<"))
|
|
|
|
|
|
|
|
;; Language: Emacs-Lisp
|
|
|
|
(setq-default eval-expression-print-length nil ; don't limit print length
|
|
|
|
eval-expression-print-level nil
|
|
|
|
)
|
|
|
|
;; indent like common lisp
|
|
|
|
(require 'cl-lib)
|
|
|
|
(setq-default lisp-indent-function #'common-lisp-indent-function)
|
|
|
|
(put 'cl-flet 'common-lisp-indent-function
|
|
|
|
(get 'flet 'common-lisp-indent-function))
|
|
|
|
(put 'cl-labels 'common-lisp-indent-function
|
|
|
|
(get 'labels 'common-lisp-indent-function))
|
|
|
|
(put 'if 'common-lisp-indent-function 2)
|
|
|
|
(put 'dotimes-protect 'common-lisp-indent-function
|
|
|
|
(get 'when 'common-lisp-indent-function))
|
2021-03-02 04:53:56 +00:00
|
|
|
;; eldoc mode
|
|
|
|
(use-package eldoc
|
|
|
|
:straight nil
|
|
|
|
:init (setq-default eldoc-echo-area-display-truncation-message nil
|
|
|
|
eldoc-idle-delay 0))
|
2021-03-01 20:46:58 +00:00
|
|
|
|
|
|
|
;; Dired
|
|
|
|
(use-package dired
|
|
|
|
:straight nil
|
|
|
|
:init
|
|
|
|
(setq-default dired-recursive-copies 'always
|
|
|
|
dired-recursive-deletes 'always
|
|
|
|
delete-by-moving-to-trash t
|
|
|
|
dired-listing-switches "-AFgho --group-directories-first"
|
2021-03-02 04:54:03 +00:00
|
|
|
dired-auto-revert-buffer t
|
2021-03-01 20:46:58 +00:00
|
|
|
dired-dwim-target t)
|
|
|
|
:bind ("C-x C-j" . dired-jump))
|
|
|
|
(defun hook--dired-mode ()
|
|
|
|
(hl-line-mode +1)
|
|
|
|
(dired-hide-details-mode +1))
|
|
|
|
(add-hook 'dired-mode-hook #'hook--dired-mode)
|
|
|
|
|
|
|
|
(use-package dired-subtree
|
|
|
|
:bind (:map dired-mode-map
|
|
|
|
("i" . dired-subtree-toggle)))
|
|
|
|
|
|
|
|
(use-package dired-collapse
|
|
|
|
:hook dired-mode)
|
|
|
|
|
|
|
|
(use-package 0x0
|
|
|
|
:straight (:repo "https://git.sr.ht/~zge/nullpointer-emacs")
|
|
|
|
:init (setq 0x0-default-service 'ttm)
|
|
|
|
:commands (0x0-upload
|
|
|
|
0x0-upload-file
|
|
|
|
0x0-upload-string
|
|
|
|
0x0-upload-kill-ring
|
|
|
|
0x0-popup))
|
|
|
|
|
|
|
|
(use-package elpher
|
|
|
|
:straight (:repo "git://thelambdalab.xyz/elpher.git")
|
|
|
|
:commands (elpher elpher-bookmarks)
|
|
|
|
:init (setq elpher-ipv4-always t
|
|
|
|
elpher-certificate-directory
|
|
|
|
(expand-file-name "elpher-certificates/"
|
|
|
|
acdw/var-dir))
|
|
|
|
(add-hook 'elpher-mode-hook #'acdw/reading-mode)
|
|
|
|
:custom-face
|
|
|
|
(elpher-gemini-heading1
|
|
|
|
((t (:inherit (modus-theme-heading-1)
|
|
|
|
:height 1.0))))
|
|
|
|
(elpher-gemini-heading2
|
|
|
|
((t (:inherit (modus-theme-heading-2)
|
|
|
|
:height 1.0))))
|
|
|
|
(elpher-gemini-heading3
|
|
|
|
((t (:inherit (modus-theme-heading-3)
|
|
|
|
:height 1.0))))
|
|
|
|
:bind (:map elpher-mode-map
|
|
|
|
("n" . elpher-next-link)
|
|
|
|
("p" . elpher-prev-link)
|
|
|
|
("o" . elpher-follow-current-link)
|
|
|
|
("G" . elpher-go-current)))
|
|
|
|
|
|
|
|
(use-package gemini-write
|
|
|
|
:straight (:repo
|
|
|
|
"https://alexschroeder.ch/cgit/gemini-write"
|
|
|
|
:fork (:repo "https://tildegit.org/acdw/gemini-write"
|
|
|
|
:branch "main"))
|
|
|
|
:after elpher)
|
|
|
|
|
|
|
|
(use-package gemini-mode
|
|
|
|
:straight (:repo "https://git.carcosa.net/jmcbray/gemini.el.git")
|
|
|
|
:mode "\\.\\(gemini\\|gmi\\)\\'"
|
|
|
|
:custom-face
|
|
|
|
(gemini-heading-face-1
|
|
|
|
((t (:inherit (elpher-gemini-heading1)))))
|
|
|
|
(gemini-heading-face2
|
|
|
|
((t (:inherit (elpher-gemini-heading2)))))
|
|
|
|
(gemini-heading-face3
|
|
|
|
((t (:inherit (elpher-gemini-heading3))))))
|
|
|
|
|
|
|
|
(use-package nov
|
2021-03-01 22:58:18 +00:00
|
|
|
:init (setq nov-text-width fill-column)
|
2021-03-01 20:46:58 +00:00
|
|
|
(add-hook 'nov-mode-hook #'acdw/reading-mode)
|
|
|
|
:mode ("\\.epub\\'" . nov-mode))
|
|
|
|
|
|
|
|
(use-package undo-fu
|
|
|
|
:bind (("C-/" . undo-fu-only-undo)
|
|
|
|
("C-?" . undo-fu-only-redo)))
|
|
|
|
(use-package undo-fu-session
|
|
|
|
:init (setq undo-fu-session-directory (expand-file-name "undo/"
|
|
|
|
acdw/var-dir)
|
|
|
|
undo-fu-session-incompatible-files
|
|
|
|
'("/COMMIT_EDITMSG\\'" "/git-rebase-todo\\'"))
|
|
|
|
:config (global-undo-fu-session-mode))
|
|
|
|
|
|
|
|
(setq-default set-mark-repeat-command-pop t) ; repeat mark pops w/o prefix
|
|
|
|
|
|
|
|
(use-package expand-region
|
|
|
|
:bind ("C-=" . er/expand-region))
|
|
|
|
|
|
|
|
(use-package goggles
|
|
|
|
:hook ((text-mode prog-mode) . goggles-mode))
|
|
|
|
|
2021-03-02 04:54:16 +00:00
|
|
|
(use-package isearch
|
|
|
|
:straight nil)
|
|
|
|
|
2021-03-01 20:46:58 +00:00
|
|
|
(use-package anzu
|
|
|
|
:init (setq search-default-mode t)
|
|
|
|
:bind (([remap query-replace] . anzu-query-replace-regexp)
|
|
|
|
([remap query-replace-regexp] . anzu-query-replace)
|
|
|
|
:map isearch-mode-map
|
|
|
|
([remap isearch-query-replace] . anzu-isearch-query-replace)
|
|
|
|
([remap isearch-query-replace-regexp] .
|
|
|
|
anzu-isearch-query-replace-regexp)))
|
|
|
|
|
|
|
|
(use-package iscroll
|
2021-03-01 22:58:18 +00:00
|
|
|
:hook (text-mode . iscroll-mode))
|
2021-03-01 20:46:58 +00:00
|
|
|
|
2021-03-02 04:54:16 +00:00
|
|
|
(use-package ibuffer
|
|
|
|
:straight nil
|
2021-03-05 00:36:14 +00:00
|
|
|
:bind ([remap list-buffers] . #'ibuffer)
|
|
|
|
;; from http://martinowen.net/blog/2010/02/03/tips-for-emacs-ibuffer.html
|
|
|
|
:init
|
|
|
|
(setq ibuffer-saved-filter-groups ; this could still be improved
|
|
|
|
'(("home"
|
|
|
|
("emacs-config" (or (filename . ".emacs.d")
|
|
|
|
(filename . "etc/emacs")))
|
|
|
|
("Org" (or (mode . org-mode)
|
|
|
|
(filename . "OrgMode")))
|
|
|
|
("Dired" (mode . dired-mode))
|
|
|
|
("Magit" (name . "magit"))
|
|
|
|
("Help" (or (name . "\*Help\*")
|
|
|
|
(name . "\*Apropos\*")
|
|
|
|
(name . "\*info\*")))))
|
|
|
|
ibuffer-expert t ; don't ask if i wanna kill unmodifieds
|
|
|
|
ibuffer-show-empty-filter-groups nil
|
|
|
|
)
|
|
|
|
(defun hook--ibuffer-setup ()
|
|
|
|
(ibuffer-auto-mode +1)
|
|
|
|
(ibuffer-switch-to-saved-filter-groups "home"))
|
|
|
|
(add-hook 'ibuffer-mode-hook #'hook--ibuffer-setup))
|
2021-03-02 04:54:16 +00:00
|
|
|
|
2021-03-01 20:46:58 +00:00
|
|
|
(setq-default
|
|
|
|
browse-url-browser-function 'browse-url-firefox
|
|
|
|
browse-url-new-window-flag t
|
|
|
|
browse-url-firefox-new-window-is-tab t
|
|
|
|
shr-max-width fill-column
|
|
|
|
shr-width fill-column)
|
|
|
|
|
|
|
|
(when (eq acdw/system :work)
|
|
|
|
(add-to-list 'exec-path "C:/Program Files/Mozilla Firefox"))
|
2021-03-02 04:54:16 +00:00
|
|
|
|
|
|
|
(bind-key [remap just-one-space] #'cycle-spacing)
|
2021-03-04 15:09:29 +00:00
|
|
|
|
|
|
|
;; Org mode
|
|
|
|
;; org-return-dwim (unpacakged)
|
|
|
|
(defun unpackaged/org-element-descendant-of (type element)
|
|
|
|
"Return non-nil if ELEMENT is a descendant of TYPE.
|
|
|
|
TYPE should be an element type, like `item' or `paragraph'.
|
|
|
|
ELEMENT should be a list like that returned by `org-element-context'."
|
|
|
|
;; MAYBE: Use `org-element-lineage'.
|
|
|
|
(when-let* ((parent (org-element-property :parent element)))
|
|
|
|
(or (eq type (car parent))
|
|
|
|
(unpackaged/org-element-descendant-of type parent))))
|
|
|
|
|
|
|
|
(defun unpackaged/org-return-dwim (&optional default)
|
|
|
|
"A helpful replacement for `org-return'. With prefix, call `org-return'.
|
|
|
|
|
|
|
|
On headings, move point to position after entry content. In
|
|
|
|
lists, insert a new item or end the list, with checkbox if
|
|
|
|
appropriate. In tables, insert a new row or end the table."
|
|
|
|
;; Inspired by John Kitchin:
|
|
|
|
;; http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/
|
|
|
|
(interactive "P")
|
|
|
|
(if default
|
|
|
|
(org-return)
|
|
|
|
(cond
|
|
|
|
;; Act depending on context around point.
|
|
|
|
|
|
|
|
;; NOTE: I prefer RET to not follow links, but by uncommenting
|
|
|
|
;; this block, links will be followed.
|
|
|
|
;; FURTHER NOTE: Ideally, I would follow links unless point
|
|
|
|
;; /appeared/ to be at the end of the line (even if it's still
|
|
|
|
;; inside the link) -- when it would do `org-return'. That
|
|
|
|
;; would take some /doing/, however.
|
|
|
|
|
|
|
|
;; ((eq 'link (car (org-element-context)))
|
|
|
|
;; ;; Link: Open it.
|
|
|
|
;; (org-open-at-point-global))
|
|
|
|
|
|
|
|
((org-at-heading-p)
|
|
|
|
;; Heading: Move to position after entry content.
|
|
|
|
;; NOTE: This is probably the most interesting feature of this function.
|
|
|
|
(let ((heading-start (org-entry-beginning-position)))
|
|
|
|
(goto-char (org-entry-end-position))
|
|
|
|
(cond ((and (org-at-heading-p)
|
|
|
|
(= heading-start (org-entry-beginning-position)))
|
|
|
|
;; Entry ends on its heading; add newline after
|
|
|
|
(end-of-line)
|
|
|
|
(insert "\n\n"))
|
|
|
|
(t
|
|
|
|
;; Entry ends after its heading; back up
|
|
|
|
(forward-line -1)
|
|
|
|
(end-of-line)
|
|
|
|
(when (org-at-heading-p)
|
|
|
|
;; At the same heading
|
|
|
|
(forward-line)
|
|
|
|
(insert "\n")
|
|
|
|
(forward-line -1))
|
|
|
|
;; FIXME: looking-back is supposed to be called with
|
|
|
|
;; more arguments.
|
|
|
|
(while (not (looking-back (rx
|
|
|
|
(repeat 3
|
|
|
|
(seq (optional blank)
|
|
|
|
"\n")))
|
|
|
|
nil))
|
|
|
|
(insert "\n"))
|
|
|
|
(forward-line -1)))))
|
|
|
|
|
|
|
|
((org-at-item-checkbox-p)
|
|
|
|
;; Checkbox: Insert new item with checkbox.
|
|
|
|
(org-insert-todo-heading nil))
|
|
|
|
|
|
|
|
((org-in-item-p)
|
|
|
|
;; Plain list. Yes, this gets a little complicated...
|
|
|
|
(let ((context (org-element-context)))
|
|
|
|
(if (or (eq 'plain-list (car context)) ; First item in list
|
|
|
|
(and (eq 'item (car context))
|
|
|
|
(not (eq (org-element-property :contents-begin context)
|
|
|
|
(org-element-property :contents-end context))))
|
|
|
|
;; Element in list item, e.g. a link
|
|
|
|
(unpackaged/org-element-descendant-of 'item context))
|
|
|
|
;; Non-empty item: Add new item.
|
|
|
|
(org-insert-item)
|
|
|
|
;; Empty item: Close the list.
|
|
|
|
;; TODO: Do this with org functions rather than operating
|
|
|
|
;; on the text. Can't seem to find the right function.
|
|
|
|
(delete-region (line-beginning-position) (line-end-position))
|
|
|
|
(insert "\n"))))
|
|
|
|
|
|
|
|
((when (fboundp 'org-inlinetask-in-task-p)
|
|
|
|
(org-inlinetask-in-task-p))
|
|
|
|
;; Inline task: Don't insert a new heading.
|
|
|
|
(org-return))
|
|
|
|
|
|
|
|
((org-at-table-p)
|
|
|
|
(cond ((save-excursion
|
|
|
|
(beginning-of-line)
|
|
|
|
;; See `org-table-next-field'.
|
|
|
|
(cl-loop with end = (line-end-position)
|
|
|
|
for cell = (org-element-table-cell-parser)
|
|
|
|
always (equal (org-element-property :contents-begin cell)
|
|
|
|
(org-element-property :contents-end cell))
|
|
|
|
while (re-search-forward "|" end t)))
|
|
|
|
;; Empty row: end the table.
|
|
|
|
(delete-region (line-beginning-position) (line-end-position))
|
|
|
|
(org-return))
|
|
|
|
(t
|
|
|
|
;; Non-empty row: call `org-return'.
|
|
|
|
(org-return))))
|
|
|
|
(t
|
|
|
|
;; All other cases: call `org-return'.
|
|
|
|
(org-return)))))
|
|
|
|
|
|
|
|
;; org-fix-blank-lines (unpackaged)
|
|
|
|
(defun unpackaged/org-fix-blank-lines (&optional prefix)
|
|
|
|
"Ensure that blank lines exist between headings and between headings and their contents.
|
|
|
|
With prefix, operate on whole buffer. Ensures that blank lines
|
|
|
|
exist after each headings's drawers."
|
|
|
|
(interactive "P")
|
|
|
|
(org-map-entries (lambda ()
|
|
|
|
(org-with-wide-buffer
|
|
|
|
;; `org-map-entries' narrows the buffer, which prevents us
|
|
|
|
;; from seeing newlines before the current heading, so we
|
|
|
|
;; do this part widened.
|
|
|
|
(while (not (looking-back "\n\n" nil))
|
|
|
|
;; Insert blank lines before heading.
|
|
|
|
(insert "\n")))
|
|
|
|
(let ((end (org-entry-end-position)))
|
|
|
|
;; Insert blank lines before entry content
|
|
|
|
(forward-line)
|
|
|
|
(while (and (org-at-planning-p)
|
|
|
|
(< (point) (point-max)))
|
|
|
|
;; Skip planning lines
|
|
|
|
(forward-line))
|
|
|
|
(while (re-search-forward org-drawer-regexp end t)
|
|
|
|
;; Skip drawers. You might think that `org-at-drawer-p'
|
|
|
|
;; would suffice, but for some reason it doesn't work
|
|
|
|
;; correctly when operating on hidden text. This
|
|
|
|
;; works, taken from `org-agenda-get-some-entry-text'.
|
|
|
|
(re-search-forward "^[ \t]*:END:.*\n?" end t)
|
|
|
|
(goto-char (match-end 0)))
|
|
|
|
(unless (or (= (point) (point-max))
|
|
|
|
(org-at-heading-p)
|
|
|
|
(looking-at-p "\n"))
|
|
|
|
(insert "\n"))))
|
|
|
|
t (if prefix
|
|
|
|
nil
|
|
|
|
'tree)))
|
|
|
|
|
|
|
|
(defun hook--org-mode-fix-blank-lines ()
|
|
|
|
(when (eq major-mode 'org-mode)
|
|
|
|
(let ((current-prefix-arg 4)) ; Emulate C-u
|
|
|
|
(call-interactively 'unpackaged/org-fix-blank-lines))))
|
|
|
|
(add-hook 'before-save-hook #'hook--org-mode-fix-blank-lines)
|
|
|
|
|
|
|
|
(use-package org
|
|
|
|
:straight (:repo "https://code.orgmode.org/bzg/org-mode.git")
|
|
|
|
:init
|
|
|
|
(setq-default
|
|
|
|
org-directory "~/org" ; where to search for org files
|
|
|
|
;; typesetting
|
|
|
|
org-hide-emphasis-markers t
|
|
|
|
org-fontify-whole-heading-line t
|
|
|
|
org-fontify-done-headline t
|
|
|
|
org-fontify-quote-and-verse-blocks t
|
|
|
|
org-src-fontify-natively t
|
|
|
|
org-ellipsis " ≡"
|
|
|
|
org-pretty-entities t
|
|
|
|
org-tags-column (- 0 fill-column (- (length org-ellipsis)))
|
|
|
|
;; Source blocks
|
|
|
|
org-src-tab-acts-natively t
|
|
|
|
org-src-window-setup 'current-window
|
|
|
|
org-confirm-babel-evaluate nil
|
|
|
|
;; Behavior
|
|
|
|
org-adapt-indentation t ; indent text after a header
|
|
|
|
org-catch-invisible-edits 'smart
|
|
|
|
org-special-ctrl-a/e t
|
|
|
|
org-special-ctrl-k t
|
|
|
|
org-imenu-depth 8 ; catch all headings
|
|
|
|
;; Exporting
|
|
|
|
org-export-headline-levels 8 ; export all headings
|
|
|
|
org-export-with-smart-quotes t
|
|
|
|
org-export-with-sub-superscripts t
|
|
|
|
;; Modules
|
|
|
|
org-modules '(;; default (commented if unused)
|
|
|
|
;; bbdb
|
|
|
|
;; bibtex
|
|
|
|
;; docview
|
|
|
|
eww
|
|
|
|
;; gnus
|
|
|
|
info
|
|
|
|
;; irc
|
|
|
|
;; mhe
|
|
|
|
;; rmail
|
|
|
|
;; w3m
|
|
|
|
;; extra stuff for me
|
|
|
|
;; habit ; track your consistency with habits
|
|
|
|
;; inlinetask ; tasks independent of outline hierarchy
|
|
|
|
mouse ; additional mouse support
|
|
|
|
;; protocol ; intercept calls from emacsclient
|
|
|
|
;; man
|
|
|
|
tempo ; templates
|
|
|
|
)
|
|
|
|
org-export-backends '(;; defaults
|
|
|
|
ascii
|
|
|
|
html
|
|
|
|
latex
|
|
|
|
odt
|
|
|
|
;; added by me
|
|
|
|
man
|
|
|
|
md
|
|
|
|
)
|
|
|
|
)
|
|
|
|
:config
|
|
|
|
(require 'org-tempo)
|
|
|
|
(require 'ox-md)
|
|
|
|
:bind (:map org-mode-map
|
|
|
|
("RET" . unpackaged/org-return-dwim)))
|
|
|
|
|
|
|
|
(use-package goto-addr
|
|
|
|
:straight nil
|
|
|
|
:config
|
|
|
|
(goto-address-mode +1))
|
|
|
|
|
|
|
|
(use-package web-mode
|
|
|
|
:mode (("\\.phtml\\'" . web-mode)
|
|
|
|
("\\.tpl\\.php\\'" . web-mode)
|
|
|
|
("\\.[agj]sp\\'" . web-mode)
|
|
|
|
("\\as[cp]x\\'" . web-mode)
|
|
|
|
("\\.erb\\'" . web-mode)
|
|
|
|
("\\.mustache\\'" . web-mode)
|
|
|
|
("\\.djhtml\\'" . web-mode)
|
|
|
|
("\\.html?\\'" . web-mode)))
|