In my .emacs file I have initializations to smash various modes
in various ways. For example:
(setq sql-mode-font-lock-keywords sql-mode-oracle-font-lock-keywords)
(define-key tcl-mode-map [(meta backspace)] 'backward-kill-word)
(define-key makefile-mode-map "$" 'self-insert-command)
(define-key makefile-mode-map "\^x\$" 'makefile-insert-macro-ref)
However doing these things require that I load all of the packages
first.
(require 'sql)
(require 'tcl)
(require 'makefile)
Is there some standard way to do initializations like these (that
require that the file be loaded first) without causing the file to
be loaded? Basically what I want is a load-hook, but most packages
do not have load hooks (comint has one).
I hacked something up to do what I wanted, but there's got to
be a better way.
-jeff
Example:
;; stuff to do after sql gets loaded
(after-provided 'sql
'(lambda () (setq sql-mode-font-lock-keywords sql-mode-oracle-font-lock-keywords)))
;; stuff to do after tcl gets loaded
(after-provided 'tcl
'(lambda () (define-key tcl-mode-map [(meta backspace)] 'backward-kill-word)))
;; stuff to do after makefile gets loaded
(after-provided 'makefile
'(lambda ()
(define-key makefile-mode-map "$" 'self-insert-command)
(define-key makefile-mode-map "\^x\$" 'makefile-insert-macro-ref)))
;; Keep track of nesting level of require/load. Don't do after-provide stuff until
we
;; know that we are done loading the files. Some files do the provide at the top of the
file
(defvar load-level 0)
;; Track packages that have been provided.
(defvar provided ())
(put 'after-provided 'lisp-indent-function 1)
(defun after-provided (symbol function)
(if (memq symbol features)
;; Package has already been loaded, just do it.
(progn
;;(message "already loaded %s" symbol)
(funcall function))
;; Keep function around until package gets provided.
(setf (get symbol 'after-provide)
(cons function (get symbol 'after-provide)))))
(defun provided (symbol)
(while (not (null (get symbol 'after-provide)))
;;(message "after %s" symbol)
(funcall (pop (get symbol 'after-provide)))))
(defadvice load (around first activate protect)
(incf load-level)
ad-do-it
(decf load-level)
;; If load has caused some packages to have been provided then do after stuff, when done
loading.
(when (zerop load-level)
(while (not (null provided))
(provided (pop provided)))))
(defadvice provide (around first activate protect)
(incf load-level)
ad-do-it
(decf load-level)
(push (ad-get-arg 0) provided)
;; Some packages to have been provided do after stuff, when done loading.
;; Doing a (provide 'foo) at top level will cause the after stuff to run.
(when (zerop load-level)
(while (not (null provided))
(provided (pop provided)))))
(defadvice require (around first activate protect)
(incf load-level)
ad-do-it
(decf load-level)
;; We're done doing require, look for packages that have been provided.
(when (zerop load-level)
(while (not (null provided))
(provided (pop provided)))
;; If package already loaded just do the cleanup, this also catches the case where
;; the package loaded didn't do a provide - underlying require already gave
error.
(provided (ad-get-arg 0))))