7

I save the kill-ring using the savehist package. savehist saves the kill ring with text-properties intact.

Unfortunately, this is a problem.

I have a rather large emacs config, and I use a lot of highlighting. Here is the first element of my kill-ring

#("avehist-printable value)\n         (prin1 `(setq ,symbol ',value) (current-buffer))\n          (insert ?\\n))))))\n    ;; If autosaving, avoid writing if nothing has changed since the\n    ;; last write." 0 23   (fontified t wrap-prefix     #("     " 0 5        (fontified t)))   23 24   (fontified t face     (rainbow-delimiters-depth-8-face)     wrap-prefix     #("      " 0 5        (fontified t)))   24 25   (fontified t wrap-prefix     #("     " 0 5        (fontified t)))   25 32   (fontified t wrap-prefix     #("       " 0 7        (fontified t)))   32 33   (fontified t face     (rainbow-delimiters-depth-8-face)     wrap-prefix     #("          " 0 7        (fontified t)))   33 40   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   40 41   (fontified t face     (rainbow-delimiters-depth-9-face)     wrap-prefix     #("          " 0 7        (fontified t)))   41 61   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   61 62   (fontified t face     (rainbow-delimiters-depth-9-face)     wrap-prefix     #("          " 0 7        (fontified t)))   62 63   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   63 64   (fontified t face     (rainbow-delimiters-depth-9-face)     wrap-prefix     #("          " 0 7        (fontified t)))   64 78   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   78 79   (fontified t face     (rainbow-delimiters-depth-9-face)     wrap-prefix     #("          " 0 7        (fontified t)))   79 80   (fontified t face     (rainbow-delimiters-depth-8-face)     wrap-prefix     #("          " 0 7        (fontified t)))   80 81   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   81 88   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   88 89   (fontified t face     (rainbow-delimiters-depth-8-face)     wrap-prefix     #("          " 0 7        (fontified t)))   89 99   (fontified t wrap-prefix     #("         " 0 7        (fontified t)))   99 100   (fontified t face     (rainbow-delimiters-depth-8-face)     wrap-prefix     #("         " 0 7        (fontified t)))   100 101   (fontified t face     (rainbow-delimiters-depth-7-face)     wrap-prefix     #("        " 0 7        (fontified t)))   101 102   (fontified t face     (rainbow-delimiters-depth-6-face)     wrap-prefix     #("        " 0 7        (fontified t)))   102 103   (fontified t face     (rainbow-delimiters-depth-5-face)     wrap-prefix     #("        " 0 7        (fontified t)))   103 104   (fontified t face     (rainbow-delimiters-depth-4-face)     wrap-prefix     #("        " 0 7        (fontified t)))   104 105   (fontified t face     (rainbow-delimiters-depth-3-face)     wrap-prefix     #("        " 0 7        (fontified t)))   105 106   (fontified t wrap-prefix     #("       " 0 7        (fontified t)))   106 110   (fontified t wrap-prefix     #("    ;; " 0 4        (fontified t)        4 7        (fontified t face font-lock-comment-delimiter-face)))   110 113   (fontified t face font-lock-comment-delimiter-face wrap-prefix     #("    ;; " 0 4        (fontified t)        4 7        (fontified t face font-lock-comment-delimiter-face)))   113 175   (fontified t face font-lock-comment-face wrap-prefix     #("    ;; " 0 4        (fontified t)        4 7        (fontified t face font-lock-comment-delimiter-face)))   175 179   (fontified t wrap-prefix     #("    ;; " 0 4        (fontified t)        4 7        (fontified t face font-lock-comment-delimiter-face)))   179 182   (fontified t face font-lock-comment-delimiter-face wrap-prefix     #("    ;; " 0 4        (fontified t)        4 7        (fontified t face font-lock-comment-delimiter-face)))   182 193   (fontified t face font-lock-comment-face wrap-prefix     #("    ;; " 0 4        (fontified t)        4 7        (fontified t face font-lock-comment-delimiter-face))))

In essence, text properties bloat my ~/.emacs.d/savehist by almost a factor of 100. I'm looking at ~30MB of kill ring. This is bad for all sorts of reasons. Not least because it makes emacs very slow.

How can I tell savehist to strip text properties from the kill-ring before saving, without deleting the properties for the current session?

10

Add the following to your init-file:

(defun unpropertize-kill-ring ()
  (setq kill-ring (mapcar 'substring-no-properties kill-ring)))

(add-hook 'kill-emacs-hook 'unpropertize-kill-ring)

How it works

substring-no-properties removes any text properties from a given string. kill-ring is a list of strings; we're using mapcar to apply substring-no-properties to each string that is currently in the kill ring. The result of the mapcar call (i.e., a list of strings without any text properties) is used to override the original value of kill-ring.

savehist-mode saves the minibuffer history and any additional variables in savehist-additional-variables when you quit Emacs. So in the last line we simply tell Emacs to "unpropertize" the kill ring on quit. Note that this happens before savehist does its thing because add-hook prepends functions by default, so unpropertize-kill-ring will be called before savehist-autosave (which is the actual function that gets executed when you quit Emacs).

  • Are you aware of savehist-save-hook? – PythonNut Dec 8 '14 at 4:57
  • 1
    @PythonNut Yes I am. If you never call savehist-save manually, you can add the function for "unpropertizing" strings to savehist-save-hook instead of kill-emacs-hook. But if you want to preserve the option of calling savehist-save during an editing session without losing text properties of recent kill ring entries, kill-emacs-hook is a better choice. – itsjeyd Dec 8 '14 at 12:04
  • Thank you, I just wanted to make sure that wasn't a solution. – PythonNut Dec 9 '14 at 19:34
6

One simple solution is to use savehist-20.el.

It is a version of savehist.el that works with all Emacs versions (20+). It automatically strips history elements of properties, and it does not save variables in savehist-additional-variables whose values are propertized strings.

In other words, you can read the file it saves even in an Emacs version (e.g. 20) that barfs on propertized strings.

  • Basically all of the elements of kill-ring are propertied, so it sounds like this would trow away the kill-ring wholesale. – PythonNut Dec 7 '14 at 22:13
  • Yes. (If you don't want that then you can tweak one line of the code.) – Drew Dec 7 '14 at 23:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.