; GPL'ed as under the GNU license..
; -- Deepak Goel (deego@glue.umd.edu)
;9/5/00
; This helps me do automated actions everytime a particular file gets updated..
; Most of the functions here are oriented towards a display-ed screen..

; O GENERAL USER: PLEASE CHANGE THE LOADED-PROFILE FILE TO
; generalprofile.el  below. You will need to download this
; generalprofile.el, edit it to your needs, and also download
; timerfunctions.el. Please have an emacs installed on your system,
; pref. emacs20.



;;;====================================================
 (defmacro bind (a &optional value)
   "Like setq but only If a not already bound.
Copied from .emacs.macros. Basically, is like defvar."
   (list 'if (list 'not (list 'boundp (list 'quote a)))
       (list 'setq a value))
   )

;USER OPTIONS BEGIN
;;;====================================================

(require 'cl)
(load-file "timerfunctions.el") 
; *file* ==> file without extension
; *ext* ==> extension of file, default: .tex.e
; there are also defaults for *view-command* and *command*

;PROFILES ARE SET HERE: 
(load "deegoprofile.el")


(setq *overrule-error* nil)

(bind *overrule-error* nil)
(bind *ext* ".tex.e")
(bind *view-command* (concat "gv -scale 2 " *file*  ".ps &"))
; FOR ME:
(bind  *command* (concat "elat " *file*))

(bind *directory* "~/more/tex")
(bind *file* "myarticle")


;;;====================================================
;;;====================================================

(setq *repeattime* 4)
(setq *initialtime* 4)
(setq *viewp* t)
(setq *includeruntime* nil)
;;;====================================================
;USER OPTIONS END
; overrule-error => show gv even if error-found..

;;;====================================================


(setq *begintime* (cadr (current-time)))

(defun last-modified-time-my (file)
  "Gets file's last modified-time."
  (sixth (file-attributes file)))

; this ensures initial processing..
(setq *last-modified-time* nil)
;(setq *last-modified-time* (ignore-errors (last-modified-time-my *file*)))

; (defun elatstart ()
;  "Automatically elatexes *file* whenever needed. The main function
; here.. Does so by running elatrun whenever it finds it idle.. Does not
; work for more than a day continuously.
; "
;   (interactive)
;   (cd *directory*)
;   (run-with-idle-timer *initialtime* "repeat" 'elatrestartrun)
; )

; ;;;====================================================
; (defun elatrestartrun ()
;   "Internal."
;  (setq *begintime* (cadr (current-time)))
;  (elatrun)
; )
; ;;;====================================================
; (defun elatrun ()
; "Whenever emacs is idle for *initialtime* sec., this function is
; called by elatstart. This function then runs elat on the file.  Then,
; sets a one-time-timer to run itself for time + repeat seconds in case
; emacs remains idle.... which
; will do the same and so on.., so that as long as emacs is idle,
; elatrun will run every repeat seconds. Does not work for more than a
; day continuosly because i am using \(cadr \(current-time\)\). 
; WHEN I SAY IT WILL REPEAT EVERY *repeattime* SECONDS, I MEAN THAT THE
; TIME TO RUN ELAT IS *NOT* COUNTED TOWARDS THAT. IN FACT, I GO TO GREAT
; LENGTHS TO ENSURE THAT---SEE KEEPTRACK BELOW..
; "
; (let ((keeptrack (cadr (current-time))))
;  (cd *directory*)
;  (elat)
;  (setq *begintime* (+ *begintime* (- (cadr (current-time)) keeptrack)))
;  (run-with-idle-timer (+ *repeattime* (- (cadr (current-time))
; 					 *begintime*)) 
		      
		      
; ; the one below is no good---doesn't even respect the users' options.
; ; (run-at-time nil *repeattime* 'elat)
; ; (run-at-time nil *repeattime* 'elatwhenidle)

; )


;;;###autoload
(defun elatstart ()
  (tf-run-with-idle-timer *initialtime*  t *repeattime* t
			  *includeruntime* 'elat)
)

;;;====================================================
(global-set-key "\C-cv" 'elatview)
(defun elatview ()
  "Ghostview command."
  (interactive)
  (shell-command (concat "cd " *directory*))
  (shell-command *view-command*))

(global-set-key "\C-ce" 'elat)

(defun elatwhenidle ()
  (run-with-idle-timer 5 nil 'elat))

(defun elat ()
"One instance of processing. Bound to C-cC-e.
This command elats the file if the file has been modified. It shows
the processing-results, searching for errors, if any. The last time's
precessing results are backuped into a buffer called Previous Shell
Command Output."
  (interactive)
  (cd *directory*)
  (let* 
      ((newtime (last-modified-time-my (concat *file* *ext*)))
       (modifiedp (not (equal *last-modified-time* newtime))))
    (setq *last-modified-time* newtime)
    (if modifiedp
	(progn
	  (get-buffer-create "*Shell Command Output*")
	  (get-buffer-create "*Previous Shell Command Output*")
	  (kill-region (point-min) (point-max))
	  (insert-buffer "*Shell Command Output*")
	  (switch-to-buffer "*Shell Command Output*")
	  (kill-region (point-min) (point-max))
	  (shell-command "echo Running elat now.")
	  (shell-command (concat "cd " *directory*))
	  (shell-command *command*)
	  (switch-to-buffer "*Shell Command Output*")
	  (goto-char (point-min))
	  (search-forward "about the first error" nil t)
	  (let (error-found)
	    (if 
		(or
		 (search-forward "Error" nil "go-to-end-otherwise")
		 (progn
		   (goto-char (point-min))
		   (search-forward "Undefined control sequence" nil "go-to-end-otherwise"))
		 (progn
		   (goto-char (point-min))
		   (search-forward "Emergency stop" nil "go-to-end-otherwise")))
					; (ignore-errors (bold-region
					;		(- (point) 7)
					;		(point))))
		(setq error-found t))
	    (if error-found
		(progn
		  (insert "[[[<---**ERROR**DETECTED**DURING**RUN**!!***]]]")
		  (ding t)
		  (ding t)
		  (ding t)
		  (ding t)
		  (ding t)
		  
		  ))			; else gv..
	    (if *viewp* 
		(if (or *overrule-error*  (not error-found))
		    (progn
		      (ignore-errors (delete-process 
				      "*Async Shell Command*"))
		      
		      (elatview
		       )))))
	    
	  (switch-to-buffer "*Shell Command Output*")
	  (insert (current-time-my))
	  (line-to-top-of-window)
					;	  (shell-command "echo Done")
	  )))
  )



;;;====================================================
;;;====================================================
; The following might be useful in a batch mode..

; (defun do-upon-revert (file sittime action &optional skip-initial)
;   "NOT CURRENTLY IN USE.
; If a file exists and has been modified, perform action.
; The action is performed by default the first time this function is
; launched, unless skip-initial is non-nil. Any action is
; performed only if the file exists. Is basically a generalization of
; auto-revert-buffer, and helps me auto-process my latex documents. This
; process is more suited for background batch type jobs, and will not be
; used here any more. The problem with background jobs, however, is that
; the sit-for won't work, so I had better comment it out.. But that
; would mean continuous CPU wastage.."
;   (let ((aatime (last-modified-time-my file)) bbtime modifiedp)
;     (if (and aatime (not skip-initial)) (eval action))
;     (while (> 1 0)
;       (sit-for sittime)
;       (setq bbtime (last-modified-time-my file))
;       (setq modifiedp (equal aatime bbtime))
;       (setq aatime bbtime)
;       (if (and modifiedp aatime)
; 	  (eval action)))))



; LocalWords:  timerfunctions