1

I want to delete regions without adding them to the kill ring following this thread:

(defun backward-kill-word-no-kill-ring ()
  "Delete the previous word and remove it from the kill ring."
  (interactive)
  (backward-kill-word 1)
  (setq kill-ring (cdr kill-ring))
  )

(global-set-key (kbd "M-DEL") 'backward-kill-word-no-kill-ring)

It fails and I don't understand why. If I type abcd, copy it with Cmd-C, and yank it with C-y, Emacs inserts abcd and the kill ring, viewed with C-h v kill-ring RET, is:

(Value:
(#("abcd" 0 4
    (fontified t))
...

If I type 123, delete it with M-DEL, which calls my function, and then yank with C-y, Emacs inserts https://www.fablabs.io/labs, which I had copied 30 minutes ago and is no longer an entry in the kill ring, and the kill ring is:

Value:
(#("123" 0 3
   (fontified t))
  #("abcd" 0 4
    (fontified t))
...

Then I cut text with C-w (kill-region), yank in another buffer, and it's the same link that comes first and my cut text that comes second (after M-y).

Where does yank grab its text if not from the kill ring?

Update

Following Tobias's comment, I had save-interprogram-paste-before-kill at t, and have the same behavior when I set it to nil and start Emacs with emacs -Q. When I follow the steps above, after M-DEL of 123, Emacs inserts the last entry from the kill ring, abcd. (When I first asked the question, I may have missed that the inserted text was the last entry of the kill ring, even after searching for the string in the kill-ring information buffer.)

Further udpate

A similar question asks how to delete text without adding to the kill ring. The solution there, as the answer by Tobias here, is more elegant than my first attempt. I edited the question to understand why Emacs is using the last entry in the kill ring instead of the top entry.

Further update (10 March)

I follow the steps above with emacs -Q, copy abcd to the clipboard and yank it, copy the function and keybinding and execute it, and after M-DEL of 123, Emacs inserts the last entry from the kill ring, abcd.

The kill ring after that insertion is:

Value:
("(defun backward-kill-word-no-kill-ring ()
  \"Delete the previous word and remove it from the kill ring.\"
  (interactive)
  (backward-kill-word 1)
  (setq kill-ring (cdr kill-ring))
  )

(global-set-key (kbd \"M-DEL\") 'backward-kill-word-no-kill-ring)"
 #("abcd" 0 4
   (fontified t)))

The Emacs version is:

GNU Emacs 26.3 (build 1, x86_64-apple-darwin18.2.0, NS appkit-1671.20 Version 10.14.3 (Build 18D109)) of 2019-09-02

The values of interprogram-paste-function and interprogram-cut-function are the default ones, gui-selection-value and gui-select-text. The behavior is the same if I use M-w instead of Cmd-C to copy the first piece, abcd, to the kill ring.

miguelmorin
  • 1,751
  • 11
  • 33
  • What is the value of `save-interprogram-paste-before-kill`? – Tobias Mar 03 '20 at 16:43
  • 3
    Side note: Emacs follows the namiong convention that `kill` means "delete plus put into the kill ring" where `delete` means "just delete without affecting the kill ring", so you can call your function `backward-delete-word`. – Stefan Mar 03 '20 at 18:37
  • @Tobias: The value of `save-interprogram-paste-before-kill` is `t`, original value was `nil`. I set it with `(setq save-interprogram-paste-before-kill t)` before binding the key to the function. – miguelmorin Mar 05 '20 at 09:50
  • 1
    If you are still interested in finding the cause of the strange kill-ring behavior, could you try with `save-interprogram-paste-before-kill` set to nil. Or better, could you try with `emacs -Q` and only your function definition? – Tobias Mar 05 '20 at 09:57
  • @Tobias I checked with my function definition and binding from the question, and with either (1) `save-interprogram-paste-before-kill` set to `nil` and restarting Emacs, or (2) launching Emacs with `emacs -Q` and using the function and keybinding in the scratch buffer. The result is as I described in the question, except that it's the *last* entry from the kill-ring that is pasted. In the course of that testing, I found weird behavior that I could not pin down and updated the question. – miguelmorin Mar 05 '20 at 10:15
  • 2
    Does this answer your question? [Backspace without adding to kill ring](https://emacs.stackexchange.com/questions/22266/backspace-without-adding-to-kill-ring) – Basil Mar 05 '20 at 11:36
  • @Basil Yes, it answers part of the question. I don't know why Emacs uses the last entry in the kill ring instead of the top one. – miguelmorin Mar 06 '20 at 12:04
  • @miguelmorin What do you mean it uses the last entry? I do not see how this follows from what you have stated above. Given that you use `Cmd-C` and that text that is not in the `kill-ring` unexpectedly appears when you `yank`, my suspicion is that all of this can be explained as some interaction between Emacs and the macOS clipboard(s). Check and/or change your values of `interprogram-paste-function` and `interprogram-cut-function`. Try using the Emacs binding `M-w` instead of `Cmd-C`. – Basil Mar 06 '20 at 12:57
  • @miguelmorin Please state your exact `M-x emacs-version RET` - is this vanilla GNU Emacs built for macOS, or some third-party build like Emacs.app, Aquamacs, etc.? I don't use macOS but judging from [`(emacs) Mac / GNUstep Basics`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Mac-_002f-GNUstep-Basics.html) it sounds like you could be mixing your primary/secondary/clipboard selections - note that these are all different "copy/paste areas". See also [`(elisp) The Kill Ring`](https://www.gnu.org/software/emacs/manual/html_node/elisp/The-Kill-Ring.html) and its subnodes. – Basil Mar 06 '20 at 13:00
  • @Basil I updated the question. Sorry for the confusion about "last entry", I now included the full kill ring. The behavior is the same with the default values of `interprogram-paste-function` and `interprogram-cut-function`, inherited from `emacs -Q`, and with `M-w` instead of `Cmd-C`. I believe `macOS` uses Quartz instead of X11, and thus am not sure that it uses GNUstep and the X-windows environment. – miguelmorin Mar 10 '20 at 10:51

1 Answers1

2

I don't know why your kill-ring gets messed up. It might be that it is some inter-program action that modifies the kill-ring.

But the right way to implement deleting instead of killing is:

(defun delete-word (arg)
  "Delete characters forward until encountering the end of a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-region (point) (progn (forward-word arg) (point))))

(defun backward-delete-word (arg)
  "Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-word (- arg)))

Note, that I just copied the stuff from simple.el and replaced kill with delete.

Tobias
  • 32,569
  • 1
  • 34
  • 75