Many changes

This commit is contained in:
Case Duckworth 2022-01-03 08:41:18 -06:00
parent c1ceacefd6
commit 3041f185dd
11 changed files with 5173 additions and 414 deletions

4271
+ispell.el Normal file

File diff suppressed because it is too large Load Diff

View File

@ -66,7 +66,8 @@ say, `tool-bar-mode' once to toggle the tool bar back on."
(defun after-make-frame@setup (&rest args)
(ignore args)
(let ((fixed-pitch-faces
'((:font "Fantasque Sans Mono" :height 115)
'((:font "Cascadia Mono" :height 100)
(:font "Fantasque Sans Mono" :height 115)
(:font "Go Mono" :height 110)
(:font "DejaVu Sans Mono" :height 110)
(:font "monospace" :height 100)))

773
init.el
View File

@ -146,12 +146,18 @@
#'browse-url-default-browser)
browse-url-new-window-flag nil ; for eww
browse-url-firefox-arguments '("--new-tab") ; for firefox
browse-url-firefox-new-window-is-tab t)
browse-url-firefox-new-window-is-tab t
browse-url-mpv-arguments (when (memq system-type '(windows-nt))
`("--ytdl"
,(concat "--script-opts="
"ytdl_hook-ytdl_path="
(expand-file-name
"~/usr/bin/yt-dlp")))))
(acdw/browse-url-set-handlers
(list
(cons (rx (seq "." (or "jpeg" "jpg" ; images
"png")
"png" "webp")
eos))
(lambda (&rest args)
(apply
@ -173,13 +179,16 @@
args)))
(cons (rx (or "youtube.com" ; videos
"youtu.be"
(seq "." (or "mp4"
"yewtu.be"
"bandcamp.com" ; and music
(seq "." (or "mp4" ; and video files
"gif"
"mov" "MOV")
"mov" "MOV"
"webm")
eos)))
(lambda (&rest args)
(apply (if (executable-find "mpv")
#'browse-url-mpv
#'browse-url-youtube->invidious
browse-url-secondary-browser-function)
args)))
(cons (rx (or "google.com" ; websites that don't work with eww
@ -393,7 +402,7 @@
global-mark-ring-max 100
regexp-search-ring-max 100
load-prefer-newer t
native-comp-async-report-warnings-errors nil
native-comp-async-report-warnings-errors 'silent
password-cache t
password-cache-expiry (* 60 5) ; seconds
set-mark-command-repeat-pop t
@ -422,6 +431,11 @@
"C-c _" #'add-file-local-variable
"C-x C-c" #'acdw/fat-finger-exit)
;;https://karthinks.com/software/an-elisp-editing-tip/
(global-set-key [remap eval-last-sexp] 'pp-eval-last-sexp)
;; And more! from https://old.reddit.com/r/emacs/comments/qfhzjg/
(global-set-key [remap eval-expression] 'pp-eval-expression)
(global-set-key (kbd "M-n") (kbd "C-u 1 C-v"))
(global-set-key (kbd "M-p") (kbd "C-u 1 M-v"))
@ -634,10 +648,12 @@ specific to most general, they are these:
(:hook-into text-mode))
(setup frames
(:option frame-title-format '("%b@"
(:eval
(or (file-remote-p default-directory 'host)
system-name))
(:option frame-title-format '((:eval
(concat
(or (buffer-file-name) (buffer-name))
"@"
(or (file-remote-p default-directory 'host)
system-name)))
" %+%* GNU Emacs"
(:eval (when (frame-parameter nil 'client)
" Client")))
@ -899,9 +915,26 @@ specific to most general, they are these:
;; window, so when I have the same buffer viewed in multiple windows I can
;; still see where my cursor is. To see the issue, C-x 2 then C-x o a few
;; times.
;; <bpalmer> the other hand, I think you can make faces have
;; window-specific values (and you can definitely do that with variables)
;; <bpalmer> so there might be a way to get what you want, one way or
;; another.
;; <bpalmer> acdw: oh, actually, see (info "(elisp) Overlay Properties") . If
;; you set the 'window property to a window, the overlay is only displayed in
;; that window
;; <bpalmer> (it's still attached to the buffer as a whole, so
;; I'm not entirely sure whether it will be made eligible for garbage
;; collection after the window is deleted. Perhaps I'll investigate that
;; later)
(defun pulse-line-current-window (&rest _)
"Pulse the current line, but only if this window is active."
(pulse-momentary-highlight-one-line (window-point (selected-window))))
(pulse-momentary-highlight-one-line (window-point
(actually-selected-window-determine))))
(dolist (func '(scroll-up-command
scroll-down-command
@ -1135,11 +1168,53 @@ specific to most general, they are these:
(winner-mode +1))
(with-eval-after-load 'org
(el-patch-defun org-format-outline-path (path &optional
width prefix separator)
"Format the outline path PATH for display.
WIDTH is the maximum number of characters that is available.
PREFIX is a prefix to be included in the returned string,
such as the file name.
SEPARATOR is inserted between the different parts of the path,
the default is \"/\"."
(setq width (or width 79))
(setq path (delq nil path))
(unless (> width 0)
(user-error "Argument `width' must be positive"))
(setq separator (or separator "/"))
(let* ((org-odd-levels-only nil)
(fpath (concat
prefix (and prefix path separator)
(mapconcat
(lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s))
(cl-loop for head in path
for n from 0
collect
(el-patch-swap
(org-add-props
head nil 'face
(nth (% n org-n-level-faces)
org-level-faces))
head))
separator))))
(when (> (length fpath) width)
(if (< width 7)
;; It's unlikely that `width' will be this small, but don't
;; waste characters by adding ".." if it is.
(setq fpath (substring fpath 0 width))
(setf (substring fpath (- width 2)) "..")))
fpath)))
(setup (:straight (0x0
:host gitlab
:repo "willvaughn/emacs-0x0"))
(:option 0x0-default-server 'ttm))
(setup (:straight acme-theme)
(:option acme-theme-black-fg t)
;; (load-theme 'acme :noconfirm)
)
(setup (:straight (actually-selected-window
:host github
:repo "duckwork/actually-selected-window.el"))
@ -1202,6 +1277,7 @@ specific to most general, they are these:
circe-default-nick "acdw"
circe-default-part-message "See You, Space Cowpokes . . ."
circe-default-user "acdw"
tracking-ignored-buffers '("idlerpg")
circe-format-action (format
(format "%%%ds* {nick} {body}"
(- acdw-irc/left-margin 2)) " ")
@ -1249,7 +1325,9 @@ specific to most general, they are these:
(:advise circe-command-PART :after #'circe-part@kill-buffer
circe-command-QUIT :after #'circe-quit@kill-buffer
circe-command-GQUIT :after #'circe-gquit@kill-buffer)
circe-command-GQUIT :after #'circe-gquit@kill-buffer
lui-track-jump-to-indicator
:after 'pulse-line-current-window)
(:with-mode circe-chat-mode
(:hook #'acdw/stop-paren-annoyances
@ -1268,7 +1346,7 @@ specific to most general, they are these:
(:option lui-fill-column (+ fill-column acdw-irc/left-margin)
lui-fill-type nil ;;(repeat-string acdw-irc/left-margin " ")
lui-time-stamp-position 'right-margin
lui-time-stamp-format "%H:%M"
lui-time-stamp-format "[ %H:%M"
lui-track-behavior 'before-switch-to-buffer
lui-track-indicator 'fringe
lui-fill-remove-face-from-newline nil)
@ -1282,8 +1360,10 @@ specific to most general, they are these:
(:local-set visual-fill-column-extra-text-width
(cons acdw-irc/left-margin 0)
scroll-margin 0
hscroll-margin 0
fringes-outside-margins t
right-margin-width 5
right-margin-width (+ 2 (length lui-time-stamp-format))
scroll-margin 0
word-wrap t
wrap-prefix (repeat-string acdw-irc/left-margin " ")
@ -1735,7 +1815,9 @@ See also `crux-reopen-as-root-mode'."
("tilderadio" .
"https://azuracast.tilderadio.org/radio/8000/radio.ogg")
("vantaradio" .
"https://vantaa.black/radio")))
"https://vantaa.black/radio")
("113fm KPOP Radio" .
"http://yp.shoutcast.com/sbin/tunein-station.m3u?id=1634740")))
(:global "C-c r r" #'eradio-play ; mnemonic: radio
"C-c r s" #'eradio-stop ; mnemonic: stop
"C-c r p" #'eradio-toggle ; mnemonic: play/pause
@ -1893,11 +1975,12 @@ See also `crux-reopen-as-root-mode'."
(add-to-list 'kaomoji-insert-alist km))
(:global "C-x 8 k" #'kaomoji-insert))
;; (setup (:straight wrap-region)
;; (:hook-into org-mode)
;; (with-eval-after-load 'org
;; (dolist (punc '("=" "*" "/" "_" "+"))
;; (wrap-region-add-wrapper punc punc nil 'org-mode))))
(setup (:straight wrap-region)
(require 'wrap-region)
(:hook-into org-mode)
(with-eval-after-load 'org
(dolist (punc '("=" "*" "/" "_" "+"))
(wrap-region-add-wrapper punc punc nil 'org-mode))))
(setup (:straight lacarte)
(:global "<f10>" #'lacarte-execute-menu-command))
@ -2006,370 +2089,34 @@ browser defined in `browse-url-secondary-browser-function'."
(:advise mastodon-tl--goto-next-toot :after #'mastodon-goto-toot@recenter
mastodon-tl--goto-prev-toot :after #'mastodon-goto-toot@recenter))
(setup (:straight (mct
:host gitlab
:repo "protesilaos/mct"))
(:option mct-minimum-input 3
mct-live-update-delay 0.25
mct-hide-completion-mode-line t
mct-remove-shadowed-file-name t
mct-completion-blocklist nil
mct-completion-passlist '(imenu
Info-goto-node
Info-index
Info-menu))
;; this is the only error that popped up with emacs 27.
(when (version< emacs-version "28")
(defvar completions-detailed nil))
(mct-mode +1))
;; (setup (:straight (mct
;; :host gitlab
;; :repo "protesilaos/mct"))
;; (:option mct-minimum-input 3
;; mct-live-update-delay 0.25
;; mct-hide-completion-mode-line t
;; mct-remove-shadowed-file-name t
;; mct-completion-blocklist nil
;; mct-completion-passlist '(imenu
;; Info-goto-node
;; Info-index
;; Info-menu))
;; ;; this is the only error that popped up with emacs 27.
;; (when (version< emacs-version "28")
;; (defvar completions-detailed nil))
;; (mct-mode +1))
(setup (:straight mode-line-bell)
(:option mode-line-bell-flash-time 0.1)
(mode-line-bell-mode +1))
(setup (:straight (modus-themes
:host gitlab
:repo "protesilaos/modus-themes"))
(:option modus-themes-slanted-constructs t
modus-themes-bold-constructs t
modus-themes-fringes nil
modus-themes-mode-line '(borderless)
modus-themes-region '(bg-only)
modus-themes-org-blocks 'gray-background
modus-themes-headings '((t . (background)))
modus-themes-lang-checkers '(straight-underline)
modus-themes-scale-headings nil)
(acdw/sunrise-sunset #'modus-themes-load-operandi
#'modus-themes-load-vivendi)
(add-hook 'modus-themes-after-load-theme-hook
(defun modus-themes@customize-faces ()
"Customize faces of modus-themes."
;; (dolist (face '(font-lock-builtin-face
;; ;; font-lock-comment-delimiter-face
;; ;; font-lock-coment-face
;; font-lock-constant-face
;; ;; font-lock-doc-face
;; font-lock-function-name-face
;; font-lock-keyword-face
;; font-lock-negation-char-face
;; font-lock-preprocessor-face
;; font-lock-regexp-grouping-backslash
;; font-lock-regexp-goruping-construct
;; font-lock-string-face
;; font-lock-type-face
;; font-lock-variable-name-face
;; font-lock-warning-face))
;; (modus-themes-with-colors
;; (custom-set-faces
;; `(,face
;; ((,class :foreground ,fg-main
;; :weight normal
;; :slant normal))))))
;; Other faces
(modus-themes-with-colors
(custom-set-faces
`(org-level-1
((,class :inherit (modus-themes-heading-1 fixed-pitch)
:extend t)))
`(org-level-2
((,class :inherit (modus-themes-heading-2 fixed-pitch)
:extend t)))
`(org-level-3
((,class :inherit (modus-themes-heading-3 fixed-pitch)
:extend t)))
`(org-level-4
((,class :inherit (modus-themes-heading-4 fixed-pitch)
:extend t)))
`(org-level-5
((,class :inherit (modus-themes-heading-5 fixed-pitch)
:extend t)))
`(org-level-6
((,class :inherit (modus-themes-heading-6 fixed-pitch)
:extend t)))
`(org-level-7
((,class :inherit (modus-themes-heading-7 fixed-pitch)
:extend t)))
`(org-level-8
((,class :inherit (modus-themes-heading-8 fixed-pitch)
:extend t))))))))
(setup (:straight mwim)
(:global "C-a" #'mwim-beginning
"C-e" #'mwim-end))
(setup (:straight nov)
(:option nov-text-width fill-column)
(:file-match (rx ".epub" eos)))
(setup (:straight (nyan-mode
:host github :repo "TeMPOraL/nyan-mode"
:fork (:host github :repo "duckwork/nyan-mode")
:files ("nyan-mode.el" "img")))
(:option nyan-animate-nyancat nil
nyan-bar-length 20
nyan-minimum-window-width (+ fill-column (/ nyan-bar-length 2)))
(nyan-mode +1)
(defun disable-nyan-mode ()
"Disable `nyan-mode' in current buffer."
(setq-local nyan-mode -1))
(dolist (mode '(eshell-mode
comint-mode))
(add-hook mode #'disable-nyan-mode)))
;; (setup (:straight olivetti)
;; (:option olivetti-body-width (+ fill-column 4)
;; olivetti-minimum-body-width fill-column)
;; (:hook (defun olivetti-mode@setup ()
;; (if olivetti-mode
;; (setq-local indicate-empty-lines nil
;; indicate-buffer-boundaries nil)
;; (acdw/setup-fringes)))))
(setup (:straight (orderless
:host github
:repo "oantolin/orderless"))
(require 'orderless)
(:option (append completion-styles) 'orderless
orderless-component-separator #'orderless-escapable-split-on-space
orderless-matching-styles '(orderless-literal
orderless-regexp
;; orderless-flex
)
orderless-style-dispatchers '(acdw/orderless-dispatch))
(:advise orderless-regexp :filter-args
(defun fix-dollar (args)
(if (string-suffix-p "$" (car args))
(list (concat (substring (car args) 0 -1)
"[\x100000-\x10FFFD]*$"))
args)))
(defun acdw/orderless-dispatch (pattern _index _total)
"My custom dispatcher for `orderless'."
(cond
;; Ensure that $ works with Consult commands, which add disambiguation
;; suffixes -- see `fix-dollar'
((string-suffix-p "$" pattern)
`(orderless-regexp . ,(concat (substring pattern 0 -1)
"[\x100000-\x10FFFD]*$")))
;; File extensions
((string-match-p "\\`\\.." pattern)
`(orderless-regexp . ,(concat "\\." (substring pattern 1)
"[\x100000-\x10FFFD]*$")))
;; Ignore single !
((string= "!" pattern)
`(orderless-literal . ""))
;; Character folding
((string-prefix-p "%" pattern)
`(char-fold-to-regexp . ,(substring pattern 1)))
((string-suffix-p "%" pattern)
`(char-fold-to-regexp . ,(substring pattern 0 -1)))
;; Without literal
((string-prefix-p "!" pattern)
`(orderless-without-literal . ,(substring pattern 1)))
((string-suffix-p "!" pattern)
`(orderless-without-literal . ,(substring pattern 0 -1)))
;; Initialism matching
((string-prefix-p "`" pattern)
`(orderless-initialism . ,(substring pattern 1)))
((string-suffix-p "`" pattern)
`(orderless-initialism . ,(substring pattern 0 -1)))
;; Literal matching
((string-prefix-p "=" pattern)
`(orderless-literal . ,(substring pattern 1)))
((string-suffix-p "=" pattern)
`(orderless-literal . ,(substring pattern 0 -1)))
;; Flex matching
((string-prefix-p "~" pattern)
`(orderless-flex . ,(substring pattern 1)))
((string-suffix-p "~" pattern)
`(orderless-flex . ,(substring pattern 0 -1))))))
(setup (:straight (org
:type git
:repo "https://git.savannah.gnu.org/git/emacs/org-mode.git"
:local-repo "org"
:depth full
:pre-build (straight-recipes-org-elpa--build)
:build (:not autoloads)
:files (:defaults
"lisp/*.el"
("etc/styles/" "etc/styles/*")))
(org-contrib
:type git
:repo "https://git.sr.ht/~bzg/org-contrib"))
(:also-load acdw-org
ox-md)
(require 'chd nil 'noerror)
(:option org-adapt-indentation nil
;; org-agenda-files nil ; only until I set this up
org-catch-invisible-edits 'show-and-error
org-clock-clocked-in-display 'mode-line
org-clock-frame-title-format (cons
'(t org-mode-line-string)
(cons " --- " frame-title-format))
org-clock-string-limit 7 ; just the clock bit
;; org-clock-string-limit 25 ; gives enough information
org-clock-persist t
org-confirm-babel-evaluate nil
org-cycle-separator-lines 0
org-directory "~/org"
org-ellipsis ""
org-export-coding-system 'utf-8-unix
org-export-headline-levels 8
org-export-with-section-numbers nil
org-export-with-smart-quotes t
org-export-with-sub-superscripts t
org-export-with-toc nil
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-fontify-whole-heading-line t
org-hide-emphasis-markers t
org-html-coding-system 'utf-8-unix
org-image-actual-width '(300)
org-imenu-depth 3
org-list-demote-modify-bullet '(("-" . "+")
("+" . "*")
("*" . "-"))
org-log-done 'time
org-log-into-drawer t
org-outline-path-complete-in-steps nil
org-pretty-entities t
org-refile-use-outline-path 'file
org-special-ctrl-a/e t
org-special-ctrl-k t
org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-startup-truncated nil
org-startup-with-inline-images t
org-tags-column (- (- fill-column (length org-ellipsis))))
(:bind "RET" #'acdw-org/return-dwim
"<S-return>" #'acdw-org/org-table-copy-down
;; "M-SPC M-SPC" #'insert-zero-width-space
"C-c C-l" #'org-insert-link-dwim
"C-c w" #'chd/do-the-thing
"C-c C-n" #'acdw/org-next-heading-widen
"C-c C-p" #'acdw/org-previous-heading-widen
"C-x n t" #'org-narrow-to-task)
(:unbind "C-j" ; org-return-and-maybe-indent
"M-j")
(:local-set unfill-fill-function #'org-fill-paragraph
wc-count-words-function
(lambda (start end) "Count words stupidly with a limit."
(acdw-org/count-words-stupidly start
end
999)))
(with-eval-after-load 'org-export
(:option (append org-export-filter-final-output-functions)
#'org-export-remove-zero-width-spaces))
(:local-hook before-save-hook
(defun org/before-save@prettify-buffer ()
(save-mark-and-excursion
(mark-whole-buffer)
(org-fill-paragraph nil t))
(acdw-org/fix-blank-lines t)
(org-align-tags :all)))
(with-eval-after-load 'org
(org-clock-persistence-insinuate))
(with-eval-after-load 'consult
(defun consult-clock-in (&optional match scope resolve)
"Clock into an Org heading."
(interactive (list nil nil current-prefix-arg))
(require 'org-clock)
(org-clock-load)
(save-window-excursion
(consult-org-heading
match
(or scope
(thread-last org-clock-history
(mapcar 'marker-buffer)
(mapcar 'buffer-file-name)
(delete-dups)
(delq nil))
(user-error "No recent clocked tasks")))
(org-clock-in nil (when resolve
(org-resolve-clocks)
(org-read-date t t)))))
(consult-customize consult-clock-in
:prompt "Clock in: "
:preview-key (kbd "M-.")
:group
(lambda (cand transform)
(if transform
(substring
cand
(next-single-property-change
0 'consult-org--buffer cand))
(let ((m (car (get-text-property
0 'consult-org--heading cand))))
(if (member m org-clock-history)
"*Recent*"
(buffer-name (marker-buffer m))))))))
(:advise org-delete-backward-char :override #'acdw-org/delete-backward-char)
(el-patch-feature org)
(with-eval-after-load 'org
(el-patch-defun org-format-outline-path (path &optional
width prefix separator)
"Format the outline path PATH for display.
WIDTH is the maximum number of characters that is available.
PREFIX is a prefix to be included in the returned string,
such as the file name.
SEPARATOR is inserted between the different parts of the path,
the default is \"/\"."
(setq width (or width 79))
(setq path (delq nil path))
(unless (> width 0)
(user-error "Argument `width' must be positive"))
(setq separator (or separator "/"))
(let* ((org-odd-levels-only nil)
(fpath (concat
prefix (and prefix path separator)
(mapconcat
(lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s))
(cl-loop for head in path
for n from 0
collect
(el-patch-swap
(org-add-props
head nil 'face
(nth (% n org-n-level-faces)
org-level-faces))
head))
separator))))
(when (> (length fpath) width)
(if (< width 7)
;; It's unlikely that `width' will be this small, but don't
;; waste characters by adding ".." if it is.
(setq fpath (substring fpath 0 width))
(setf (substring fpath (- width 2)) "..")))
fpath))))
(setup (:straight org-appear)
(:option org-appear-autoemphasis t
org-appear-autoentities t
org-appear-autokeywords t
org-appear-autolinks nil
org-appear-autosubmarkers t
org-appear-delay 0)
(:hook-into org-mode))
(setup (:straight org-sticky-header)
(:hook-into org-mode))
(setup (:straight-when ox-clip
(pcase system-type
('windows-nt (executable-find "python"))
('gnu/linux (executable-find "xclip"))
('darwin (and (executable-find "textutil")
(executable-find "pbcopy")))))
(:global "C-M-w" #'ox-clip-formatted-copy))
(setup (:straight ox-rfc)
(:load-after org))
@ -2414,7 +2161,8 @@ the default is \"/\"."
,(rx "*Async Shell Command*")
help-mode helpful-mode
compilation-mode)
popper-mode-line nil
popper-mode-line '(:eval
(propertize " POP" 'face 'mode-line-emphasis))
popper-display-control t
popper-display-function
(defun popper/select-popup-smartly (buffer &optional _alist)
@ -2538,7 +2286,7 @@ the default is \"/\"."
(:also-load sly-autoloads)
(:straight clhs)
(:option inferior-lisp-program acdw/lisp-bin
(:option inferior-lisp-program (car acdw/lisps)
sly-kill-without-query-p t)
(:with-feature sly-mrepl
@ -2621,17 +2369,17 @@ the default is \"/\"."
;; Enable C-c 8 map in all buffers
(typo-global-mode +1)
(add-hook 'text-mode-hook
(defun text-mode@typo-unless ()
"Start `typo-mode' UNLESS the buffer matches a predicate."
;; I implement this instead of using
;; `typo-disable-electricity-functions' because the latter checks
;; on every pertinent keypress. I know I want /no/ typo-ing in
;; these certain buffers, so I won't even turn on the mode.
(unless (or ; predicates here
(string-match-p "COMMIT_EDITMSG"
(or (buffer-name) "")))
(typo-mode +1))))
;; (add-hook 'text-mode-hook
;; (defun text-mode@typo-unless ()
;; "Start `typo-mode' UNLESS the buffer matches a predicate."
;; ;; I implement this instead of using
;; ;; `typo-disable-electricity-functions' because the latter checks
;; ;; on every pertinent keypress. I know I want /no/ typo-ing in
;; ;; these certain buffers, so I won't even turn on the mode.
;; (unless (or ; predicates here
;; (string-match-p "COMMIT_EDITMSG"
;; (or (buffer-name) "")))
;; (typo-mode +1))))
;; jlf & cvandusen on #emacs make a great point: (RIGHT SINGLE QUOTATION
;; MARK) is /not/ an apostrophe. Making it curly is a typographical
@ -2671,6 +2419,18 @@ If used with a numeric prefix argument N, N backticks will be inserted."
(:with-hook unfocused-hook
(:hook #'garbage-collect)))
;; This is a pretty good mct setup.
;; (setup (:straight (mct :host gitlab :repo "protesilaos/mct"))
;; (when (version< emacs-version "28")
;; (defvar completions-detailed nil))
;; (:option mct-remove-shadowed-file-names t
;; mct-hide-completion-mode-line t
;; mct-minimum-input 1
;; mct-live-update-delay 0.1)
;; (when (bound-and-true-p vertico-mode)
;; (vertico-mode -1))
;; (mct-mode +1))
(setup (:straight (vertico
:host github
:repo "minad/vertico"
@ -2684,8 +2444,7 @@ If used with a numeric prefix argument N, N backticks will be inserted."
(when (boundp 'native-comp-deferred-compilation-deny-list)
(add-to-list 'native-comp-deferred-compilation-deny-list "vertico"))
(unless mct-mode
(vertico-mode +1))
(vertico-mode +1)
;; Extensions!
(:also-load vertico-mouse
@ -2798,3 +2557,229 @@ If used with a numeric prefix argument N, N backticks will be inserted."
(if prefix
(call-interactively #'zzz-up-to-char)
(call-interactively #'zzz-to-char)))))
(setup z ;; C-z map!
(defvar acdw/z-map
(let ((map (make-sparse-keymap))
(c-z (global-key-binding "\C-z")))
(global-set-key "\C-z" map)
(define-key map "\C-z" c-z)
map))
(dolist (binding ;; (KEY COMMAND &optional FILE)
'(("c" org-capture)
("a" org-agenda)))
(let* ((key (nth 0 binding))
(c-key (concat "C-" key))
(command (nth 1 binding))
(file (or (nth 2 binding) (symbol-name command))))
(autoload command file nil t)
(define-key acdw/z-map (kbd c-key) command)
(define-key acdw/z-map (kbd key) command))))
(setup (:straight (org
:type git
:repo "https://git.savannah.gnu.org/git/emacs/org-mode.git"
:local-repo "org"
:depth full
:pre-build (straight-recipes-org-elpa--build)
:build (:not autoloads)
:files (:defaults
"lisp/*.el"
("etc/styles/" "etc/styles/*")))
(org-contrib
:type git
:repo "https://git.sr.ht/~bzg/org-contrib"))
(:also-load acdw-org)
(require 'chd nil 'noerror)
(setq-default org-adapt-indentation nil
org-agenda-skip-deadline-if-done t
org-archive-mark-done t
org-agenda-sticky t
org-fontify-whole-heading-line t
org-agenda-window-setup 'show-window
;; org-agenda-files nil ; only until I set this up
org-catch-invisible-edits 'show-and-error
org-clock-clocked-in-display 'mode-line
org-clock-frame-title-format (cons
'(t org-mode-line-string)
(cons " --- " frame-title-format))
org-clock-string-limit 7 ; just the clock bit
;; org-clock-string-limit 25 ; gives enough information
org-clock-persist t
org-confirm-babel-evaluate nil
org-cycle-separator-lines 0
org-directory "~/org"
org-ellipsis ""
org-export-coding-system 'utf-8-unix
org-export-headline-levels 8
org-export-with-section-numbers nil
org-export-with-smart-quotes t
org-export-with-sub-superscripts t
org-export-with-toc nil
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-fontify-whole-heading-line t
org-hide-emphasis-markers t
org-html-coding-system 'utf-8-unix
org-image-actual-width '(300)
org-imenu-depth 3
org-list-demote-modify-bullet '(("-" . "+")
("+" . "*")
("*" . "-"))
org-log-done 'time
org-log-into-drawer t
org-outline-path-complete-in-steps nil
org-pretty-entities t
org-refile-use-outline-path 'file
org-special-ctrl-a/e t
org-special-ctrl-k t
org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-startup-truncated nil
org-startup-with-inline-images t
org-tags-column (- (- fill-column (length org-ellipsis))))
(:bind "RET" #'acdw-org/return-dwim
"<S-return>" #'acdw-org/org-table-copy-down
;; "M-SPC M-SPC" #'insert-zero-width-space
"C-c C-l" #'org-insert-link-dwim
"C-c w" #'chd/do-the-thing
"C-c C-n" #'acdw/org-next-heading-widen
"C-c C-p" #'acdw/org-previous-heading-widen
"C-x n t" #'org-narrow-to-task)
(:unbind "C-j" ; org-return-and-maybe-indent
"M-j")
(:local-set unfill-fill-function #'org-fill-paragraph
wc-count-words-function
(lambda (start end) "Count words stupidly with a limit."
(acdw-org/count-words-stupidly start
end
999)))
(with-eval-after-load 'org-export
(:option (append org-export-filter-final-output-functions)
#'org-export-remove-zero-width-spaces))
(:local-hook before-save-hook
(defun org/before-save@prettify-buffer ()
(save-mark-and-excursion
(mark-whole-buffer)
(org-fill-paragraph nil t))
(acdw-org/fix-blank-lines t)
(org-align-tags :all)))
(:with-mode org-agenda-mode
(:hook #'hl-line-mode))
(with-eval-after-load 'org
(org-clock-persistence-insinuate))
(with-eval-after-load 'consult
(defun consult-clock-in (&optional match scope resolve)
"Clock into an Org heading."
(interactive (list nil nil current-prefix-arg))
(require 'org-clock)
(org-clock-load)
(save-window-excursion
(consult-org-heading
match
(or scope
(thread-last org-clock-history
(mapcar 'marker-buffer)
(mapcar 'buffer-file-name)
(delete-dups)
(delq nil))
(user-error "No recent clocked tasks")))
(org-clock-in nil (when resolve
(org-resolve-clocks)
(org-read-date t t)))))
(consult-customize consult-clock-in
:prompt "Clock in: "
:preview-key (kbd "M-.")
:group
(lambda (cand transform)
(if transform
(substring
cand
(next-single-property-change
0 'consult-org--buffer cand))
(let ((m (car (get-text-property
0 'consult-org--heading cand))))
(if (member m org-clock-history)
"*Recent*"
(buffer-name (marker-buffer m))))))))
(:advise org-delete-backward-char :override #'acdw-org/delete-backward-char)
(el-patch-feature org)
(with-eval-after-load 'org
(el-patch-defun org-format-outline-path (path &optional
width prefix separator)
"Format the outline path PATH for display.
WIDTH is the maximum number of characters that is available.
PREFIX is a prefix to be included in the returned string,
such as the file name.
SEPARATOR is inserted between the different parts of the path,
the default is \"/\"."
(setq width (or width 79))
(setq path (delq nil path))
(unless (> width 0)
(user-error "Argument `width' must be positive"))
(setq separator (or separator "/"))
(let* ((org-odd-levels-only nil)
(fpath (concat
prefix (and prefix path separator)
(mapconcat
(lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s))
(cl-loop for head in path
for n from 0
collect
(el-patch-swap
(org-add-props
head nil 'face
(nth (% n org-n-level-faces)
org-level-faces))
head))
separator))))
(when (> (length fpath) width)
(if (< width 7)
;; It's unlikely that `width' will be this small, but don't
;; waste characters by adding ".." if it is.
(setq fpath (substring fpath 0 width))
(setf (substring fpath (- width 2)) "..")))
fpath))))
(setup (:straight org-appear)
(:option org-appear-autoemphasis t
org-appear-autoentities t
org-appear-autokeywords t
org-appear-autolinks nil
org-appear-autosubmarkers t
org-appear-delay 0)
(:hook-into org-mode))
(setup (:straight org-sticky-header)
(:hook-into org-mode))
(setup (:straight orderless)
(:option completion-styles '(orderless)))
;; (setup (:straight punpun-theme)
;; (load-theme 'punpun-dark t))
(setup (:straight zoom-frm))
(setup (:straight modus-themes)
(:option modus-themes-bold-constructs t
modus-themes-italic-constructs t
modus-themes-syntax 'faint
modus-themes-headings '((t . (background)))
modus-themes-vivendi-color-overrides '((fg-main . "#c8c8c8")))
(load-theme 'modus-vivendi t))
(setup (:straight transpose-frame))

394
lisp/+pp.el Normal file
View File

@ -0,0 +1,394 @@
;;; +pp.el --- pretty printer for Emacs lisp -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Case Duckworth
;; Author: Case Duckworth <acdw@acdw.ne
;;; 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:
;; - Be kind to yourself.
;; - Make good choices.
;;; Commentary:
;; from Emacs master
;;; Code:
(defvar font-lock-verbose)
(defgroup pp nil
"Pretty printer for Emacs Lisp."
:prefix "pp-"
:group 'lisp)
(defcustom pp-escape-newlines t
"Value of `print-escape-newlines' used by pp-* functions."
:type 'boolean)
(defcustom pp-max-width t
"Max width to use when formatting.
If nil, there's no max width. If t, use the window width.
Otherwise this should be a number."
:type '(choice (const :tag "none" nil)
(const :tag "window width" t)
number)
:version "29.1")
(defcustom pp-use-max-width nil
"If non-nil, `pp'-related functions will try to fold lines.
The target width is given by the `pp-max-width' variable."
:type 'boolean
:version "29.1")
(defvar pp--inhibit-function-formatting nil)
;;;###autoload
(defun pp-to-string (object)
"Return a string containing the pretty-printed representation of OBJECT.
OBJECT can be any Lisp object. Quoting characters are used as needed
to make output that `read' can handle, whenever this is possible."
(if pp-use-max-width
(let ((pp--inhibit-function-formatting t))
(with-temp-buffer
(pp-emacs-lisp-code object)
(buffer-string)))
(with-temp-buffer
(lisp-mode-variables nil)
(set-syntax-table emacs-lisp-mode-syntax-table)
(let ((print-escape-newlines pp-escape-newlines)
(print-quoted t))
(prin1 object (current-buffer)))
(pp-buffer)
(buffer-string))))
;;;###autoload
(defun pp-buffer ()
"Prettify the current buffer with printed representation of a Lisp object."
(interactive)
(goto-char (point-min))
(while (not (eobp))
(cond
((ignore-errors (down-list 1) t)
(save-excursion
(backward-char 1)
(skip-chars-backward "'`#^")
(when (and (not (bobp)) (memq (char-before) '(?\s ?\t ?\n)))
(delete-region
(point)
(progn (skip-chars-backward " \t\n") (point)))
(insert "\n"))))
((ignore-errors (up-list 1) t)
(skip-syntax-forward ")")
(delete-region
(point)
(progn (skip-chars-forward " \t\n") (point)))
(insert ?\n))
(t (goto-char (point-max)))))
(goto-char (point-min))
(indent-sexp))
;;;###autoload
(defun pp (object &optional stream)
"Output the pretty-printed representation of OBJECT, any Lisp object.
Quoting characters are printed as needed to make output that `read'
can handle, whenever this is possible.
This function does not apply special formatting rules for Emacs
Lisp code. See `pp-emacs-lisp-code' instead.
By default, this function won't limit the line length of lists
and vectors. Bind `pp-use-max-width' to a non-nil value to do so.
Output stream is STREAM, or value of `standard-output' (which see)."
(princ (pp-to-string object) (or stream standard-output)))
;;;###autoload
(defun pp-display-expression (expression out-buffer-name &optional lisp)
"Prettify and display EXPRESSION in an appropriate way, depending on length.
If LISP, format with `pp-emacs-lisp-code'; use `pp' otherwise.
If a temporary buffer is needed for representation, it will be named
after OUT-BUFFER-NAME."
(let* ((old-show-function temp-buffer-show-function)
;; Use this function to display the buffer.
;; This function either decides not to display it at all
;; or displays it in the usual way.
(temp-buffer-show-function
(lambda (buf)
(with-current-buffer buf
(goto-char (point-min))
(end-of-line 1)
(if (or (< (1+ (point)) (point-max))
(>= (- (point) (point-min)) (frame-width)))
(let ((temp-buffer-show-function old-show-function)
(old-selected (selected-window))
(window (display-buffer buf)))
(goto-char (point-min)) ; expected by some hooks ...
(make-frame-visible (window-frame window))
(unwind-protect
(progn
(select-window window)
(run-hooks 'temp-buffer-show-hook))
(when (window-live-p old-selected)
(select-window old-selected))))
(message "%s" (buffer-substring (point-min) (point))))))))
(with-output-to-temp-buffer out-buffer-name
(if lisp
(with-current-buffer standard-output
(pp-emacs-lisp-code expression))
(pp expression))
(with-current-buffer standard-output
(emacs-lisp-mode)
(setq buffer-read-only nil)
(setq-local font-lock-verbose nil)))))
;;;###autoload
(defun pp-eval-expression (expression)
"Evaluate EXPRESSION and pretty-print its value.
Also add the value to the front of the list in the variable `values'."
(interactive
(list (read--expression "Eval: ")))
(message "Evaluating...")
(let ((result (eval expression lexical-binding)))
(values--store-value result)
(pp-display-expression result "*Pp Eval Output*")))
;;;###autoload
(defun pp-macroexpand-expression (expression)
"Macroexpand EXPRESSION and pretty-print its value."
(interactive
(list (read--expression "Macroexpand: ")))
(pp-display-expression (macroexpand-1 expression) "*Pp Macroexpand Output*"))
(defun pp-last-sexp ()
"Read sexp before point. Ignore leading comment characters."
(with-syntax-table emacs-lisp-mode-syntax-table
(let ((pt (point)))
(save-excursion
(forward-sexp -1)
(read
;; If first line is commented, ignore all leading comments:
(if (save-excursion (beginning-of-line) (looking-at-p "[ \t]*;"))
(let ((exp (buffer-substring (point) pt))
(start nil))
(while (string-match "\n[ \t]*;+" exp start)
(setq start (1+ (match-beginning 0))
exp (concat (substring exp 0 start)
(substring exp (match-end 0)))))
exp)
(current-buffer)))))))
;;;###autoload
(defun pp-eval-last-sexp (arg)
"Run `pp-eval-expression' on sexp before point.
With ARG, pretty-print output into current buffer.
Ignores leading comment characters."
(interactive "P")
(if arg
(insert (pp-to-string (eval (elisp--eval-defun-1
(macroexpand (pp-last-sexp)))
lexical-binding)))
(pp-eval-expression (elisp--eval-defun-1
(macroexpand (pp-last-sexp))))))
;;;###autoload
(defun pp-macroexpand-last-sexp (arg)
"Run `pp-macroexpand-expression' on sexp before point.
With ARG, pretty-print output into current buffer.
Ignores leading comment characters."
(interactive "P")
(if arg
(insert (pp-to-string (macroexpand-1 (pp-last-sexp))))
(pp-macroexpand-expression (pp-last-sexp))))
;;;###autoload
(defun pp-emacs-lisp-code (sexp)
"Insert SEXP into the current buffer, formatted as Emacs Lisp code.
Use the `pp-max-width' variable to control the desired line length."
(require 'edebug)
(let ((obuf (current-buffer)))
(with-temp-buffer
(emacs-lisp-mode)
(pp--insert-lisp sexp)
(insert "\n")
(goto-char (point-min))
(indent-sexp)
(while (re-search-forward " +$" nil t)
(replace-match ""))
(insert-into-buffer obuf))))
(defun pp--insert-lisp (sexp)
(cl-case (type-of sexp)
(vector (pp--format-vector sexp))
(cons (cond
((consp (cdr sexp))
(if (and (length= sexp 2)
(eq (car sexp) 'quote))
(cond
((symbolp (cadr sexp))
(let ((print-quoted t))
(prin1 sexp (current-buffer))))
((consp (cadr sexp))
(insert "'")
(pp--format-list (cadr sexp)
(set-marker (make-marker) (1- (point))))))
(pp--format-list sexp)))
(t
(princ sexp (current-buffer)))))
;; Print some of the smaller integers as characters, perhaps?
(integer
(if (<= ?0 sexp ?z)
(let ((print-integers-as-characters t))
(princ sexp (current-buffer)))
(princ sexp (current-buffer))))
(string
(let ((print-escape-newlines t))
(prin1 sexp (current-buffer))))
(otherwise (princ sexp (current-buffer)))))
(defun pp--format-vector (sexp)
(insert "[")
(cl-loop for i from 0
for element across sexp
do (pp--insert (and (> i 0) " ") element))
(insert "]"))
(defun pp--format-list (sexp &optional start)
(if (and (symbolp (car sexp))
(not pp--inhibit-function-formatting)
(not (keywordp (car sexp))))
(pp--format-function sexp)
(insert "(")
(pp--insert start (pop sexp))
(while sexp
(pp--insert " " (pop sexp)))
(insert ")")))
(defun pp--format-function (sexp)
(let* ((sym (car sexp))
(edebug (get sym 'edebug-form-spec))
(indent (get sym 'lisp-indent-function))
(doc (get sym 'doc-string-elt)))
(when (eq indent 'defun)
(setq indent 2))
;; We probably want to keep all the elements before the doc string
;; on a single line.
(when doc
(setq indent (1- doc)))
;; Special-case closures -- these shouldn't really exist in actual
;; source code, so there's no indentation information. But make
;; them output slightly better.
(when (and (not indent)
(eq sym 'closure))
(setq indent 0))
(pp--insert "(" sym)
(pop sexp)
;; Get the first entries on the first line.
(if indent
(pp--format-definition sexp indent edebug)
(let ((prev 0))
(while sexp
(let ((start (point)))
;; Don't put sexps on the same line as a multi-line sexp
;; preceding it.
(pp--insert (if (> prev 1) "\n" " ")
(pop sexp))
(setq prev (count-lines start (point)))))))
(insert ")")))
(defun pp--format-definition (sexp indent edebug)
(while (and (cl-plusp indent)
sexp)
(insert " ")
;; We don't understand all the edebug specs.
(unless (consp edebug)
(setq edebug nil))
(if (and (consp (car edebug))
(eq (caar edebug) '&rest))
(pp--insert-binding (pop sexp))
(if (null (car sexp))
(insert "()")
(pp--insert-lisp (car sexp)))
(pop sexp))
(pop edebug)
(cl-decf indent))
(when (stringp (car sexp))
(insert "\n")
(prin1 (pop sexp) (current-buffer)))
;; Then insert the rest with line breaks before each form.
(while sexp
(insert "\n")
(if (keywordp (car sexp))
(progn
(pp--insert-lisp (pop sexp))
(when sexp
(pp--insert " " (pop sexp))))
(pp--insert-lisp (pop sexp)))))
(defun pp--insert-binding (sexp)
(insert "(")
(while sexp
(if (consp (car sexp))
;; Newlines after each (...) binding.
(progn
(pp--insert-lisp (car sexp))
(when (cdr sexp)
(insert "\n")))
;; Keep plain symbols on the same line.
(pp--insert " " (car sexp)))
(pop sexp))
(insert ")"))
(defun pp--insert (delim &rest things)
(let ((start (if (markerp delim)
(prog1
delim
(setq delim nil))
(point-marker))))
(when delim
(insert delim))
(dolist (thing things)
(pp--insert-lisp thing))
;; We need to indent what we have so far to see if we have to fold.
(pp--indent-buffer)
(when (> (current-column) (pp--max-width))
(save-excursion
(goto-char start)
(unless (looking-at "[ \t]+$")
(insert "\n"))
(pp--indent-buffer)
(goto-char (point-max))
;; If we're still too wide, then go up one step and try to
;; insert a newline there.
(when (> (current-column) (pp--max-width))
(condition-case ()
(backward-up-list 1)
(:success (when (looking-back " " 2)
(insert "\n")))
(error nil)))))))
(defun pp--max-width ()
(cond ((numberp pp-max-width)
pp-max-width)
((null pp-max-width)
most-positive-fixnum)
((eq pp-max-width t)
(window-width))
(t
(error "Invalid pp-max-width value: %s" pp-max-width))))
(defun pp--indent-buffer ()
(goto-char (point-min))
(while (not (eobp))
(lisp-indent-line)
(forward-line 1)))
(provide '+pp)
;;; +pp.el ends here

View File

@ -19,6 +19,29 @@
browse-url-mpv-arguments
(list url)))))
(defvar browse-url-invidious-instance "https://yewtu.be")
(defun youtube->invidious (url)
"Convert URL from a YouTube to Invidious link."
(replace-regexp-in-string (rx "http" (? "s") "://"
(? "www.") "youtube.com")
browse-url-invidious-instance
url))
(defun browse-url-youtube->invidious (url &optional new-window)
"Play URL in MPV, converting Youtube to Invidious links."
(interactive (browse-url-interactive-arg "Video URL: "))
(ignore new-window) ; mpv always opens in a new window
(let* ((url (browse-url-encode-url (youtube->invidious url)))
(process-environment (browse-url-process-environment)))
(message "Playing %s in mpv..." url)
(apply #'start-process
(concat "mpv " url) nil
"mpv"
(append
browse-url-mpv-arguments
(list url)))))
(defvar browse-url-feh-arguments '("--auto-zoom"
"--geometry" "800x600")
"Arguments to pass to feh in `browse-url-feh'.")

View File

@ -14,9 +14,10 @@
(defun irc ()
"Connect to all IRC networks in `circe-network-options'."
(interactive)
(dolist (network (mapcar #'car circe-network-options))
(unless (member network circe-network-inhibit-autoconnect)
(circe-maybe-connect network))))
(with-message "Connecting to IRC"
(dolist (network (mapcar #'car circe-network-options))
(unless (member network circe-network-inhibit-autoconnect)
(circe-maybe-connect network)))))
(defun circe-network-connected-p (network)
"Return whether circe is connected to NETWORK."
@ -42,7 +43,9 @@ message the current topic."
(save-excursion
(goto-char (point-max))
(or (re-search-backward
(rx (group "*** Topic" (+ (not ":")) ": ")
(rx (group "*** "
(or "Topic" "topic" "TOPIC")
(* (not ":")) ": ")
(group (+ nonl)))))
(buffer-substring-no-properties
(match-beginning 2) (match-end 2)))))
@ -73,14 +76,17 @@ message the current topic."
"Set the prompt to the buffer name, shortening it."
(interactive) ; set interactive to unfuck the prompt when need be
(lui-set-prompt
(propertize
(concat
(acdw-irc/margin-format (buffer-name) "" ">")
" ")
'face 'circe-prompt-face
'read-only t
'intangible t
'cursor-intangible t)))
(concat (propertize
(concat
(acdw-irc/margin-format (buffer-name) "" ">"))
'face 'circe-prompt-face
'read-only t
'intangible t
'cursor-intangible t)
(propertize " "
'read-only t
'intangible t
'cursor-intangible t))))
;;; Advices
@ -165,3 +171,9 @@ See `circe-network-options' for a list of common options."
(provide 'acdw-circe)
;;; acdw-circe.el ends here
;; mio | lucidiot | /alias add npc /quote npc $channel $*
;; mio | lucidiot | /alias add npca /quote npca $channel $*
;; mio | lucidiot | /alias add scene /quote scene $channel $*
;; mio | lucidiot | and then you can use /npc name blah /npca name blah /scene blah

View File

@ -37,7 +37,7 @@ if ripgrep is installed, otherwise `consult-grep'."
(lambda (str) (orderless--highlight input str))))
(defun acdw-consult/complete-in-region (&rest args)
(apply (if vertico-mode
(apply (if (bound-and-true-p vertico-mode)
#'consult-completion-in-region
#'completion--in-region)
args))

View File

@ -195,8 +195,12 @@ is, if point < mark."
(defun acdw-modeline/track ()
"Display `tracking-mode' information."
'(tracking-mode
tracking-mode-line-buffers))
(when (bound-and-true-p tracking-mode)
(if (and (bound-and-true-p tracking-mode-length)
(>= (length (format-mode-line tracking-mode-line-buffers))
tracking-mode-length))
(propertize "[#...]")
tracking-mode-line-buffers)))
(defun acdw-modeline/vc-branch ()
"Display the version control branch of the current buffer in the modeline."

View File

@ -508,6 +508,14 @@ probably abandon it at some point for a better solution (see:
(outline-show-children)
(recenter-top-bottom)))
;;; org tel: links
(org-link-set-parameters "tel" :follow 'org-tel-open)
(defun org-tel-open (number _)
"Notify the user of what phone NUMBER to call."
(message "Call number: %s" number))
(provide 'acdw-org)
;;; acdw-org.el ends here

View File

@ -790,14 +790,23 @@ This function is internal. Use `acdw/make-password-fetcher' instead."
;;; Fat finger solutions
(defvar y-or-bail-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map y-or-n-p-map)
(define-key map "y" 'act)
(define-key map [t] 'abort-recursive-edit)
map))
(defun acdw/fat-finger-exit (&optional prefix)
"Delete a frame, or kill Emacs with confirmation.
When called with PREFIX, just kill Emacs without confirmation."
(interactive "P")
(if (or prefix
(and (= 1 (length (frame-list)))
(yes-or-no-p "This is the last frame! Wanna quit?")))
(kill-emacs)
(let ((y-or-n-p-map y-or-bail-map))
(yes-or-no-p "This is the last frame! Wanna quit?"))))
;; Save all buffers before quitting
(save-buffers-kill-emacs t)
(ignore-errors
(delete-frame))))
@ -865,5 +874,55 @@ the change."
feature-name))))
(require (intern feature-name) filename noerror)))
(defmacro setc (&rest args)
"Handle ARGS like `setq' using `customize-set-variable'."
(let (body)
(while args
(let* ((var (pop args))
(val (pop args)))
(push `(customize-set-variable ',var ,val) body)))
(macroexp-progn (nreverse body))))
(defun acdw/singlify-blank-lines ()
"Ensure only one blank line between everything."
;; TODO: right now, it just does everything in the buffer. It should be able
;; to do like, all in the region, or a prefix will do the buffer ... or
;; something.
(interactive "*")
(save-excursion
(goto-char (point-min))
(while (< (point) (point-max))
(forward-paragraph)
;; `delete-blank-lines' deletes just one blank line
;; ALSO TODO: this is like, stupid. Should be extracted probably.
(let (thisblank singleblank)
(save-excursion
(beginning-of-line)
(setq thisblank (looking-at "[ \t]*$"))
(setq singleblank (and thisblank
(not (looking-at "[ \t]*\n[ \t]*$"))
(or (bobp)
(progn (forward-line -1)
(not (looking-at "[ \t]*$")))))))
;; Delete preceding blank lines
(when thisblank
(beginning-of-line)
(delete-region (point)
(if (re-search-backward "[^ \t\n]" nil t)
(progn (forward-line 1) (point))
(point-min))))
;; Delete following blank lines
(when (not (and thisblank singleblank))
(save-excursion
(end-of-line)
(forward-line 1)
(delete-region (point)
(if (re-search-forward "[^ \t\n]" nil t)
(progn (beginning-of-line) (point))
(point-max)))))
;; Special case
(when (looking-at "^[ \t\n]*\\'")
(delete-region (point) (point-max)))))))
(provide 'acdw)
;;; acdw.el ends here

View File

@ -22,11 +22,13 @@ containing directory exists."
(when point (goto-char point))
(if (called-interactively-p 'interactive)
(save-excursion
(while (not (org-entry-is-todo-p))
(while (not (or (org-entry-is-done-p)
(org-entry-is-todo-p)))
(acdw/org-previous-heading-widen 1))
(org-narrow-to-subtree))
;; well this is dumb...
(while (not (org-entry-is-todo-p))
(while (not (or (org-entry-is-done-p)
(org-entry-is-todo-p)))
(acdw/org-previous-heading-widen 1))
(org-narrow-to-subtree)))