Sean Whitton <spwhit...@spwhitton.name> writes: > Hello, > > On Thu 05 Sep 2024 at 09:39am GMT, Philip Kaludercic wrote: > >>>> + ((eq region 'unix-word) >>>> + (let ((end (point))) >>>> + (save-excursion >>>> + (skip-chars-backward "[:space:]") >>>> + (skip-chars-backward "^[:space:]") >>>> + (filter-buffer-substring >>>> + (if (get-char-property (point) 'read-only) >>>> + (next-single-char-property-change >>>> + (point) 'read-only nil end) >>>> + (point)) >>>> + end 'delete)))) >>>> + (region >>>> + (funcall region-extract-function 'delete)) >>>> + ((filter-buffer-substring beg end 'delete))))) >>> >>> Shall I rather commit this as an independent unix-word-rubout? >>> >>> Improves attribution, and it's independently useful. >> >> As a standalone command? > > I mean, yeah, I have had it on my C-w for years. Probably some other > people have implementations too.
In that case, it would be difficult to use it directly in this implementation, as kill-region needs a command that just moves the point. I guess it would be possible to hack something together with atomic change groups, but the cleanest strategy would probably be to have a unix-word-forward command that goes in both directions, and use that both in a standalone unix-word-rubout and this patch. But we can do that after merging this patch -- assuming there are no more blocking issues with the latest version:
>From fa7b5158fb1507db32a7b537137418afa024cfad Mon Sep 17 00:00:00 2001 From: Philip Kaludercic <phil...@posteo.net> Date: Tue, 3 Sep 2024 18:29:56 +0200 Subject: [PATCH] Allow 'kill-region' kill the last word when there is no region * etc/NEWS: Document the new user option. * lisp/simple.el (kill-region-dwim): Add new option. (kill-region): Respect 'kill-region-dwim'. (Bug#69097) --- etc/NEWS | 8 +++++++- lisp/simple.el | 49 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 1e66f084117..60efbfb43d8 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -123,6 +123,12 @@ When using 'visual-wrap-prefix-mode' in buffers with variable-pitch fonts, the wrapped text will now be lined up correctly so that it's exactly below the text after the prefix on the first line. +--- +** New user option 'kill-word-if-no-region'. +This option will modify the fall-back behaviour of 'kill-region' if no +region is active, and will kill the last word instead of raising an +error. + * Changes in Specialized Modes and Packages in Emacs 31.1 @@ -268,7 +274,7 @@ any. ** Diff --- -*** New command 'diff-kill-ring-save'. +*** New command 'diff-kill-dwim'. This command copies to the 'kill-ring' a region of text modified according to diffs in the current buffer, but without applying the diffs to the original text. If the selected range extends a hunk, the diff --git a/lisp/simple.el b/lisp/simple.el index eedc5768fe2..efa338f0b0d 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5817,6 +5817,18 @@ kill-read-only-ok :type 'boolean :group 'killing) +(defcustom kill-region-dwim nil + "Behaviour when `kill-region' is invoked without an active region. +If set to nil (default), the behaviour of `kill-region' stays the same. +If set to `emacs-word', then kill the last word as defined by the +current major mode. If set to `unix-word', then kill the last word in +the style of a shell like Bash, disregarding the major mode." + :type '(choice (const :tag "Kill a word like `backward-kill-word'" emacs-word) + (const :tag "Kill a word like Bash would" unix-word) + (const :tag "Do not kill anything" nil)) + :group 'killing + :version "31.1") + (defun kill-region (beg end &optional region) "Kill (\"cut\") text between point and mark. This deletes the text from the buffer and saves it in the kill ring. @@ -5843,21 +5855,44 @@ kill-region (To delete text, use `delete-region'.) Supply two arguments, character positions BEG and END indicating the stretch of text to be killed. If the optional argument REGION is - non-nil, the function ignores BEG and END, and kills the current + `region', the function ignores BEG and END, and kills the current region instead. Interactively, REGION is always non-nil, and so - this command always kills the current region." + this command always kills the current region. It is possible to + override this behaviour by customising the user option + `kill-region-dwim'." ;; Pass mark first, then point, because the order matters when ;; calling `kill-append'. (interactive (progn (let ((beg (mark)) (end (point))) - (unless (and beg end) + (cond + ((and kill-region-dwim (not (use-region-p))) + (list beg end kill-region-dwim)) + ((not (or beg end)) (user-error "The mark is not set now, so there is no region")) - (list beg end 'region)))) + ((list beg end 'region)))))) + (condition-case nil - (let ((string (if region - (funcall region-extract-function 'delete) - (filter-buffer-substring beg end 'delete)))) + (let ((string (cond + ((eq region 'emacs-word) + (let ((end (point))) + (save-excursion + (forward-word -1) + (filter-buffer-substring (point) end 'delete)))) + ((eq region 'unix-word) + (let ((end (point))) + (save-excursion + (skip-chars-backward "[:space:]") + (skip-chars-backward "^[:space:]") + (filter-buffer-substring + (if (get-char-property (point) 'read-only) + (next-single-char-property-change + (point) 'read-only nil end) + (point)) + end 'delete)))) + (region + (funcall region-extract-function 'delete)) + ((filter-buffer-substring beg end 'delete))))) (when string ;STRING is nil if BEG = END ;; Add that string to the kill ring, one way or another. (if (eq last-command 'kill-region) -- 2.45.2
-- Philip Kaludercic on siskin