;;;;
;;;;;; Shells (eshell/shell/term)
;;;;

(defun eaw-check-exit-status ()
  (unless (= eshell-last-command-status 0)
    (eshell-interactive-print
     (format "[Exit %d]\n" eshell-last-command-status))))

(defun eaw-eshell-hook ()
  (define-key eshell-mode-map [C-up] 'windmove-up)
  (define-key eshell-mode-map [C-down] 'windmove-down)
  (define-key eshell-mode-map (kbd "<up>") 'previous-line)
  (define-key eshell-mode-map (kbd "<down>") 'next-line)
  (add-hook 'eshell-before-prompt-hook 'eaw-check-exit-status))

(add-hook 'eshell-mode-hook 'eaw-eshell-hook)

(setq eshell-modify-global-environment t)

(setq eshell-banner-message "")

;; eshell files go in ~/.emacs.d/var/eshell
(setq eshell-directory-name (locate-user-emacs-file "var/eshell/"))

(defadvice eshell-write-aliases-list (after eaw-sort-eshell-aliases)
  (if (file-writable-p (file-name-directory eshell-aliases-file))
      (with-temp-buffer
        (insert-file-contents-literally eshell-aliases-file)
        (sort-lines nil (point-min) (point-max))
        (write-region (point-min) (point-max) eshell-aliases-file))))
(ad-activate 'eshell-write-aliases-list)

(defvar eaw-ansi-escape-re
  (rx (or ?\233 (and ?\e ?\[))
      (zero-or-more (char (?0 . ?\?)))
      (zero-or-more (char ?\s ?- ?\/))
      (char (?@ . ?~))))

(defun eaw-nuke-ansi-escapes (beg end)
  (save-excursion
    (goto-char beg)
    (while (re-search-forward eaw-ansi-escape-re end t)
      (replace-match ""))))

(defun eaw-eshell-nuke-ansi-escapes ()
  (eaw-nuke-ansi-escapes eshell-last-output-start eshell-last-output-end))

(add-hook 'eshell-output-filter-functions 'eaw-eshell-nuke-ansi-escapes t)

(let ((default-directory (expand-file-name "~/")))
  (eshell))

(add-hook 'comint-mode-hook
          '(lambda ()
             (define-key comint-mode-map [C-up] 'windmove-up)
             (define-key comint-mode-map [C-down] 'windmove-down)))

(setq comint-prompt-read-only t)

;; allow ls --color=auto output to be processed correctly
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)

(add-hook 'term-mode-hook
          '(lambda ()
             (define-key term-raw-escape-map "\M-v" 'scroll-down)))

;; terminal buffers should have infinite scrollback
(setq term-buffer-maximum-size 0)

(defadvice telnet-filter (around eaw-telnet-filter)
  (if (= (point) (point-max))
      ad-do-it
    (save-excursion ad-do-it)))
(ad-activate 'telnet-filter)
(add-hook 'telnet-mode-hook
          '(lambda () (setq comint-scroll-to-bottom-on-input 'this)))

(provide 'ew-shell)