From: Philip Kaludercic Date: Tue, 3 Sep 2024 16:29:56 +0000 (+0200) Subject: Allow 'kill-region' to kill the last word when there is no region X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=ec91756dab9756eab4f4b5f7e850f401d430e40a;p=emacs.git Allow 'kill-region' to kill the last word when there is no region * etc/NEWS: Document the new user option. * lisp/simple.el (kill-region-dwim): New option. (kill-region): Respect 'kill-region-dwim'. (Bug#69097) (cherry picked from commit 7451bd6e398f3dd8a3acc99df46d238d161463cb) --- diff --git a/etc/NEWS b/etc/NEWS index 73157b20804..e63a301db07 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -111,6 +111,15 @@ Unix-words are words separated by whitespace regardless of the buffer's syntax table. In a Unix terminal or shell, C-w kills by Unix-word. The new commands 'unix-word-rubout' and 'unix-filename-rubout' allow you to bind keys to operate more similarly to the terminal. + +--- +** New user option 'kill-word-dwim'. +This option, if non-nil, modifies the fall-back behavior of +'kill-region' if no region is active, and will kill the last word +instead of raising an error. Note that if you have disabled Transient +Mark mode you might prefer to use 'unix-word-rubout', as this feature +relies on there being an active region. + * Changes in Specialized Modes and Packages in Emacs 31.1 diff --git a/lisp/simple.el b/lisp/simple.el index a2d6ec21250..ff62ea62e0d 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5696,6 +5696,19 @@ move the yanking point; just return the Nth kill forward." :type 'boolean :group 'killing) +(defcustom kill-region-dwim nil + "Behavior when `kill-region' is invoked without an active region. +If set to nil (default), then the behavior of `kill-region' will not +change. 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 like with +`unix-word-rubout'." + :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. @@ -5722,21 +5735,35 @@ Lisp programs should use this function for killing text. (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 behavior 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 + ((memq region '(unix-word emacs-word)) + (let ((end (point))) + (save-excursion + (if (eq region 'emacs-word) + (forward-word -1) + (forward-unix-word -1)) + (filter-buffer-substring (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)