Introduction
Hello! In our last lesson, we gained the ability to navigate within an Emacs buffer by programmatically controlling the point and mark. We learned how to find our location with (point) and move to specific positions with functions like (goto-char) and (beginning-of-buffer).
Today, we'll build directly on that foundation. Now that we can place the cursor exactly where we want it, we'll learn how to add new content at that position. This lesson addresses the learning outcome: Insert text into a buffer programmatically using insert.
This is a fundamental skill for your goal of extending Emacs. Whether you're creating a command to insert a boilerplate for a new speculative fiction chapter, a template for character notes, or a formatted timestamp, you'll be using the insert function.
1. The insert Function
The primary tool for programmatically adding text to a buffer is the insert function. Its operation is straightforward: it inserts its arguments into the current buffer at the current location of the point. The point then moves to the end of the inserted text.
The insert function is very flexible and can accept multiple arguments, which it will insert in sequence. These arguments are typically strings, but can also be characters.

Let's watch a quick demonstration of the basics.
Reading and Writing Buffers in Practice - Learning Emacs Lisp #5
This clip from the 'Learning Emacs Lisp' series by System Crafters provides a clear and concise introduction to insert and its companion, insert-char.
Watch from 00:50:14 to 00:51:12. Pay attention to how insert can handle multiple arguments and how insert-char can be used to repeat a character.
As you saw in the video, you can use insert like this in your *scratch* buffer. Place your cursor somewhere and evaluate these expressions with C-x C-e:
;; Inserts a single string at point
(insert "A long time ago in a galaxy far, far away....")
;; Inserts multiple strings and a newline character in sequence
(insert "It was a dark " "and stormy " "night.\n")
The video also mentioned insert-char. This function is optimized for inserting a single character, with an optional argument to specify how many times it should be inserted. This can be useful for creating dividers or simple ASCII art.
;; Inserts the character 'X' five times
(insert-char ?X 5)
This produces XXXXX in the buffer.
2. Combining Movement and Insertion
The true power of insert is unlocked when you combine it with the point-manipulation functions from our previous lesson. By first moving the point to a specific location, you can control precisely where your text appears.
A common pattern is to:
- Move the point to a target location (e.g., beginning of the buffer).
- Insert the desired text.
The following video segment illustrates this perfectly. It first shows how to insert a title at the top of a file by combining goto-char and insert.
Emacs Lisp 101 - Write a useful function Today!!
Let's watch this clip from 'Emacs Lisp 101' by Mostly Code. It demonstrates how to combine movement and insertion to build a practical function.
Watch from 07:45 to 10:43. Notice how (goto-char (point-min)) is called before (insert ...) to ensure the text is placed at the very beginning of the buffer.
Here is the core logic from the video:
(defun insert-title-at-top (title)
"Insert a TITLE at the beginning of the buffer."
(interactive "sEnter title: ")
;; 1. Move to the top
(goto-char (point-min))
;; 2. Insert the formatted text
(insert ";; Title: " title "\n\n"))
However, as we discussed in the last lesson, this function has a side effect: it moves the user's cursor. To create a well-behaved command that doesn't disrupt the user's workflow, we should wrap the logic in save-excursion.
This next clip shows exactly how to do that.
Emacs Lisp 101 - Write a useful function Today!!
Now, let's see how to improve the function by using save-excursion.
Watch from 12:16 to 15:16. The key takeaway is how goto-char and insert are wrapped within the save-excursion form. The function now inserts text at the top of the buffer but leaves the cursor in its original position.
The improved, non-disruptive pattern looks like this:
(defun insert-title-at-top-safely (title)
"Insert a TITLE at the beginning of the buffer without moving point."
(interactive "sEnter title: ")
(save-excursion
;; All movement and modification happens inside here
(goto-char (point-min))
(insert ";; Title: " title "\n\n")))
This (save-excursion (goto-char ...) (insert ...)) pattern is one of the most common and useful idioms in Emacs Lisp.
3. Your Turn: Create a Character Template Inserter
Now it's time to apply these concepts to a task relevant to your creative writing workflow. Your goal is to create an interactive command that inserts a simple character profile template into the current buffer.
Task:
Write a function named ar-insert-character-template that, when called interactively:
- Inserts a predefined character profile template at the current
point. - The template should contain placeholders for a character's name, role, and a brief description.
Here's the text for the template. Note the use of \n to create new lines.
"# Character Profile\n\n- **Name:** \n- **Role:** \n- **Description:** \n"
Instructions:
- Use
defunto define your function. - Make it interactive with
(interactive). - Use the
insertfunction to add the template text.
Give it a try in your *scratch* buffer. After defining the function with C-x C-e, you can run it by typing M-x ar-insert-character-template.
Click here for a solution
(defun ar-insert-character-template ()
"Insert a character profile template at point."
(interactive)
(insert "# Character Profile\n\n- **Name:** \n- **Role:** \n- **Description:** \n"))
When you run this, the template will appear wherever your cursor is.
Bonus Challenge:
Modify your function so that it always inserts the template at the end of the buffer, but leaves your cursor where it was.
Hints:
- You'll need to wrap your
insertcall insave-excursion. - Inside
save-excursion, you'll first need to move to the end of the buffer. The function(point-max)will be useful here.
Click here for the bonus solution
(defun ar-insert-character-template-at-end ()
"Insert a character profile template at the end of the buffer."
(interactive)
(save-excursion
(goto-char (point-max))
;; Ensure there's a newline before the template if not at the very beginning
(unless (bobp) (insert "\n"))
(insert "# Character Profile\n\n- **Name:** \n- **Role:** \n- **Description:** \n")))
Note: (bobp) is a handy function that returns t if the point is at the beginning of the buffer (beginning-of-buffer-p). This avoids adding an unnecessary blank line at the top of an empty file.
Conclusion
In this lesson, you've mastered the essential skill of programmatically inserting text into an Emacs buffer. By combining insert with the positional tools from our last session, you can now place any text anywhere you need it.
Key Takeaways:
insertis Your Tool: The(insert ...)function is the primary way to add text to a buffer at thepoint.- Combine and Conquer: The real utility comes from combining
insertwith point-manipulation functions likegoto-char,point-min, andpoint-max. - The
save-excursionIdiom: To write professional, non-disruptive commands, always wrap your buffer-modifying code in(save-excursion ...)to restore the point's original position.
Preview of the Next Lesson
We can now move within buffers and insert text. But what if we want to modify text that's already there? To do that, we first need to find it. In our next lesson, we will learn how to search for text in a buffer using search-forward. This will open the door to a whole new level of automation, allowing us to build functions that can locate and then act upon specific content in our documents.