UP | HOME
Emacs make runner

Emacs make runner

Table of Contents

Description

The purpose of this is to ease the running of makefiles.

It does this adding 3 features. One is searching upwards from the current buffer's file's directory until a Makefile is found. The second is fetching targets from the file to use for auto-completion. And the third is remembering the last target.

Quirks

As mentioned in the my-make self-documentation, to run the make with no target you can use ".". This is not intuitive and I would have preferred to have used just a space, but that is already defined as auto-complete. If anyone know a good way around this, I would appreciate the information.

Code

(defun my-dir-upsearch (path files)
  "search PATH upwards until one of FILES is found."
  (let ((out (or (null (string-match "/" path))
                 (my-find (lambda (x)
                            (let ((f (concat path "/" x)))
                              (and (file-exists-p f) f)))
                          files)
                 (my-dir-upsearch (replace-regexp-in-string 
                                   "/[^/]*/?$" "" path)
                                  files))))
    (if (stringp out)
        out
      nil)))

(defun my-get-makefile-targets (f)
  (with-temp-buffer
    (insert-file f)
    (end-of-buffer)
    (let ((v (lambda (v)
               (if (re-search-backward "^\\([^:\n#[:space:]]+?\\):" 
                                       (not 'bound) 'noerror)
                   (cons (match-string 1) (funcall v v))
                 '()))))
      (funcall v v))))

(defvar my-make-last-target ""
  "holds the last target, and what is used if no input is given
  when doing my-make")

(defun my-make ()
  "Runs closest Makefile with specified target.

Closest Makefile means first Makefile found when seacrching
upwards from the current buffer's file's directory.

If no target is specified the last target will be used.

To force running make without a target use the fake target \".\"."
  (interactive)
  (let ((makefile (my-dir-upsearch (buffer-file-name) (list "Makefile"))))
    (if (not makefile)
        (message "No Makefile found.")
      (let* ((targets (my-get-makefile-targets makefile))
             (prompt (if (string= "" my-make-last-target)
                         "Target: "
                       (concat "Target (" my-make-last-target "): ")))
             (target (completing-read prompt targets nil nil))
             (target (cond ((string= "" target) my-make-last-target)
                           ((string= "." target) "")
                           (t target))))
        (setq my-make-last-target target)
        (compile (concat "cd " (file-name-directory makefile) "; "
                         "make " target))))))


(global-set-key (kbd "F11") 'my-make)

Installation

Copy-paste the code into your .emacs file and restart Emacs.

Open some file near a Makefile and press F11.

Comments


Author: Dan Amlund <danamlund@gmail.com>

Date: 2009-12-12 Sat

HTML generated by org-mode 6.31trans in emacs 23