---
(require 'early-bindings)
(require 'd-time)
(require 'd-make-faces)
(require 'd-groups)
(require 'd-find)
(defvar d-recent--pad-width 10)
(defvar d-recent--keymap (make-keymap))
(defvar d-recent--buf-name "*recent*")
(when prefs-davins-keybindings-online-p
(global-set-key [kp-enter] 'd-recent-switch-to-buffer)
)
(defvar d-recent--persistent-file-name (car (last (directory-files "~/.emacs.d" t "^recent.*$"))))
(defun d-recent--get-nf-string (cons-cell)
(assert (consp cons-cell))
(assert (numberp (car cons-cell)))
(assert (stringp (cdr cons-cell)))
(let ((number (format (concat "%" (format "%d" 10) "d") (car cons-cell)))
(file (cdr cons-cell)))
(concat number " " file)))
(defun d-recent--insert-lines ()
(progn
(if (get-buffer d-recent--buf-name)
(kill-buffer d-recent--buf-name))
(generate-new-buffer d-recent--buf-name)
(set-buffer d-recent--buf-name)
(read-only-mode -1)
(erase-buffer)
(goto-char (point-min))
(let ((ptr d-recent--list))
(while ptr
(if (file-exists-p (cdar ptr))
(insert (d-recent--get-nf-string (car ptr)) "\n"))
(setq ptr (cdr ptr)))
))
)
(defun d-recent--fontify-lines ()
(assert (string= d-recent--buf-name (buffer-name)))
(let ((array (make-vector 999 0)))
(let ((i 0) (len (length array)))
(while (< i len)
(aset array i (d-read-str (eval (format "recent-line%04d" i))))
(setq elt (aref array i))
(make-face elt)
(incf i)
)
(goto-char (point-min))
(setq i 0)
(while (and (< (point) (point-max)) (< i len))
(let* ((s (d-current-line-as-string))
(min (point-at-bol))
(max (point-at-eol))
(pair (d-groups-get-face (substring s (1+ d-recent--pad-width)))))
(setq elt (aref array i))
(set-face-background elt (nth 0 pair))
(set-face-foreground elt (nth 1 pair))
(put-text-property min (1+ max) 'face elt)
(forward-line 1)
(incf i)
)
)
)
)
)
(defun d-recent--pred (x y)
(> (car x) (car y)))
(defun d-recent--generate-buffer ()
(interactive)
(setq d-recent--list (sort d-recent--list 'd-recent--pred))
(save-excursion
(d-recent--insert-lines)
(use-local-map d-recent--keymap)
(when prefs-davins-keybindings-online-p
(local-set-key "\C-m" 'd-recent--find-file))
(d-recent--fontify-lines)
)
(progn
(set-buffer d-recent--buf-name)
(goto-char (point-min)))
)
(defun d-recent-switch-to-buffer ()
(interactive)
(if (get-buffer d-recent--buf-name)
(kill-buffer d-recent--buf-name))
(d-recent--generate-buffer)
(switch-to-buffer d-recent--buf-name)
)
(defun d-recent--find-file ()
(interactive)
(let ((s (substring (d-current-line-as-string) (1+ d-recent--pad-width))))
(assert (file-exists-p s))
(d-find-file s)
)
)
(defun d-recent-find-file-hook (filename)
(setq filename (safe-compress-file-name filename))
(if (file-directory-p filename)
(setq filename (concat filename "/")))
(if (string= d-recent--persistent-file-name filename)
nil
(if t (let ((found (rassoc filename d-recent--list)))
(if found
(setcar found (1+ (car found)))
(setq d-recent--list (cons (cons 1 filename) d-recent--list))))
)
)
)
(defun d-recent--load-log-file ()
(save-excursion
(setq d-recent--list nil)
(find-file d-recent--persistent-file-name)
(goto-char (point-min))
(while (< (point) (point-max))
(let* ((line (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
(numb (d-read-str (substring line 0 d-recent--pad-width)))
(file (d-trim-string (substring line (1+ d-recent--pad-width)))))
(if (file-exists-p file)
(setq d-recent--list (cons (cons numb file) d-recent--list))))
(forward-line 1))
(kill-buffer nil)
)
)
(add-hook 'kill-emacs-hook 'd-recent--save-log-file)
(defun d-recent--save-log-file ()
(interactive)
(progn
(find-file d-recent--persistent-file-name)
(read-only-mode -1)
(erase-buffer)
(let ((ptr d-recent--list)
line)
(while ptr
(when (file-exists-p (cdar ptr))
(setq line (d-recent--get-nf-string (car ptr)))
(insert line "\n"))
(setq ptr (cdr ptr))))
(save-buffer 'NO-QUESTIONS)
(kill-buffer)
(message "Saved log file %s" d-recent--persistent-file-name)
(sit-for 1)
)
)
(defadvice save-some-buffers (before d-recent activate)
(let* ((list (buffer-list))
(ptr list)
(found nil))
(setq d-recent--list (sort d-recent--list 'd-recent--pred))
(while (and ptr (not found))
(when (and (buffer-modified-p (car ptr)) (buffer-file-name (car ptr)))
(setq found t))
(setq ptr (cdr ptr)))
))
(setq d-recent--list nil)
(provide 'd-recent)