├── README.md
└── cl-libify.el
/README.md:
--------------------------------------------------------------------------------
1 | [](http://melpa.org/#/cl-libify)
2 | [](http://stable.melpa.org/#/cl-libify)
3 |
4 |
5 | # Update Emacs Lisp code to use cl-lib instead of cl
6 |
7 | `cl` is a deprecated library, and elisp authors should use `cl-lib`
8 | instead. In most cases, this is a matter of requiring "cl-lib" and
9 | adding a "cl-" prefix to symbols that came from "cl".
10 |
11 | This library provides an interactive command, `cl-libify`, which
12 | replaces usages of "cl" symbols with their "cl-lib" equivalent,
13 | optionally prompting for each
14 |
15 | Note that some cl functions do not have exact replacements,
16 | e.g. `flet`, so further code changes might still be necessary.
17 |
18 | You can also use `cl-libify-mark-cl-symbols-obsolete` to mark old `cl`
19 | names as obsolete, so that the byte compiler will help flag their use.
20 |
21 | ## Installation
22 |
23 | ### Manual
24 |
25 | Ensure `cl-libify.el` is in a directory on your load-path, and
26 | add the following to your `~/.emacs` or `~/.emacs.d/init.el`:
27 |
28 | ```elisp
29 | (require 'cl-libify)
30 | ```
31 |
32 | ### MELPA
33 |
34 | If you're an Emacs 24 user or you have a recent version of
35 | `package.el` you can install `cl-libify` from the
36 | [MELPA](http://melpa.org) repository. The version of
37 | `cl-libify` there will always be up-to-date.
38 |
39 | See the command `cl-libify`.
40 |
41 | ## About
42 |
43 | Author: Steve Purcell
44 |
45 | Homepage: https://github.com/purcell/cl-libify
46 |
47 | This little library was extracted from the author's
48 | [full Emacs configuration](https://github.com/purcell/emacs.d), which
49 | readers might find of interest.
50 |
51 |
52 |
53 | [💝 Support this project and my other Open Source work](https://www.patreon.com/sanityinc)
54 |
55 | [💼 LinkedIn profile](https://uk.linkedin.com/in/stevepurcell)
56 |
57 | [✍ sanityinc.com](http://www.sanityinc.com/)
58 |
--------------------------------------------------------------------------------
/cl-libify.el:
--------------------------------------------------------------------------------
1 | ;;; cl-libify.el --- Update elisp code to use cl-lib instead of cl -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2018 Steve Purcell
4 |
5 | ;; Author: Steve Purcell
6 | ;; Keywords: lisp
7 | ;; Homepage: https://github.com/purcell/cl-libify
8 | ;; Package-Requires: ((emacs "25"))
9 | ;; Package-Version: 0
10 |
11 | ;; This program is free software; you can redistribute it and/or modify
12 | ;; it under the terms of the GNU General Public License as published by
13 | ;; the Free Software Foundation, either version 3 of the License, or
14 | ;; (at your option) any later version.
15 |
16 | ;; This program is distributed in the hope that it will be useful,
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | ;; GNU General Public License for more details.
20 |
21 | ;; You should have received a copy of the GNU General Public License
22 | ;; along with this program. If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; `cl' is a deprecated library, and elisp authors should use `cl-lib'
27 | ;; instead. In most cases, this is a matter of requiring "cl-lib" and
28 | ;; adding a "cl-" prefix to symbols that came from "cl".
29 |
30 | ;; This library provides an interactive command, `cl-libify', which
31 | ;; replaces usages of "cl" symbols with their "cl-lib" equivalent,
32 | ;; optionally prompting for each
33 |
34 | ;; Note that some cl functions do not have exact replacements,
35 | ;; e.g. `flet', so further code changes might still be necessary.
36 |
37 | ;; You can also use `cl-libify-mark-cl-symbols-obsolete' to mark old
38 | ;; `cl' names as obsolete, so that the byte compiler will help flag
39 | ;; their use.
40 |
41 | ;;; Code:
42 |
43 |
44 | (require 'cl-lib)
45 | (eval-when-compile
46 | (with-no-warnings
47 | (require 'cl)))
48 |
49 | (defconst cl-libify-function-alias-alist
50 | (eval-when-compile
51 | (cl-loop for s being the symbols
52 | for sf = (symbol-function s)
53 | for nm = (symbol-name s)
54 | when (and sf
55 | (symbolp sf)
56 | (not (string= (symbol-name sf) nm))
57 | (string-prefix-p "cl-" (symbol-name sf))
58 | (not (string-prefix-p "cl-" nm)))
59 | collect (cons s sf)))
60 | "Alist of symbols pairs mapping cl functions to their cl-lib equivalents.")
61 |
62 | (defconst cl-libify-var-alias-alist
63 | (eval-when-compile
64 | (cl-loop for s being the symbols
65 | for sf = (indirect-variable s)
66 | for nm = (symbol-name s)
67 | when (and (not (eq sf s))
68 | (not (string= (symbol-name sf) nm))
69 | (string-prefix-p "cl-" (symbol-name sf))
70 | (not (string-prefix-p "cl-" nm)))
71 | collect (cons s sf)))
72 | "Alist of symbols pairs mapping cl variables to their cl-lib equivalents.")
73 |
74 | (defconst cl-libify-other-functions
75 | '(
76 | lexical-let
77 | lexical-let*
78 | flet
79 | labels
80 | define-setf-expander
81 | defsetf
82 | define-modify-macro)
83 | "Functions from `cl' which have no direct `cl-lib' equivalent.")
84 |
85 | ;;;###autoload
86 | (defun cl-libify (beg end)
87 | "Replace cl symbol names between BEG and END with their cl-lib equivalents.
88 |
89 | If no region is supplied, this operates on the entire
90 | buffer. With prefix argument PROMPT, ask the user to confirm each
91 | replacement."
92 | (interactive "r")
93 | (unless (use-region-p)
94 | (setq beg (point-min)
95 | end (point-max)))
96 | (let ((prompt current-prefix-arg))
97 | (cl-libify--replace-in-region prompt beg end "[(']" cl-libify-function-alias-alist)
98 | (cl-libify--replace-in-region prompt beg end "" cl-libify-var-alias-alist)))
99 |
100 | (defun cl-libify--replace-in-region (prompt beg end prefix alist)
101 | "Between BEG and END, replace keys of ALIST with their matching values.
102 | Keys must be distinct symbols which follow the regexp PREFIX.
103 | That regexp must not contain any capture groups. When PROMPT is
104 | non-nil, ask the user to confirm each replacement."
105 | (save-excursion
106 | (goto-char beg)
107 | (let ((end-marker (set-marker (make-marker) end))
108 | (pat (regexp-opt (mapcar 'symbol-name (mapcar 'car alist)) 'symbols)))
109 | (while (search-forward-regexp (concat prefix pat) end-marker t)
110 | (unless (cl-libify--in-string-or-comment)
111 | (let* ((orig (match-string 1))
112 | (replacement (symbol-name (alist-get (intern orig) alist))))
113 | (when (or (null prompt)
114 | (let ((msg (format "Replace `%s' with `%s'?" orig replacement)))
115 | (save-match-data (y-or-n-p msg))))
116 | (replace-match replacement t t nil 1))))))))
117 |
118 | (defun cl-libify--in-string-or-comment ()
119 | "Return non-nil if point is within a string or comment."
120 | (let ((ppss (syntax-ppss)))
121 | (or (car (setq ppss (nthcdr 3 ppss)))
122 | (car (setq ppss (cdr ppss)))
123 | (nth 3 ppss))))
124 |
125 | ;;;###autoload
126 | (defun cl-libify-mark-cl-symbols-obsolete ()
127 | "Make all the `cl' vars and functions obsolete so that byte compilation will flag their use."
128 | (interactive)
129 | (pcase-dolist (`(,old . ,new) cl-libify-function-alias-alist)
130 | (make-obsolete old new "cl-lib"))
131 | (pcase-dolist (`(,old . ,new) cl-libify-var-alias-alist)
132 | (make-obsolete-variable old new "cl-lib")))
133 |
134 |
135 | (provide 'cl-libify)
136 | ;;; cl-libify.el ends here
137 |
--------------------------------------------------------------------------------