blob: d52177193620f01045d776aa896ce74ef00e4e26 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
;;; show-kill-ring --- Displays Previous Kill Ring Entries -*- lexical-binding: t; coding: utf-8; -*-
;; Show Kill Ring
;; Stolen from Steve Yegge when he wasn't looking
;; enhancements and bugs added by Craig Jennings <c@cjennings.net>
;;
;;; Commentary:
;; Browse items you've previously killed.
;; Yank text using C-u, the index, then C-y.
;;
;; I've lovingly kept the nice 1970s aesthetic, complete with wood paneling.
;; Maybe I'll give it a makeover at some point.
;;
;;; Code:
(require 'cl-lib)
(defvar show-kill-max-item-size 1000
"This represents the size of a \='kill ring\=' entry.
A positive number means to limit the display of \='kill-ring\=' items to
that number of characters.")
(defun show-kill-ring-exit ()
"Exit the show-kill-ring buffer."
(interactive)
(quit-window t))
(defun show-kill-ring ()
"Show the current contents of the kill ring in a separate buffer.
This makes it easy to figure out which prefix to pass to yank."
(interactive)
;; kill existing one, since erasing it doesn't work
(let ((buf (get-buffer "*Kill Ring*")))
(and buf (kill-buffer buf)))
(let* ((buf (get-buffer-create "*Kill Ring*"))
(temp kill-ring)
(count 1)
(bar (make-string 32 ?=))
(bar2 (concat " " bar))
(item " Item ")
(yptr nil) (ynum 1))
(set-buffer buf)
(erase-buffer)
(show-kill-insert-header)
;; show each of the items in the kill ring, in order
(while temp
;; insert our little divider
(insert (concat "\n" bar item (prin1-to-string count) " "
(if (< count 10) bar2 bar) "\n"))
;; if this is the yank pointer target, grab it
(when (equal temp kill-ring-yank-pointer)
(setq yptr (car temp) ynum count))
;; insert the item and loop
(show-kill-insert-item (car temp))
(cl-incf count)
(setq temp (cdr temp)))
;; show info about yank item
(show-kill-insert-footer yptr ynum)
;; use define-key instead of local-set-key
(use-local-map (make-sparse-keymap))
(define-key (current-local-map) "q" #'show-kill-ring-exit)
;; show it
(goto-char (point-min))
(setq buffer-read-only t)
(set-buffer-modified-p nil)
;; display-buffer rather than pop-to-buffer
;; easier for user to C-u (item#) C-y
;; while the point is where they want to yank
(display-buffer buf)))
(defun show-kill-insert-item (item)
"Insert an ITEM from the kill ring into the current buffer.
If it's too long, truncate it first."
(let ((max show-kill-max-item-size))
(cond
((or (not (numberp max))
(< max 0)
(< (length item) max))
(insert item))
(t
;; put ellipsis on its own line if item is longer than 1 line
(let ((preview (substring item 0 max)))
(if (< (length item) (- (frame-width) 5))
(insert (concat preview "..."))
(insert (concat preview "\n..."))))))))
(defun show-kill-insert-header ()
"Insert the show-kill-ring header or a notice if the kill ring is empty."
(if kill-ring
(insert "Contents of the kill ring:\n")
(insert "The kill ring is empty")))
(defun show-kill-insert-footer (yptr ynum)
"Insert final divider and the yank-pointer (YPTR YNUM) info."
(when kill-ring
(save-excursion
(re-search-backward "^\\(=+ Item [0-9]+ =+\\)$"))
(insert "\n")
(insert (make-string (length (match-string 1)) ?=))
;; Use number-to-string instead of int-to-string
(insert (concat "\n\nItem " (number-to-string ynum)
" is the next to be yanked:\n\n"))
(show-kill-insert-item yptr)
(insert "\n\nThe prefix arg will yank relative to this item.")))
(defun empty-kill-ring ()
"Force garbage collection of huge kill ring entries that I don't care about."
(interactive)
(setq kill-ring nil)
(garbage-collect))
(keymap-global-set "M-K" #'show-kill-ring)
(provide 'show-kill-ring)
;;; show-kill-ring.el ends here
|