yank-popAfter understanding yank and current-kill, you know how
to approach the yank-pop function. Leaving out the
documentation to save space, it looks like this:
(defun yank-pop (&optional arg)
"…"
(interactive "*p")
(if (not (eq last-command 'yank))
(error "Previous command was not a yank"))
(setq this-command 'yank)
(unless arg (setq arg 1))
(let ((inhibit-read-only t)
(before (< (point) (mark t))))
(if before
(funcall (or yank-undo-function 'delete-region) (point) (mark t))
(funcall (or yank-undo-function 'delete-region) (mark t) (point)))
(setq yank-undo-function nil)
(set-marker (mark-marker) (point) (current-buffer))
(insert-for-yank (current-kill arg))
;; Set the window start back where it was in the yank command,
;; if possible.
(set-window-start (selected-window) yank-window-start t)
(if before
;; This is like exchange-point-and-mark,
;; but doesn't activate the mark.
;; It is cleaner to avoid activation, even though the command
;; loop would deactivate the mark because we inserted text.
(goto-char (prog1 (mark t)
(set-marker (mark-marker)
(point)
(current-buffer))))))
nil)
The function is interactive with a small ‘p’ so the prefix
argument is processed and passed to the function. The command can
only be used after a previous yank; otherwise an error message is
sent. This check uses the variable last-command which is set
by yank and is discussed elsewhere.
(See copy-region-as-kill.)
The let clause sets the variable before to true or false
depending whether point is before or after mark and then the region
between point and mark is deleted. This is the region that was just
inserted by the previous yank and it is this text that will be
replaced.
funcall calls its first argument as a function, passing
remaining arguments to it. The first argument is whatever the
or expression returns. The two remaining arguments are the
positions of point and mark set by the preceding yank command.
There is more, but that is the hardest part.