Emacs Tips and Tricks 3: Insert and Delete

Esperanto | English
Last updated: March 18, 2022

The more you sweat in peace, the less you bleed in war.
—Norman Schwarzkopf

jr-korpa-E2i7HftbrI-unsplash

Table of contents

Introduction

This is the continuation of my series on Emacs tips and tricks. In this article, we explore string insertion, and line deletion, marking, and yanking.

Insertion

I work with a lot of Markdown files and I want a way to easily insert characters and strings.

To insert a code section using backticks:

(defun insert-backticks (&optional arg)
  "Insert three backticks for code blocks"
  (interactive)
  (insert "``````")
  (backward-char 3))

I bound it to M-g `.

To move to a specific column:

(defun go-to-column (column)
  "Move to a column inserting spaces as necessary"
  (interactive "nColumn: ")
  (move-to-column column t))

I bound it to M-g ..

To insert a string until the last column of the previous line:

(defun insert-until-last (string)
  "Insert string until column"
  (let* ((end (save-excursion
                 (previous-line)
                 (end-of-line)
                 (current-column)))
         (count (if (not (zerop (current-column)))
                    (- end (current-column))
                  end)))
    (dotimes (c count)
      (insert string))))

This function, together with the following interactive functions:

(defun insert-equals (&optional arg)
  "Insert equals until the same column number as last line"
  (interactive)
  (insert-until-last "="))

(defun insert-hyphens (&optional arg)
  "Insert hyphens until the same column number as last line"
  (interactive)
  (insert-until-last "-"))

Will make insertion of = and - easier when creating H1 and H2 headings.

I bound them to M-g = and M-g -, respectively.

If you have the following line, where ^ is point:

Foo Bar Baz

^

When I press M-g =, it will become:

Foo Bar Baz
===========
           ^

Conversely, if I have:

Foo Bar Baz
===========


Section I

^

When I press M-g -, it will become:

Foo Bar Baz
===========


Section I
---------
         ^

Deletion

I want convenient functions to delete from point to start and end:

(defun delete-to-bol (&optional arg)
  "Delete to beginning of line"
  (interactive "p")
  (delete-region (point) (save-excursion (beginning-of-line) (point))))

(defun delete-to-eol (&optional arg)
  "Delete to end of line"
  (interactive "p")
  (delete-region (point) (save-excursion (end-of-line) (point))))

I bound them to C-c ^ and C-c $, respectively.

If I have:

A journal about computing, human predilections, and random krakaboom.
                           ^

Then, I press C-c ^, it will become:

human predilections, and random krakaboom.
^

Conversely, if I press C-c $, it will become:

A journal about computing, 
                           ^

Marking

There are many times when I want to make a region from point to start and end. For that, I have the following:

(defun mark-to-bol (&optional arg)
  "Create a region from point to beginning of line"
  (interactive "p")
  (mark-thing 'point 'beginning-of-line))

(defun mark-to-eol (&optional arg)
  "Create a region from point to end of line"
  (interactive "p")
  (mark-thing 'point 'end-of-line))

I bound them C-c C-a and C-c C-e, respectively.

Yanking

I want to be able to yank from the clipboard to Emacs, especially when I’m on the terminal.

First, we need to install xclip:

Nixpkgs:

nix-env -i xclip

APT:

sudo apt-get install -y xclip

Then, we add in the Emacs Lisp code:

(defun yank-primary (&optional arg)
  "Yank the primary selection"
  (interactive)
  (insert (shell-command-to-string "xclip -selection primary -o")))

(defun yank-clipboard (&optional arg)
  "Yank the clipboard selection"
  (interactive)
  (insert (shell-command-to-string "xclip -selection clipboard -o")))

The primary selection is the one activated when doing mouse highlights, while the clipboard selection is the one used when you invoke the Copy command from an application, or when Ctrl+c is pressed.

Keys

Here’s the relevant snippet for all the commands discussed in this article. If you don’t have bind-key yet, you may install it with:

M-x package-install RET bind-key RET
(bind-keys
 :global-map
 ("C-c ^" . delete-to-bol)
 ("C-c $" . delete-to-eol)

 ("C-c ," . mark-to-bol)
 ("C-c ." . mark-to-eol)

 ("C-x y" . yank-clipboard)
 ("C-x C-y" . yank-primary)

 ("M-g SPC" . go-to-column)
 ("M-g `" . insert-backticks)
 ("M-g =" . insert-equals)
 ("M-g -" . insert-hyphens))

Closing remarks

These functions and key bindings make it significantly convenient for me when working with emacsclient on the terminal, due to the fact that some keyboard control codes are not received by the terminal emulator itself. By leveraging on external tools, I get a consistent behavior across platforms.

As always, the source is available here. If you have a tip to share, send in your pull request!