;;; crontab-mode.el --- Mode for editing crontab files ;; ;; ~/share/emacs/pkg/crontab/crontab-mode.el --- ;; ;; $Id: crontab-mode.el,v 1.20 2005/10/04 03:58:52 harley Exp $ ;; ;; Author: Harley Gorrell ;; URL: http://www.mahalito.net/~harley/elisp/crontab-mode.el ;; License: GPL v2 ;; Keywords: cron, crontab, emacs ;;; Commentary: ;; * I want to keep my crontabs under rcs to keep a history of ;; the file. Editing them with 'crontab -e' is rather ;; cumbersome. My method is to keep the crontab as a file, ;; under rcs, and check in the changes with 'C-c C-c' after ;; editing. ;; ;; * The remote systems are expected to share a filesystem. ;; If they dont, modify crontab-shell or crontab-apply to ;; suit your needs. ;; ;; * You may want to add one of these to your startup: ;; (add-to-list 'auto-mode-alist '("\\.cron\\(tab\\)?\\'" . crontab-mode)) ;; (add-to-list 'auto-mode-alist '("cron\\(tab\\)?\\." . crontab-mode)) ;;; History: ;; 2003-03-16: Updated URL and contact info ;; 2004-02-26: Use ssh to apply crontabs to remote hosts. ;;; Code: (defvar crontab-suffix ".crontab" "*Suffix for crontab buffers.") (defvar crontab-apply-after-save nil "*Non-nil to apply the crontab after a save.") (make-variable-buffer-local 'crontab-apply-after-save) (defvar crontab-host nil "*Hostname to use when saving the crontab to a remote host.") (make-variable-buffer-local 'crontab-host) (defvar crontab-user nil "*Username to use when saving the crontab to a remote host.") (make-variable-buffer-local 'crontab-user) ;; Would be better to have "\\([0-9]\\([-,][0-9]+\\)+\\|... (defvar crontab-unit-regexp "\\(\\(?:[-,0-9]+\\|\\*\\)\\(?:/[0-9]+\\)?\\)" "A regexp which matches a cron time unit.") (defvar crontab-sep-regexp "[ \t]+" "A regexp to match whitespace seperating cron time units.") (defvar crontab-ruler " # min hour day month day-of-week command #(0-59) (0-23) (1-31) (1-12) (0-6) #------------------------------------------------------------ " "*The ruler `crontab-insert-ruler' inserts.") ;; (defvar crontab-mode-hook nil "*Hook for customising `crontab-mode'.") (defvar crontab-load-hook nil "*Hook run when the `crontab-mode' is loaded.") ;; (defvar crontab-font-lock-keywords (list ;; Comments '("^#.*$" . font-lock-comment-face) ;; Blank lines are bad! '("^[ \t]+$" . highlight) ;; Variable defs '("^\\([A-Z_]+\\)=\\(.*\\)$" . ((1 font-lock-keyword-face) (2 font-lock-string-face)) ) ;; Cron lines ;; 50 * * * * /usr/gnu/bin/bash (cons (concat "^" crontab-unit-regexp crontab-sep-regexp crontab-unit-regexp crontab-sep-regexp crontab-unit-regexp crontab-sep-regexp crontab-unit-regexp crontab-sep-regexp crontab-unit-regexp crontab-sep-regexp "\\(.*\\)$") '((1 font-lock-keyword-face) (2 font-lock-keyword-face) (3 font-lock-keyword-face) (4 font-lock-keyword-face) (5 font-lock-keyword-face) (6 font-lock-string-face))) ) "Info for function `font-lock-mode'.") (defvar crontab-mode-map nil "Keymap used in `crontab-mode'.") (if crontab-mode-map () (setq crontab-mode-map (make-sparse-keymap)) (define-key crontab-mode-map "\C-c\C-c" 'crontab-save-and-apply) (define-key crontab-mode-map "\C-cc" 'crontab-save-and-apply) (define-key crontab-mode-map "\C-ca" 'crontab-save-and-apply-to) (define-key crontab-mode-map "\C-ci" 'crontab-insert-local-var) (define-key crontab-mode-map "\C-cr" 'crontab-insert-ruler)) ;; This will barf without the correct agent or key setup. (defvar crontab-rsh-cmd "ssh" ;; "rsh" "Program to use for remote shells.") (defun crontab-rsh-cmd () "Generate the rsh command. Redefine as needed." (if crontab-user (concat crontab-rsh-cmd " -l " (format "%s" crontab-user)) ;; str-ify crontab-rsh-cmd) ) (defun crontab-localhost-p (&optional host) "True if this is the same HOST Emacs is on." (or (null host) (string= host "") (string= host "localhost") (string= host (system-name))) ) (defun crontab-shell (host cmd out-buffer) "On a possibly remote HOST, run CMD Output to OUT-BUFFER." (when (not (crontab-localhost-p host)) (setq cmd (concat (crontab-rsh-cmd) " " host " " cmd))) (shell-command cmd out-buffer) ) ;;;###autoload (defun crontab-mode () "Major mode for editing crontabs. Defines commands for getting and applying crontabs for hosts. Sets up command `font-lock-mode'. \\{crontab-mode-map}" (interactive) ;; (kill-all-local-variables) (setq mode-name "crontab") (setq major-mode 'crontab-mode) (use-local-map crontab-mode-map) ;; (setq comment-start "#") (setq comment-start-skip "#+ *") ;; (make-local-variable 'font-lock-defaults) (setq font-lock-defaults '(crontab-font-lock-keywords)) ;; Add to the end of the buffers save hooks. (add-hook 'after-save-hook 'crontab-after-save t t) ;; (run-hooks 'crontab-mode-hook) ) ;;;###autoload (defun crontab-get (host) "Get the crontab for the HOST into a buffer." (interactive "sCrontab for host:") (let ((cbn (generate-new-buffer-name (concat host crontab-suffix)))) (switch-to-buffer-other-window cbn) (erase-buffer) (crontab-mode) (crontab-insert host) (not-modified) (setq crontab-host host)) ) (defun crontab-insert (&optional host) "Insert the crontab for the HOST into the current buffer." (crontab-shell host "crontab -l" t) ) (defun crontab-apply (&optional host) "Apply the crontab to a HOST. The filesystem must be common." (if (buffer-file-name) (crontab-shell host (concat "crontab " (buffer-file-name)) nil) (error "No filename for this buffer"))) (defun crontab-save-and-apply () "Save and apply the buffer to the HOST." (interactive) (save-buffer) (if (not crontab-apply-after-save) ;; Dont apply it twice. (crontab-apply (crontab-host))) ) (defun crontab-save-and-apply-to (host) "Prompt for the HOST and apply the file." (interactive "sApply to host:") (setq crontab-host host) ;; remember the change (crontab-save-and-apply) ) (defun crontab-insert-ruler () "Insert a ruler with comments into the crontab." (interactive) (end-of-line) (insert crontab-ruler) ) (defun crontab-insert-local-var () "Insert the current values of buffer local variables." (interactive) (goto-char (point-max)) (insert " " comment-start " Local " "Variables: " comment-start " mode: " (format "%s" (or mode-name "crontab")) " " comment-start " crontab-host: " (crontab-host) " " comment-start " crontab-apply-after-save: " (format "%s" crontab-apply-after-save) " " comment-start " End: ") ) (defun crontab-host () "Return the hostname as a string, defaulting to the local host. The variable `crontab-host' could be a symbol or a string." (format "%s" (or crontab-host system-name)) ) ;; (defun crontab-after-save () "If `crontab-apply-after-save' is set, apply the crontab after a save." (if crontab-apply-after-save (crontab-apply (crontab-host))) ) (provide 'crontab-mode) (run-hooks 'crontab-load-hook) ;;; crontab-mode.el ends here