From 56b2c9fb541d7d538cc955ae93409710bd325e0f Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Sun, 24 Apr 2022 15:00:11 -0500 Subject: [PATCH] Correct backward-kill-word behavior --- init.el | 4 +++- lisp/+emacs.el | 28 ++++++++++++++++++++++++++++ lisp/+paredit.el | 26 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 lisp/+paredit.el diff --git a/init.el b/init.el index 4e353df..46f0071 100644 --- a/init.el +++ b/init.el @@ -41,6 +41,7 @@ "C-x C-o" #'+open-paragraph "C-w" #'+kill-word-backward-or-region "C-x C-m" #'execute-extended-command ; original: coding systems + "C-" #'+backward-kill-word ;; Alright, Yegge... NOPE! C-x t is tab prefix ... (maybe F6 or something?) ;; "C-x t" #'beginning-of-buffer ;; "C-x e" #'end-of-buffer @@ -2028,8 +2029,9 @@ See also `crux-reopen-as-root-mode'." (add-hook '+init-mode-hook #'flymake-mode-off)) (setup (:straight paredit) + (:also-load +paredit) (:bind "DEL" #'paredit-backward-delete - "C-" #'paredit-backward-kill-word + "C-" #'+paredit-backward-kill-word "C-w" (lambda (arg) (interactive "P") (+kill-word-backward-or-region arg #'paredit-backward-kill-word)) diff --git a/lisp/+emacs.el b/lisp/+emacs.el index b7e31e2..a0627cf 100644 --- a/lisp/+emacs.el +++ b/lisp/+emacs.el @@ -244,6 +244,34 @@ backward. It defaults to `backward-kill-word'." #'kill-region (or backward-kill-word-fn #'backward-kill-word)))) +(defun +backward-kill-word-wrapper (fn &optional arg) + "Kill backward using FN until the beginning of a word, smartly. +If point is on at the beginning of a line, kill the previous new +line. If the only thing before point on the current line is +whitespace, kill that whitespace. + +With argument ARG: if ARG is a number, just call FN +ARG times. Otherwise, just call FN." + ;; I want this to be a wrapper so that I can call other word-killing functions + ;; with it. It's *NOT* advice because those functions probably use + ;; `backward-kill-word' under the hood (looking at you, paredit), so advice + ;; will make things weird. + (if (null arg) + (cond + ((looking-back "^" 1) + (let ((delete-active-region nil)) + (delete-backward-char 1))) + ((looking-back "^[ ]*") + (delete-horizontal-space :backward-only)) + (t (call-interactively fn))) + (funcall fn (if (listp arg) 1 arg)))) + +(defun +backward-kill-word (&optional arg) + "Kill word backward using `backward-kill-word'. +ARG is passed to `backward-kill-word'." + (interactive "P") + (+backward-kill-word-wrapper #'backward-kill-word arg)) + ;; ... and advice ;; Indent the region after a yank. diff --git a/lisp/+paredit.el b/lisp/+paredit.el new file mode 100644 index 0000000..0c65328 --- /dev/null +++ b/lisp/+paredit.el @@ -0,0 +1,26 @@ +;;; +paredit.el --- bespoke paredit stuffs -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + +(require '+emacs) ; `+backward-kill-word-wrapper' + +(defun +paredit--backward-kill-word (&optional n) + "Perform `paredit-backward-kill-word' N times." + (interactive "p") + (dotimes (_ (or n 1)) + (paredit-backward-kill-word))) + +(defun +paredit-backward-kill-word (&optional arg) + "Kill a word backward using `paredit-backward-kill-word'. +Wrapped in `+backward-kill-word-wrapper', which see. + +Prefix ARG means to just call `paredit-backward-kill-word'." + ;; Of course, `paredit-backward-kill-word' doesn't TAKE an argument ... :/// + ;; So I had to write the wrapper above. + (interactive) + (+backward-kill-word-wrapper #'+paredit--backward-kill-word arg)) + +(provide '+paredit) +;;; +paredit.el ends here