Emacs Delete vs. Kill
Tags: emacs
Published: 2018-07-04 18:07:34

---
title: Emacs Delete vs. Kill
published: true
tags: emacs
canonical_url: http://www.gonsie.com/blorg/delete-v-kill.html
---

One thing that has always vexed me is the Emacs kill ring. It’s great that it makes a list of things you’ve killed, but often I just want delete things quickly without saving it. So I need to change the default settings to enable both killing and deleting words and lines.

Basic nomenclature (for this blog post at least);

- kill means removing text and putting it in the kill ring
- delete means removing text and not putting it in the kill ring

## Understanding Key Bindings

The default behavior of Emacs can depend on the underlying operating system. This is because key presses are first translated by the OS, then passed (if they don’t trigger an OS function) to the application, e.g., Emacs. This can be further complicated by the keyboard setup and, further still, by an Emacs instance running inside of a Terminal.

To figure out the name that Emacs itself has for each key, use `C-h k KEY` or `M-x describe-key KEY`. This internal name will come in handy when rebinding these keys.

For extended keyboards, there are often two “delete” keys, one which performs a backspace and one which does a forward delete. The forward delete is often found on the “keypad” or number pad and is thus called `kp-delete` by Emacs.

### Mac Keyboards

Mac keyboards have the following modifier keys: Shift, Control, Option (Alt), and Command. While Shift and Control are already mapped for Emacs (known as `S` and `C` respectively), the Option and Command keys are not mapped. I use Option/Alt as a meta (`M`) key and Command as a super (`s`) key.

```
(setq mac-command-modifier 'super) ;; command -> s
(setq mac-option-modifier 'meta) ;; option/alt -> M
```

## Default Commands

By default, the `delete` key removes a single letter (backwards). In Emacs keybindings, this is sometimes denoted as `backspace` (in addition to sometimes being called `delete`). `M-delete` (`ALT-delete` on a Mac keyboard) will remove a whole word, but place it in the kill ring. Killing a line is simple: `C-k`, but this kills a line forwards.

Putting the most recently killed word or line back is `C-y`, called yanking. Yanking previous items in the ring is achieved with `M-y`, which will cycle through the ring.

## Combinations

There is a 3 dimensional problem to solve here, with 16 possible combinations (14 unique operations):

1. Removal direction (backwards or forwards)
2. Removal type (kill or delete)
3. Removal size (character, word, visual line, whole line)

### Direction

I use the Mac internal for marking the direction as backwards or forwards. Even on laptop keyboards, I can use `Fn-delete` to get the forwards deletion.

The whole line removal does not have a direction, but must be bound to both `delete` and `kp-delete`.

### Removal Type

The un-modified delete key-press should trigger a character delete. Using the meta (`M`) modifier triggers a word removal. Using the control (`C`) modifier triggers a line removal.

### Saving Items to the Kill Ring

I use the Shift (`S`) modifier to explicitly trigger adding the removed text to the kill ring.

## Binding the Keys

The following table tracks all the combinations which must be implemented. The implementation looks like:

```
(global-set-key (kbd "<<keybinding>>") '<<function>>)
```

| Direction | Type | Save | Key Binding | Function |
| --- | --- | --- | --- | --- |
| Backwards | Char | No | `<delete>` | None needed |
| |<del>Char</del> | <del>Yes</del> | | Not implemented |
| | Word | No |`<M-delete>` | `backward-delete-word` \*|
| | Word | Yes|`<M-S-backspace>` | `backward-kill-word` |
| | Line | No |`<C-backspace>`|`backward-delete-line` \*|
| | Line |Yes |`<C-S-backspace>`|`backward-kill-line` \*|
|Forwards|Char|No|`<kp-delete>`|`delete-forward-char`|
| |<del>Char</del>|<del>Yes</del>| |Not implemented |
| | Word | No |`<M-kp-delete>`|`delete-word` \*|
| | Word | Yes|`<M-S-kp-delete>`|`kill-word`|
| | Line | No |`<C-kp-delete>`|`delete-line` \* |
| | Line | Yes|`<C-S-kp-delete>`|`kill-line`|
|Both|Line|No|`<s-backspace>` and `<s-kp-delete>`|`delete-current-line` \*|
|Both|Line|Yes|`<s-S-backspace>` and `<s-S-kp-delete>`|`kill-whole-line`|

The functions marked with a \* must be implemented, as such:

<p></p>
<pre><code data-lang="elisp"><span>;; from https://stackoverflow.com/a/12990359/1160876</span>
<span>(</span><span>defun</span> <span>backward-delete-word</span> <span>(</span><span>arg</span><span>)</span>
  <span>"Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."</span>
  <span>(</span><span>interactive</span> <span>"p"</span><span>)</span>
  <span>(</span><span>delete-region</span> <span>(</span><span>point</span><span>)</span> <span>(</span><span>progn</span> <span>(</span><span>backward-word</span> <span>arg</span><span>)</span> <span>(</span><span>point</span><span>))))</span>

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

<span>(</span><span>defun</span> <span>backward-delete-line</span> <span>(</span><span>arg</span><span>)</span>
  <span>"Delete (not kill) the current line, backwards from cursor.
With argument ARG, do this that many times."</span>
  <span>(</span><span>interactive</span> <span>"p"</span><span>)</span>
  <span>(</span><span>delete-region</span> <span>(</span><span>point</span><span>)</span> <span>(</span><span>progn</span> <span>(</span><span>beginning-of-visual-line</span> <span>arg</span><span>)</span> <span>(</span><span>point</span><span>))))</span>

<span>(</span><span>defun</span> <span>delete-line</span> <span>(</span><span>arg</span><span>)</span>
  <span>"Delete (not kill) the current line, forwards from cursor.
With argument ARG, do this that many times."</span>
  <span>(</span><span>interactive</span> <span>"p"</span><span>)</span>
  <span>(</span><span>delete-region</span> <span>(</span><span>point</span><span>)</span> <span>(</span><span>progn</span> <span>(</span><span>end-of-visual-line</span> <span>arg</span><span>)</span> <span>(</span><span>point</span><span>))))</span>

<span>(</span><span>defun</span> <span>backward-kill-line</span> <span>(</span><span>arg</span><span>)</span>
  <span>"Kill the current line, backwards from cursor.
With argument ARG, do this that many times."</span>
  <span>(</span><span>interactive</span> <span>"p"</span><span>)</span>
  <span>(</span><span>kill-region</span> <span>(</span><span>point</span><span>)</span> <span>(</span><span>progn</span> <span>(</span><span>beginning-of-visual-line</span> <span>arg</span><span>)</span> <span>(</span><span>point</span><span>))))</span>

<span>;; from https://stackoverflow.com/a/35711240/1160876</span>
<span>(</span><span>defun</span> <span>delete-current-line</span> <span>(</span><span>arg</span><span>)</span>
  <span>"Delete (not kill) the current line."</span>
  <span>(</span><span>interactive</span> <span>"p"</span><span>)</span>
  <span>(</span><span>save-excursion</span>
    <span>(</span><span>delete-region</span>
     <span>(</span><span>progn</span> <span>(</span><span>forward-visible-line</span> <span>0</span><span>)</span> <span>(</span><span>point</span><span>))</span>
     <span>(</span><span>progn</span> <span>(</span><span>forward-visible-line</span> <span>arg</span><span>)</span> <span>(</span><span>point</span><span>)))))</span></code></pre>

## Summary

I am very happy with how cleanly these keybindings map to functionality.
Let's see if I can actually put these to use!