Emacs Tips 3
This is the third part of my Emacs tips series. In this article I’ll talk about string insertion, and line deletion, marking, and yanking.
Table of contents
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 ((count (save-excursion (previous-line) (end-of-line) (current-column)))) (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
- 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 --------- ^
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, ^
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 it C-c C-a and C-c C-e, respectively.
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:
nix-env -i xclip
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.
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))
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!