(defgroup smart-compile nil
"An interface to `compile'."
:group 'processes
:prefix "smarct-compile")
(defcustom smart-compile-alist '(
(emacs-lisp-mode . (emacs-lisp-byte-compile))
(html-mode . (browse-url-of-buffer))
(nxhtml-mode . (browse-url-of-buffer))
(html-helper-mode . (browse-url-of-buffer))
(octave-mode . (run-octave))
("\\.c\\'" . "gcc -O2 %f -lm -o %n")
("\\.[Cc]+[Pp]*\\'" . "g++ -O2 %f -lm -o %n")
("\\.m\\'" . "gcc -O2 %f -lobjc -lpthread -o %n")
("\\.java\\'" . "javac %f")
("\\.php\\'" . "php -l %f")
("\\.f90\\'" . "gfortran %f -o %n")
("\\.[Ff]\\'" . "gfortran %f -o %n")
("\\.cron\\(tab\\)?\\'" . "crontab %f")
("\\.tex\\'" . (tex-file))
("\\.texi\\'" . "makeinfo %f")
("\\.mp\\'" . "mptopdf %f")
("\\.pl\\'" . "perl -cw %f")
("\\.rb\\'" . "ruby -cw %f")
) "List of compile commands. In argument,
some keywords beginning with '%' will be replaced by:
%F absolute pathname ( /usr/local/bin/netscape.bin )
%f file name without directory ( netscape.bin )
%n file name without extension ( netscape )
%e extension of file name ( bin )
"
:type '(repeat
(cons
(choice
(regexp :tag "Filename pattern")
(function :tag "Major-mode"))
(choice
(string :tag "Compilation command")
(sexp :tag "Lisp expression"))))
:group 'smart-compile)
(put 'smart-compile-alist 'risky-local-variable t)
(defconst smart-compile-replace-alist '(
("%F" . (buffer-file-name))
("%f" . (file-name-nondirectory (buffer-file-name)))
("%n" . (file-name-sans-extension
(file-name-nondirectory (buffer-file-name))))
("%e" . (or (file-name-extension (buffer-file-name)) ""))
))
(put 'smart-compile-replace-alist 'risky-local-variable t)
(defvar smart-compile-check-makefile t)
(make-variable-buffer-local 'smart-compile-check-makefile)
(defcustom smart-compile-make-program "make "
"The command by which to invoke the make program."
:type 'string
:group 'smart-compile)
(defun smart-compile ()
"An interface to `compile'.
It calls `compile' or other compile function,
which is defined in `smart-compile-alist'."
(interactive)
(let ((name (buffer-file-name))
(not-yet t))
(if (not name)(error "cannot get filename."))
(cond
((and (local-variable-p 'compile-command)
compile-command)
(call-interactively 'compile)
(setq not-yet nil)
)
((and smart-compile-check-makefile
(or (file-readable-p "Makefile")
(file-readable-p "makefile")))
(if (y-or-n-p "Makefile is found. Try 'make'? ")
(progn
(set (make-local-variable 'compile-command) "make ")
(call-interactively 'compile)
(setq not-yet nil)
)
(setq smart-compile-check-makefile nil)))
)
(let( (alist smart-compile-alist)
(case-fold-search nil)
(function nil) )
(while (and alist not-yet)
(if (or
(and (symbolp (caar alist))
(eq (caar alist) major-mode))
(and (stringp (caar alist))
(string-match (caar alist) name))
)
(progn
(setq function (cdar alist))
(if (stringp function)
(progn
(set (make-local-variable 'compile-command)
(smart-compile-string function))
(call-interactively 'compile)
)
(if (listp function)
(eval function)
))
(setq alist nil)
(setq not-yet nil)
)
(setq alist (cdr alist)) )
))
(if (and not-yet
(not (memq system-type '(windows-nt ms-dos)))
(not (string-match "/\\.[^/]+$" name))
(not
(and (local-variable-p 'compile-command)
compile-command))
)
(save-restriction
(widen)
(if (equal "#!" (buffer-substring 1 (min 3 (point-max))))
(set (make-local-variable 'compile-command) name)
))
)
(if not-yet (call-interactively 'compile) )
))
(defun smart-compile-string (arg)
"Document forthcoming..."
(if (and (boundp 'buffer-file-name)
(stringp buffer-file-name))
(let ((rlist smart-compile-replace-alist)
(case-fold-search nil))
(while rlist
(while (string-match (caar rlist) arg)
(setq arg
(replace-match
(eval (cdar rlist)) t nil arg)))
(setq rlist (cdr rlist))
)
))
arg)
(provide 'smart-compile)