├── README.md └── cl-libify.el /README.md: -------------------------------------------------------------------------------- 1 | [![Melpa Status](http://melpa.org/packages/cl-libify-badge.svg)](http://melpa.org/#/cl-libify) 2 | [![Melpa Stable Status](http://stable.melpa.org/packages/cl-libify-badge.svg)](http://stable.melpa.org/#/cl-libify) 3 | Support me 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 | --------------------------------------------------------------------------------