;;;;
;;;;;; Buffers
;;;;

;; create unique buffer names
(require 'uniquify)
(setq uniquify-buffer-name-style 'post-forward)

;; quick keyboard access to bury a buffer
(global-set-key (kbd "C-x B") 'bury-buffer)

(require 'bs)

;; prefer buffer selection mode to normal buffer list
(global-set-key (kbd "C-x C-b") 'bs-show)

;; the size string is more useful if it's readable
(defun tmk-bs--get-size-string (&rest ignored)
  (let* ((size (buffer-size))
     (str  (number-to-string size)))
    (when (> (length str) 6)
      (setq size (/ size 1024.0)
        str (format "%.1fK" size)))
    (when (> (length str) 6)
      (setq size (/ size 1024.0)
        str (format "%.1fM" size)))
    (when (> (length str) 6)
      (setq size (/ size 1024.0)
        str (format "%.1fG" size)))
    str))

;; the mode name isn't useful for temp buffers normally
(defun eaw-bs--get-mode-name (&rest ignored)
  (let* ((fmn (if (fboundp 'format-mode-line) (format-mode-line mode-name) mode-name))
         (mn (substring fmn 0 (min (length fmn) 12))))
    (cond ((member major-mode '(shell-mode dired-mode)) mn)
          (t mn))))

;; this isn't done yet; I want to reformat the file name
(defun eaw-bs--get-file-name (&rest ignored)
  (let ((abr-dir (abbreviate-file-name default-directory)))
    (cond ((member major-mode '(dired-mode)) abr-dir)
        ((buffer-file-name) (abbreviate-file-name buffer-file-name))
        ((string= abr-dir "~/") (buffer-name))
        (t (concat (buffer-name) " (" abr-dir ")")))))

;; set up my own custom sort function
(defun eaw-bs--sort-by-name (b1 b2)
  "Compare buffers B1 and B2 by filename if files, else by name"
  (let ((n1 (with-current-buffer b1 (eaw-bs--get-file-name)))
        (n2 (with-current-buffer b2 (eaw-bs--get-file-name))))
    (string< n1 n2)))
(bs-define-sort-function "by filename/name" 'eaw-bs--sort-by-name "File")
(setq bs-default-sort-name "by filename/name")
(setq bs--current-sort-function (assoc bs-default-sort-name bs-sort-functions))

(defun eaw-bs-go-home ()
  "Change default-directory to ~/ for buffer on current line."
  (interactive)
  (with-current-buffer (bs--current-buffer)
    (cd "~/"))
  (bs--update-current-line))

(defun eaw-bs-revert-buffer ()
  "Revert the buffer on current line."
  (interactive)
  (with-current-buffer (bs--current-buffer)
    (revert-buffer))
  (bs--update-current-line))

(add-hook 'bs-mode-hook
          '(lambda ()
             (define-key bs-mode-map "*" 'bs-clear-modified)
             (define-key bs-mode-map "R" 'eaw-bs-revert-buffer)
             (define-key bs-mode-map "~" 'eaw-bs-go-home)
             (define-key bs-mode-map "`" 'eaw-bs-go-home)))

;; a better layout for the buffer table
(setq bs-attributes-list
      '((""       1   1 left  bs--get-marked-string)
        ("M"      1   1 left  bs--get-modified-string)
        ("R"      2   2 left  bs--get-readonly-string)
        ("Size"   6   6 right tmk-bs--get-size-string)
        (""       1   1 left  " ")
        ("Mode"  12  12 right eaw-bs--get-mode-name)
        (""       1   1 left  " ")
        ("File"   1  99 left  eaw-bs--get-file-name)))

;; don't hide *...* buffers by default
(setq bs--show-all t)

;; don't hide anything
(setq bs--intern-show-never "^$")

(provide 'ew-buffer)