Feeds:
Posts
Comments

Posts Tagged ‘require’

A while ago, I was trying to work around the emacs maintainers’ curious decision to always load a .elc file in preference to a .el file, even if the .el file is newer.

I didn’t want to settle for that. My solution was to recompile my emacs lisp files prior to running emacs.

I see now that there is a better alternative: replace the built-in require with my own version. And it is not just because it is open source that I can do this. I can fix it as a user too.

(require feature &optional filename noerror)

require performs the following steps:

  • do nothing if the feature has already been loaded (this protects against recursive loads)
  • finds the appropriate file in load-path
  • loads either the .el or .elc file
  • throws an error if the required feature is not provided
  • provides a mechanism for supressing errors
  • provides a mechanism to load a feature from a specific file

If I wanted a drop-in replacement, I should do all of those things, and replicate the function signature. However, I don’t need the error suppression or loading from a specific file. I also like to be able to force a load even if a library has been loaded previously. If this doesn’t match your requirements, it should be easy to adapt the code below.

(defun require* (feature &optional force)
  (when (or force (not (featurep feature)))
    (setq feature (symbol-name feature))
    (let ((path load-path)
          (found-filename nil)
          head el-attribs elc-attribs)
      (while (and (not found-filename) path)
        (setq head (pop path))
        (let ((el-filename (format "%s/%s.el" head feature))
              (elc-filename (format "%s/%s.elc" head feature)))
          ;; if .el and .elc both exist, pick the newest
          ;; otherwise pick the one that exists if any
          (cond ((and (file-exists-p el-filename)
                      (file-exists-p elc-filename))
                 (if (file-newer-than-file-p el-filename elc-filename)
                     (setq found-filename el-filename)
                   (setq found-filename elc-filename)))
                ((file-exists-p el-filename)
                 (setq found-filename el-filename))
                ((file-exists-p elc-filename)
                 (setq found-filename elc-filename)))
          ;; load file if found
          (when found-filename
            (message (format "Found: [%s]" found-filename))
            (let ((load-suffixes ()))
              (load found-filename)))))
      (unless found-filename (error "Unable to find %s" feature)))))

The brave might choose to do (defun require ...) instead of (defun require* ...)

Read Full Post »

Follow

Get every new post delivered to your Inbox.