;;----------------------------------------------------------------------------
;; Manuel López-Ibáñez .emacs file
;; <http://lopez-ibanez.eu/>
;;
;; I don't claim that anything in this file is correct, efficient or
;; good style.  Send comments and suggestions to
;; <manuel.lopez-ibanez@manchester.ac.uk>
;;
;; $Revision: 1361 $
;;
;; Download the text version from:
;;  <http://lopez-ibanez.eu/files/dotemacs.txt>
;;
;; The latest version can be found at:
;;  <http://lopez-ibanez.eu/dotemacs.html>
;;----------------------------------------------------------------------------
;; TODO
;;
;; * How to prevent emacs inserting an asterisk at the start of the
;;   line in C comments with key Alt-Q (c-fill-paragraph)?
;;
;; * Nicer default fonts. It would be ideal if the modeline used the system font. Emacs have problems with antialiasing.
;;
;;
;; * In ido, find-file a keyboard shortcut that prompts from a directory (editable) and a file, and searches the file using find. M-f: ido-wide-find-file does not work

;; * next-error matches lines that are not errors/warnings, how to avoid this?

;; * Ido should have a "show help" command like "?" mentioning the most common short-cuts (like ediff-mode has)

;; * https://github.com/magnars/multiple-cursors.el
;;
;; * Equivalent of recompile in AUCTEX?
;;
;; * How to fix window-switching?
;;   1) a function that cycles between windows in clockwise order

;; * How to show whether the current buffer is a symlink in the modeline?

;; (setq-default mode-line-buffer-identification
;;               (list 'buffer-file-name
;;                     (propertized-buffer-identification "%12f")
;;                     (propertized-buffer-identification "%12b")))

      ;;; symlink-phobia-mode.el --- Indicate files visited via symbolic links
      
      ;; (defvar symlink-phobia-mode-indicator
      ;;   (concat " " (propertize "SymLink" 'face 'font-lock-warning-face)))
      
      ;; (define-minor-mode symlink-phobia-mode
      ;;   "Minor mode to indicate when the visited file name is a symbolic link.
      
      ;; It also indicates when the file name's directory includes any symbolic links."
      
      ;;   nil (:eval symlink-phobia-mode-indicator) nil
      ;;   (require 'font-lock))
      
      ;; (defun turn-on-symlink-phobia-mode ()
      ;;   "Turn on `symlink-phobia-mode'."
      ;;   (when (or (file-symlink-p buffer-file-name)
      ;;             (not (equal buffer-file-name buffer-file-truename)))
      ;;     (symlink-phobia-mode 1)))
      
      ;; (add-hook 'find-file-hooks 'turn-on-symlink-phobia-mode)
      ;; (add-hook 'find-file-not-found-hooks 'turn-on-symlink-phobia-mode)
      
      ;; (provide 'symlink-phobia-mode)
      
      ;;; symlink-phobia-mode.el ends here
      
;; * How to show the file pointed by the symlink?

  ;; ;;finding file keeps buffer name as symlink name.  all the truename vars do
  ;; ;;not fix.  this does.  this should use before advice changing filename?

  ;; (defun alpha-find-file-truename (filename &optional codesys)
  ;;   "used for ffap."
  ;;   (interactive "FFile name (will be truenamed): ")
  ;;   (find-file (file-truename filename) codesys))

  ;; (setf ffap-file-finder 'alpha-find-file-truename)

  ;; ;;here are variables.  they are insufficient for getting the ;;truename.  in emacs 22, you only get truename if you
  ;; ;;already had the original file in a buffer.  it is as if these
  ;; ;;variables are simply ignored.  there are no other variables.

  ;; (setf find-file-compare-truenames t)    ;xemacs

  ;; (setf find-file-existing-other-name t)  ;emacs and xemacs alias for ffct

  ;; ;;find-file-use-truenames seems to default to t in xemacs but not in emacs.
  ;; ;;why can't they compare inode for hard links and what happens if these are nil?
  ;; (setf find-file-visit-truename t)

;; * https://github.com/magnars/multiple-cursors.el
;; * How to make flyspell ignore urls and HTML tags?
;; * How to make fill-paragraph do the right thing in HTML (do not fill <pre> contents)?
;; * How to make fill-paragraph recognize item lists like this one?
;; * How to check that a package is installed without loading it (avoid try-require)? eval-after-load does not really work (e.g., for flyspell) and it doesn't register which packages are missing.
;; * How to auto-load AUCTeX? 
;; * Make a2ps print to FILE always (or show preview in GV)
;; * Print to PDF file instead of PS?
;; * Remove obsolete stuff
;; * Move more stuff to CUSTOM
;; * How to define smerge key prefix as C-c +, that is, press control and c, release, press +
;; * How to make TAB do smerge-refine when position is within merge conflict?

;; Set the debug option when there is trouble...
;;(setq debug-on-error t)
(defvar *emacs-load-start* (current-time))
;; Too slow, disabled by default
;;(message "* Loading .emacs (%s)" (format-time-string "%Y-%m-%d %H:%M"))

;; Really needed?
(require 'cl) ;; turn on Common Lisp support

;;-----------------------------------------------------------------
;; Byte-compile .emacs when saving it.
;;-----------------------------------------------------------------
(defun byte-compile-user-init-file ()
  ;; FIXME: Enabled more warnings!
  (let ((byte-compile-warnings '(unresolved)))
    ;; in case compilation fails, don't leave the old .elc around:
    (when (file-exists-p (concat user-init-file ".elc"))
      (delete-file (concat user-init-file ".elc")))
    (byte-compile-file user-init-file)
    (message "%s compiled" user-init-file)
    ))
(defun my-emacs-lisp-mode-hook ()
  (when (equal buffer-file-name user-init-file)
    (add-hook 'after-save-hook 'byte-compile-user-init-file t t)))

;; (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
(add-hook 'emacs-lisp-mode-hook 'my-emacs-lisp-mode-hook)
;;-----------------------------------------------------------------

;;-----------------------------------------------------------------
;; try-require: attempt to load a feature/library, failing silently
;;-----------------------------------------------------------------
(defvar missing-packages-list nil
  "List of packages that `try-require' can't find.")

(defun try-require (feature)
  "Attempt to load a library or module. Return true if the
library given as argument is successfully loaded. If not, instead
of an error, just add the package to a list of missing packages."
  (condition-case err
      ;; protected form
      (progn
        (message "Checking for library `%s'..." feature)
        (if (stringp feature)
            (load-library feature)
          (require feature))
        (message "Checking for library `%s'... Found" feature))
    ;; error handler
    (file-error  ; condition
     (progn
       (message "Checking for library `%s'... Missing" feature)
       (add-to-list 'missing-packages-list feature))
     nil)))
;;-----------------------------------------------------------------

;;-----------------------------------------------------------------
;; CUSTOM first to override it later.
;;-----------------------------------------------------------------
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(LaTeX-command "latex -shell-escape")
 '(LaTeX-command-style (quote (("" "%(PDF)%(latex) -file-line-error %S%(PDFout) "))))
 '(LaTeX-indent-environment-list (quote (("verbatim" current-indentation) ("verbatim*" current-indentation) ("array") ("displaymath") ("eqnarray") ("eqnarray*") ("equation") ("equation*") ("picture") ("tabbing") ("table") ("table*") ("spreadtab" ignore) ("tabular" ignore) ("tabular*"))))
 '(TeX-PDF-mode t)
 '(TeX-auto-local ".auctex-auto")
 '(TeX-command-list (quote (("TeX" "%(PDF)%(tex) %`%S%(PDFout)%(mode)%' %t" TeX-run-TeX nil (plain-tex-mode texinfo-mode ams-tex-mode) :help "Run plain TeX") ("LaTeX" "%`%l%(mode)%' %t" TeX-run-TeX nil (latex-mode doctex-mode) :help "Run LaTeX") ("Makeinfo" "makeinfo %t" TeX-run-compile nil (texinfo-mode) :help "Run Makeinfo with Info output") ("Makeinfo HTML" "makeinfo --html %t" TeX-run-compile nil (texinfo-mode) :help "Run Makeinfo with HTML output") ("AmSTeX" "%(PDF)amstex %`%S%(PDFout)%(mode)%' %t" TeX-run-TeX nil (ams-tex-mode) :help "Run AMSTeX") ("ConTeXt" "texexec --once --texutil %(execopts)%t" TeX-run-TeX nil (context-mode) :help "Run ConTeXt once") ("ConTeXt Full" "texexec %(execopts)%t" TeX-run-TeX nil (context-mode) :help "Run ConTeXt until completion") ("BibTeX" "bibtex %s" TeX-run-BibTeX nil t :help "Run BibTeX") ("View" "%V" TeX-run-discard-or-function t t :help "Run Viewer") ("Print" "%p" TeX-run-command t t :help "Print the file") ("Queue" "%q" TeX-run-background nil t :help "View the printer queue" :visible TeX-queue-command) ("File" "%(o?)dvips %d -o %f " TeX-run-command t t :help "Generate PostScript file") ("Index" "makeindex %s" TeX-run-command nil t :help "Create index file") ("Check" "lacheck %s" TeX-run-compile nil (latex-mode) :help "Check LaTeX file for correctness") ("Spell" "(TeX-ispell-document \"\")" TeX-run-function nil t :help "Spell-check the document") ("Clean" "TeX-clean" TeX-run-function nil t :help "Delete generated intermediate files") ("Clean All" "(TeX-clean t)" TeX-run-function nil t :help "Delete generated intermediate and output files") ("Other" "" TeX-run-command t t :help "Run an arbitrary command"))))
 '(TeX-output-view-style (quote (("^dvi$" ("^landscape$" "^pstricks$\\|^pst-\\|^psfrag$") "%(o?)dvips -t landscape %d -o && gv %f") ("^dvi$" "^pstricks$\\|^pst-\\|^psfrag$" "%(o?)dvips %d -o && gv %f") ("^dvi$" ("^a4\\(?:dutch\\|paper\\|wide\\)\\|sem-a4$" "^landscape$") "%(o?)xdvi %dS -paper a4r -s 0 %d") ("^dvi$" "^a4\\(?:dutch\\|paper\\|wide\\)\\|sem-a4$" "%(o?)xdvi %dS -paper a4 %d") ("^dvi$" ("^a5\\(?:comb\\|paper\\)$" "^landscape$") "%(o?)xdvi %dS -paper a5r -s 0 %d") ("^dvi$" "^a5\\(?:comb\\|paper\\)$" "%(o?)xdvi %dS -paper a5 %d") ("^dvi$" "^b5paper$" "%(o?)xdvi %dS -paper b5 %d") ("^dvi$" "^letterpaper$" "%(o?)xdvi %dS -paper us %d") ("^dvi$" "^legalpaper$" "%(o?)xdvi %dS -paper legal %d") ("^dvi$" "^executivepaper$" "%(o?)xdvi %dS -paper 7.25x10.5in %d") ("^dvi$" "." "%(o?)xdvi %dS %d") ("^pdf$" "." "okular %o") ("^html?$" "." "netscape %o"))))
 '(TeX-view-program-list (quote (("okular" "okular %o"))))
 '(TeX-view-program-selection (quote (((output-dvi style-pstricks) "dvips and gv") (output-dvi "xdvi") (output-pdf "okular") (output-html "xdg-open"))))
 '(blink-cursor-mode nil)
 '(browse-url-browser-function (quote browse-url-default-browser))
 '(c-default-style (quote ((c-mode . "K&R") (java-mode . "java") (other . "gnu"))))
 '(case-fold-search t)
 '(case-replace t)
 '(column-number-mode t)
 '(compilation-scroll-output (quote first-error))
 '(diff-default-read-only t)
 '(ediff-window-setup-function (quote ediff-setup-windows-plain))
 '(ess-default-style (quote DEFAULT))
 '(ess-execute-in-process-buffer t)
 '(ess-language "R" t)
 '(ffap-url-fetcher (quote browse-url-emacs))
 '(fill-column 79)
 '(font-latex-fontify-script nil)
 '(font-latex-fontify-sectioning (quote color))
 '(font-latex-title-fontify (quote color) t)
 '(font-lock-maximum-decoration t)
 '(frame-title-format "Emacs: %b %+%+ %f" t)
 '(gc-cons-threshold 1600000)
 '(grep-files-aliases (quote (("all" . "* .*") ("el" . "*.el") ("ch" . "*.cc *.[ch]xx *.[ch]pp *.[cCHh] *.CC *.HH *.[ch]++") ("c" . "*.[ch]") ("cc" . "*.cc *.cxx *.cpp *.C *.CC *.c++") ("cchh" . "*.cc *.[ch]xx *.[ch]pp *.[CHh] *.CC *.HH *.[ch]++") ("hh" . "*.hxx *.hpp *.[Hh] *.HH *.h++") ("h" . "*.h") ("l" . "[Cc]hange[Ll]og*") ("m" . "[Mm]akefile*") ("tex" . "*.tex") ("texi" . "*.texi") ("asm" . "*.[sS]"))))
 '(highlight-nonselected-windows t)
 '(icon-title-format "Emacs - %b" t)
 '(inhibit-startup-screen t)
 '(initial-frame-alist (quote ((top . 1) (height . 90))))
 '(isearch-regexp-lax-whitespace t t)
 '(ispell-program-name "aspell")
 '(line-number-display-limit-width 1000)
 '(line-number-mode 1)
 '(markdown-enable-math t)
 '(mouse-wheel-mode t nil (mwheel))
 '(reftex-extra-bindings t)
 '(ring-bell-function (quote ignore) t)
 '(safe-local-variable-values (quote ((TeX-master . ACO-MetaHandbook) (LocalWords . Vanzyl) (LocalWords . Tchebycheff) (LocalWords . "Tchebycheff") (ispell-dictionary . "english") (c-file-offsets (c . 0)) (c++-member-init-indent . 8) (TeX-master quote paper) (ispell-dictionary . "british") (auto-fill-mode) (TeX-master . race-test) (ess-indent-level . 2) (ess-continued-statement-offset . 2) (ess-brace-offset . 0) (ess-expression-offset . 4) (ess-else-offset . 0) (ess-brace-imaginary-offset . 0) (ess-continued-brace-offset . 0) (ess-arg-function-offset . 2) (ess-close-brace-offset . 0) (ispell-current-dictionary . british) (LocalWords . parallelized) (TeX-master . automoaco\.tex) (TeX-master . beamaco-csa) (ess-style . DEFAULT) (ess-fancy-comments) (ispell-local-dictionary . british) (Local . british) (bibtex-sort-ignore-string-entries))))
 '(scroll-bar-mode (quote right))
 '(scroll-step 1)
 '(search-whitespace-regexp "[  
]+")
 '(show-paren-mode t)
 '(smerge-command-prefix "")
 '(speedbar-frame-parameters (quote ((minibuffer) (width . 20) (border-width . 0) (menu-bar-lines . 0) (tool-bar-lines . 0) (unsplittable . t) (set-background-color "black"))))
 '(suggest-key-bindings 10)
 '(switch-to-buffer-preserve-window-point t)
 '(tool-bar-mode nil)
 '(track-eol t)
 '(transient-mark-mode t)
 '(undo-limit 200000)
 '(undo-strong-limit 300000)
 '(vc-follow-symlinks nil)
 '(vc-make-backup-files t)
 '(wc-modeline-format "[%tw words|%tc chars]")
 '(which-func-non-auto-modes (quote (bibtex-mode)))
 '(whitespace-modes (quote (ada-mode asm-mode autoconf-mode awk-mode c-mode c++-mode cc-mode change-log-mode cperl-mode electric-nroff-mode emacs-lisp-mode f90-mode fortran-mode html-mode html3-mode java-mode jde-mode ksh-mode latex-mode LaTeX-mode lisp-mode m4-mode makefile-mode modula-2-mode nroff-mode objc-mode pascal-mode perl-mode prolog-mode python-mode scheme-mode sgml-mode sh-mode shell-script-mode simula-mode tcl-mode tex-mode texinfo-mode vrml-mode xml-mode bibtex-mode))))

;;-------------------------------------------
;;  DISPLAY
;;-------------------------------------------
;; Macro to detect if we are under X.
(if (not (fboundp 'Xlaunch))
    (defmacro Xlaunch (&rest x)
      (list 'if (eq window-system 'x)(cons 'progn x)))
  (message ".emacs: Xlaunch already defined!"))

(Xlaunch
;         use xlsfonts -fn and xfd -fn
 (setq default-frame-alist
       '(
         (icon-type . t)
         (cursor-color . "Orchid")
         (mouse-color . "Orchid")
         ))
 (set-face-attribute 'default nil
                     :family "Terminus"
                     :height 120
                     :weight 'normal
                     :width 'normal
                     :foreground "Wheat"
                     :background "DarkSlateGray")

 ; This only works in Emacs > 24.3
 (setq mode-line-end-spaces (make-string 1024 ?─))

 (setq-default mode-line-position
               `((-3 ,(propertize
                       "%p"
                       'mouse-face 'mode-line-highlight
                       ;; XXX needs better description
                       'help-echo "Relative position"))
                 (size-indication-mode
                  (8 ,(propertize
                       " of %I"
                       'mouse-face 'mode-line-highlight
                       ;; XXX needs better description
                       'help-echo "Relative position")))
                 (line-number-mode
         ((column-number-mode
           (10 ,(propertize
                 " %l:%c"
                 'mouse-face 'mode-line-highlight
                 'help-echo "Line number and Column number"))
           (6 ,(propertize
                " L%l"
                ''mouse-face 'mode-line-highlight
                'help-echo "Line Number"))))
         ((column-number-mode
           (5 ,(propertize
                " C%c"
                'mouse-face 'mode-line-highlight
                'help-echo "Column number")))))))

(make-face 'mode-line-read-only-face)
(set-face-attribute 'mode-line-read-only-face nil
    :inherit 'mode-line-face
    :foreground "#4271ae"
    ;:box '(:line-width -1 :color "#4271ae")
    )
(make-face 'mode-line-modified-face)
(set-face-attribute 'mode-line-modified-face nil
    :inherit 'mode-line-face
    :foreground "#c82829"
    ;:box '(:line-width -1 :color "#c82829")
)

(setq-default mode-line-modified
 (list ;; read-only or modified status
  `(:eval (if (buffer-modified-p) 
              (propertize "MM" 'face 'mode-line-modified-face
                          ;; TODO: Handle saving when clicking
                          'help-echo "Buffer is modified")
            (propertize 
             (if buffer-read-only "RO" "  ") 
             'face 'mode-line-read-only-face
             'help-echo (purecopy (lambda (window object point)
                                    (format "Buffer is %s\nmouse-1 toggles"
                                            (save-selected-window
                                              (select-window window)
                                              (if buffer-read-only
                                                  "read-only" "writable")))))
             'local-map (purecopy (make-mode-line-mouse-map
                                   'mouse-1 #'mode-line-toggle-read-only))
             'mouse-face 'mode-line-highlight
             )))
  ":"))
;(force-mode-line-update t)
;; TODO: Customize mode-line-remote to show L or @
)

(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(diff-added ((t (:foreground "#44DD11"))))
 '(diff-context ((t nil)))
 '(diff-file-header ((((class color) (min-colors 88) (background dark)) (:foreground "gray"))))
 '(diff-function ((t (:foreground "gray"))))
 '(diff-header ((((class color) (min-colors 88) (background dark)) (:foreground "gray"))))
 '(diff-hunk-header ((t (:foreground "gray"))))
 '(diff-nonexistent ((t (:inherit diff-file-header :strike-through nil))))
 '(diff-refine-change ((((class color) (min-colors 88) (background dark)) (:background "#182042"))))
 '(diff-removed ((t (:foreground "#FF3300"))))
 '(mode-line ((((class color) (min-colors 88)) (:background "grey75" :foreground "black" :box (:line-width -1 :style released-button))))))
;;-----------------------------------------------------------------

;;-----------------------------------------------------------------
; Color and Fonts.
;;-----------------------------------------------------------------

(if (not window-system)
    (progn (menu-bar-mode nil)
           (when (try-require 'color-theme)
             (color-theme-initialize)
             (color-theme-dark-laptop))))


;(when (try-require 'color-theme)
  ;(color-theme-initialize)
  ;(color-theme-robin-hood))

(require 'font-lock)
(if (fboundp 'global-font-lock-mode)
    (global-font-lock-mode t))        ; By default turn on colorization.
;(setq frame-background-mode 'dark)

(which-function-mode t)       ; Show function name in modeline
(setq which-func-maxout 0)    ; No limit
(fset 'yes-or-no-p 'y-or-n-p) ; Make all "yes or no" prompts show "y
                              ; or n" instead
(setq use-dialog-box nil);; don't use dialog boxes to ask questions
(setq use-file-dialog nil);; don't use a file dialog to ask for files

;; Set up WindMove to be able to move between windows with control-arrow
(when (fboundp 'windmove-default-keybindings)
  (progn
    (global-set-key (kbd "C-x C-<left>")  'windmove-left)
    (global-set-key (kbd "C-x C-<right>") 'windmove-right)
    (global-set-key (kbd "C-x C-<up>")    'windmove-up)
    (global-set-key (kbd "C-x C-<down>")  'windmove-down)))

; How to navigate windows in clockwise order?
; Perhaps? http://www.stat.cmu.edu/~genovese/emacs/win-switch/
(defvar last-different-window nil "")
(defvar last-selected-window nil "")
(setq last-different-window nil)
(setq last-selected-window (selected-window))

(defadvice select-window (before update-last-window (window &optional norecord) activate)
  "Record the last-selected-window that was different"
  (let ((curr (selected-window)))
    (if (and (not (equal window last-selected-window))
             (not (equal window curr))
             (window-live-p curr))
      (setq last-different-window curr))
      (setq last-selected-window curr))
  )

(defun select-next-window ()
  "Switch to the next window" 
  (interactive)
  (select-window (next-window)))

(defun select-previous-window ()
  "Switch to the previous window" 
  (interactive)
  (select-window (previous-window)))

(defun switch-windows ()
  "Switch to the previously selected window" 
  (interactive)
  (if (or (equal last-different-window (selected-window))
          (not (window-live-p last-different-window))
          (and (window-minibuffer-p last-different-window)
               (not (minibuffer-window-active-p last-different-window))))
      (progn 
        (message "next-window (%s)" (next-window))
        (select-window (next-window)))
      (progn        
        (message "last-different-window (%s)" last-different-window)
        (select-window last-different-window))
    ))

(defun other-window-reverse ()
  "Switch to other window in reverse order"
  (interactive)
  (other-window -1))

; FIXME: How to override \C-o in buffer list?
(global-set-key "\C-o" 'select-previous-window)
; Reverse of the default stupid order of emacs
(global-set-key "\C-x\C-o" 'select-next-window)
(global-set-key "\C-xo" 'switch-windows)

;; Many times a temporary window comes up for help or compilation
;; results, auto complete, buffer list, etc. To close that one has to
;; switch to the other window and kill the buffer. After killing the
;; buffer, another buffer gets shown in that window and so we need to
;; close the window to restore the original buffer with full size.
(defun close-and-kill-next-pane ()
  "Close the other pane and kill the buffer in it also."
  (interactive)
  (other-window 1)
  ;(close-current-buffer)
  (kill-buffer)
  (delete-window)
  )

(defun close-and-kill-this-pane ()
  "Close this pane and kill the buffer in it also."
  (interactive)
  (kill-buffer)
  ;(close-current-buffer)
  (delete-window)
  )

;;-----------------------------------------------------------------

(prefer-coding-system 'utf-8);; Enable UTF-8 by default
;; Emacs < 23 sometimes require setting these directly.
;; Now they cause more problems than they solve.
;; (setq locale-coding-system 'utf-8)
;; (set-terminal-coding-system 'utf-8)
;; (set-keyboard-coding-system 'utf-8)
;; (set-selection-coding-system 'utf-8)

; If images are supported then display them when visiting them
;(if (fboundp 'auto-image-file-mode)
;    (auto-image-file-mode 1))
;;-----------------------------------------------------------------

;;-----------------------------------------------------------
;;      SERVER MODE
;;-----------------------------------------------------------
;; FIXME: I never got this to work correctly.
;;
;; Using server mode means that after starting emacs, eg from an
;; icon, there is an always-running process, which handles editing
;; requests.
;;
;; Client:
;;   alias emacs='emacsclient --alternate-editor emacs '
;; in $HOME/.bashrc. You can get this startup file re-read without
;; re-starting a terminal window, by a command such as
;;    % . .bashrc
;;
;(when (try-require 'server)
;(server-start)
;; Do not repeat custom-set-variables
;; (custom-set-variables
;;  '(server-done-hook (quote ((lambda nil (kill-buffer nil)) delete-frame)))
;;  '(server-switch-hook (quote ((lambda nil (let (server-buf)
;;                    (setq server-buf (current-buffer))
;;                    (bury-buffer)
;;                    (switch-to-buffer-other-frame server-buf))))))
;;  )

;; A function to wrap up editing of a buffer, saving it first if edited.
;; Below, this is attached to a function key. This function is only useful
;; if you are using server mode.
;;(defun wrap-up ()
;;  (interactive)
;;  (save-buffer)
;;  (server-edit))
;; (add-hook 'server-done-hook (lambda nil (kill-buffer nil)) t)
;; (add-hook 'server-visit-hook 'raise-frame t)


;;-----------------------------------------------------------------
;;  KEYS
;;-----------------------------------------------------------------
; C-u C-SPC pop-mark
; Under X to get the suppr key working.
(Xlaunch (define-key global-map [(delete)] "\C-d"))
;;Delete does deletion like ctrl-D:
;;(define-key global-map [(delete)]    "\C-d")

;; Make shifted direction keys work on the Linux console or in an xterm
(when (member (getenv "TERM") '("linux" "xterm"))
  (dolist (prefix '("\eO" "\eO1;" "\e[1;"))
    (dolist (m '(("2" . "S-") ("3" . "M-") ("4" . "S-M-") ("5" . "C-")
                 ("6" . "S-C-") ("7" . "C-M-") ("8" . "S-C-M-")))
      (dolist (k '(("A" . "<up>") ("B" . "<down>") ("C" . "<right>")
                   ("D" . "<left>") ("H" . "<home>") ("F" . "<end>")))
        (define-key function-key-map
          (concat prefix (car m) (car k))
          (read-kbd-macro (concat (cdr m) (cdr k))))))))

; X selection manipulation
(if (not (fboundp 'x-own-selection))
    (defun x-own-selection (s) (x-set-selection `PRIMARY s))
  (message ".emacs: x-own-selection already defined!"))

(global-set-key [(shift insert)] '(lambda () (interactive)
       (insert (x-get-selection))))
(global-set-key [(control insert)] '(lambda () (interactive)
       (x-own-selection (buffer-substring (point) (mark)))))

;;; XEmacs compatibility
(global-set-key [(control tab)] `other-window)
(global-set-key [(meta g)] `goto-line)
(defun switch-to-other-buffer ()
  (interactive) (switch-to-buffer (other-buffer) 1))
(global-set-key [(meta control ?l)] `switch-to-other-buffer)
(global-set-key [(meta O) ?H] 'beginning-of-line)
(global-set-key [(meta O) ?F] 'end-of-line)
;; shift-tab
(global-set-key (kbd "<backtab>")  'tab-to-tab-stop)

;; FIXME: Doesn't work!
; This prevents key-strokes deleting the echo area
;; This function goes on pre-command-hook for XEmacs or when using idle
;; timers in Emacs.  Motion commands clear the echo area for some reason,
;; which make eldoc messages flicker or disappear just before motion
;; begins.  This function reprints the last eldoc message immediately
;; before the next command executes, which does away with the flicker.
;; This doesn't seem to be required for Emacs 19.28 and earlier.
;; (defun compilation-pre-command-refresh-echo-area ()
;;   (and compilation-last-message
;;        (if (compilation-display-message-no-interference-p)
;;            (compilation-message compilation-last-message)
;;          (setq compilation-last-message nil))))
;; ;; Check various conditions about the current environment that might make
;; ;; it undesirable to print eldoc messages right this instant.
;; (defun eldoc-display-message-no-interference-p ()
;;   (and (not executing-kbd-macro)
;;        (not (and (boundp 'edebug-active) edebug-active))
;;        ;; Having this mode operate in an active minibuffer/echo area causes
;;        ;; interference with what's going on there.
;;        (not cursor-in-echo-area)
;;        (not (eq (selected-window) (minibuffer-window)))))

;; ;; (defun compilation-schedule-timer ()
;; ;;   (or (and compilation-timer
;; ;;            (memq compilation-timer timer-idle-list))
;; ;;       (setq compilation-timer
;; ;;             (run-with-idle-timer compilation-idle-delay t
;; ;;                                  'compilation-print-current-symbol-info)))

;; ;;   ;; If user has changed the idle delay, update the timer.
;; ;;   (cond ((not (= compilation-idle-delay compilation-current-idle-delay))
;; ;;          (setq compilation-current-idle-delay compilation-idle-delay)
;; ;;          (timer-set-idle-time compilation-timer compilation-idle-delay t))))

;; (defun compilation-message (&rest args)
;;   (let ((omessage compilation-last-message))
;;     (setq compilation-last-message
;;        (cond ((eq (car args) compilation-last-message) compilation-last-message)
;;              ((null (car args)) nil)
;;              ;; If only one arg, no formatting to do, so put it in
;;              ;; compilation-last-message so eq test above might succeed on
;;              ;; subsequent calls.
;;              ((null (cdr args)) (car args))
;;              (t (apply 'format args))))
;;     ;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages
;;     ;; are recorded in a log.  Do not put compilation messages in that log since
;;     ;; they are Legion.
;;     ;; Emacs way of preventing log messages.
;;     (let ((message-log-max nil))
;;       (cond (compilation-last-message (message "%s" compilation-last-message))
;;          (omessage (message nil)))))
;;   compilation-last-message)

;; ;(add-hook 'post-command-hook 'compilation-schedule-timer nil t)
;; (add-hook 'pre-command-hook 'compilation-pre-command-refresh-echo-area t)

(defun recompile-quietly ()
  "Re-compile without changing the window configuration."
  (interactive)
  (save-window-excursion
    (recompile)))

(defun compile-again (pfx)
  "Run the same compile as the last time. If there was no last time, or there is a prefix argument, this acts like M-x compile."
(interactive "p")
(save-window-excursion
  (if (and (eq pfx 1)
           compilation-last-buffer)
      (progn
        (set-buffer compilation-last-buffer)
        (revert-buffer t t))
    (call-interactively 'compile))))

(setq compilation-last-buffer nil)
;; FIXME: Doesn't work!
;; (setq compilation-last-message nil)
;; (defun notify-compilation-result(buffer msg)
;;   "Notify that the compilation is finished,
;; close the *compilation* buffer if the compilation is successful,
;; and set the focus back to Emacs frame"
;;   (if (string-match "^finished" msg)
;;       (compilation-message "Compilation %s" (propertize "finished" 'face '(:foreground "green")))
;;     (compilation-message "Compilation %s" (propertize "failed" 'face '(:foreground "red")))))

;; (add-to-list 'compilation-finish-functions
;;              'notify-compilation-result)

(define-key global-map [f5] 'compile-again)
(define-key global-map [f6] 'isearch-repeat-forward)
(define-key global-map [f10] 'wrap-up)
(global-set-key [home] 'beginning-of-line)
(global-set-key [end] 'end-of-line)
(global-set-key [(control home)] 'beginning-of-buffer)
(global-set-key [(control end)] 'end-of-buffer)
;; Make control+pageup/down scroll the other buffer
(global-set-key [(control next)] 'scroll-other-window)
(global-set-key [(control prior)] 'scroll-other-window-down)
;; By default this is suspend-frame (minimize), which is useful, but
;;some may prefer 'undo' (global-set-key [(control z)] 'undo)
(global-set-key [(control shift z)] 'redo)
;;(global-unset-key "\C-z")
(global-unset-key "\C-x\C-z")
; Replace buffer-list (if we're not going to use ibuffer.el):
(global-set-key "\C-x\C-b" 'electric-buffer-list)
;;(global-set-key "\C-x\C-b" 'buffer-menu)

;(global-set-key "\C-c\C-c" 'compile)
;(global-set-key "\C-cc" 'comment-region)
(defun swap-compile-comment-keys ()
 "Swap compile and commen-region keybindings"
 (local-unset-key "\C-c\C-c")
 (local-unset-key "\C-cc")
 (local-set-key "\C-c\C-c" 'compile)
 (local-set-key "\C-cc" 'comment-region)
)
(defun compilation-mode-keys ()
""
(local-set-key "\C-c`" 'next-error-no-select)
)
(add-hook 'makefile-mode-hook 'swap-compile-comment-keys)
(add-hook 'compilation-mode-hook 'compilation-mode-keys)
(add-hook 'c++-mode-hook         'compilation-mode-keys)
(add-hook 'c-mode-hook          'compilation-mode-keys)
(add-hook 'makefile-mode-hook   'compilation-mode-keys)

(defun my-smerge-keys ()
""
(local-set-key "\C-csn" 'smerge-next)
(local-set-key "\C-csp" 'smerge-prev)
(local-set-key "\C-cs+" 'smerge-refine)
)
(add-hook 'smerge-mode-hook   'my-smerge-keys)


(defun nxml-mode-keys()
  ""
  (local-unset-key "\C-c\C-f")
  (local-set-key "\C-c]" 'nxml-finish-element)
)
(add-hook 'nxml-mode-hook 'nxml-mode-keys)


(add-to-list 'auto-mode-alist '("TODO\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))

(global-set-key "\C-cg" 'goto-line)
(global-set-key "\C-x\C-r" 'revert-buffer)
(global-set-key [(control ?()] 'forward-sexp)
(global-set-key [(control ?))] 'backward-sexp)
;; This runs mark-sexp which is not useful. Better give it another
;; purpose outside Emacs.
(global-unset-key (read-kbd-macro "C-M-SPC"))

;; DEPRECATED: This is already the default in recent emacs
;; (defun centerer ()
;;    "Repositions current line: once middle, twice top, thrice bottom"
;;    (interactive)
;;    (cond ((eq last-command 'centerer2)  ; 3 times pressed = bottom
;;        (recenter -1))
;;       ((eq last-command 'centerer1)  ; 2 times pressed = top
;;        (recenter 0)
;;        (setq this-command 'centerer2))
;;       (t                             ; 1 time pressed = middle
;;        (recenter)
;;        (setq this-command 'centerer1))))
;;(global-set-key "\C-l"             'centerer)

(defun shuffle-lines (beg end)
  "Scramble all the lines in region defined by BEG END
If region contains less than 2 lines, lines are left untouched."
  (interactive "*r")
  (catch 'cancel
    (save-restriction
      (narrow-to-region beg end)
      ;;   Exit when there is not enough lines in region
      (if (< (- (point-max) (point-min)) 3)
      (throw 'cancel t))

      ;;    Prefix lines with a random number and a space
      (goto-char (point-min))
      (while (not (eobp))
        (insert (int-to-string (random 32000)) " ")
        (forward-line 1))

      ;;  Sort lines according to first field (random number)
      (sort-numeric-fields 1 (point-min) (point-max))

      (goto-char (point-min))  ;Remove the prefix fields
      (while (not (eobp))
        (delete-region (point) (progn (forward-word 1) (+ (point) 1)))
        (forward-line 1))
      )))


;; ISearch mods
;; Always use regexps
(global-set-key [(control s)]               'isearch-forward-regexp)
(global-set-key [(control r)]               'isearch-backward-regexp)
(global-set-key [(control c)(meta %)]       'query-replace-regexp)

;; Not really key-bindings.  These just rename a few commonly used
;; functions
(defalias 'cr 'comment-region)
(defalias 'ucr 'uncomment-region)
(defalias 'rr 'replace-rectangle)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Moving lines up & down with <M-up> & <M-down>
(defun move-line (&optional n)
  "Move current line N (1) lines up/down leaving point in place."
  (interactive "p")
  (when (null n)
    (setq n 1))
  (let ((col (current-column)))
    (beginning-of-line)
    (forward-line)
    (transpose-lines n)
    (forward-line -1)
    (forward-char col))
  (indent-according-to-mode))

(defun move-line-up (n)
  "Moves current line N (1) lines up leaving point in place."
  (interactive "p")
  (move-line (if (null n) -1 (- n))))

(defun move-line-down (n)
  "Moves current line N (1) lines down leaving point in place."
  (interactive "p")
  (move-line (if (null n) 1 n)))

(defun move-region (start end n)
  "Move the current region up or down by N lines."
  (interactive "r\np")
  (let ((line-text (delete-and-extract-region start end)))
    (forward-line n)
    (let ((start (point)))
      (insert line-text)
      (setq deactivate-mark nil)
      (set-mark start))))

(defun move-region-up (start end n)
  "Move the current region up by N lines."
  (interactive "r\np")
  (move-region start end (if (null n) -1 (- n))))

(defun move-region-down (start end n)
  "Move the current region down by N lines."
  (interactive "r\np")
  (move-region start end (if (null n) 1 n)))

;; http://www.emacswiki.org/emacs/MoveLineRegion
;; These, in combination with MoveLine and MoveRegion, provide
;; behavior similar to Eclipse’s Alt-Up/Down. They use MoveLine if
;; there is no active region, MoveRegion if there is. Note that unlike
;; in Eclipse, the region will not expand to the beginning of the
;; first line or the end of the last line.
(defun move-line-region-up (start end n)
  (interactive "r\np")
  (if (region-active-p) (move-region-up start end n) (move-line-up n)))

(defun move-line-region-down (start end n)
  (interactive "r\np")
  (if (region-active-p) (move-region-down start end n) (move-line-down n)))

;;(global-set-key (kbd "M-p") 'move-line-region-up)
;;(global-set-key (kbd "M-n") 'move-line-region-down)
(global-set-key [(meta up)]   'move-line-region-up)
(global-set-key [(meta down)] 'move-line-region-down)


;; Rectangle
(when (try-require 'rect)
  (defun copy-rectangle-as-kill (start end)
    "Copy rectangle with corners at point and mark; save as last
killed one.  Calling from program, supply two args START and END,
buffer positions.  But in programs you might prefer to use
`extract-rectangle'."
    (interactive "r")
    (setq killed-rectangle (extract-rectangle start end))
    (message "Rectangle saved."))
  (global-set-key "\C-xrw"           'copy-rectangle-as-kill)
)

(defun insert-date-string ()
  "Insert a nicely formatted date string."
  (interactive)
  (insert (format-time-string "%Y-%m-%d")))

(defun delete-horizontal-space-forward ()
  ;; adapted from `delete-horizontal-space'
  "*Delete all spaces and tabs after point."
  (interactive "*")
  (delete-region (point) (progn (skip-chars-forward " \t") (point))))
(global-set-key "\M- " 'delete-horizontal-space-forward)

;; default to unified diffs
(setq diff-switches "-u")

(defun rename-file-and-buffer ()
  "Rename the current buffer and file it is visiting."
  (interactive)
  (let ((filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (message "Buffer is not visiting a file!")
      (let ((new-name (read-file-name "New name: " filename)))
        (cond
         ((vc-backend filename) (vc-rename-file filename new-name))
         (t
          (rename-file filename new-name t)
          (set-visited-file-name new-name t t)))))))
;;-----------------------------------------------------------------


;;-----------------------------------------------------------------
;; PACKAGES CONF
;;-----------------------------------------------------------------
;; vc-git is too slow: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8288
;; (defun vc-git-state-heuristic (file)
;;   "Just claim we're up to date."
;;   'up-to-date)


;(dynamic-completion-mode) ; Use alt-enter
;; By default start in TEXT mode.
(setq-default major-mode (lambda () (text-mode) (font-lock-mode t)))
;; One may want to disable auto-fill through
;(remove-hook 'text-mode-hook 'turn-on-auto-fill)
(add-hook 'text-mode-hook 'turn-on-auto-fill)
(add-hook 'sgml-mode-hook 'turn-off-auto-fill)
(add-hook 'nxml-mode-hook 'turn-off-auto-fill)
(add-hook 'text-mode-hook 'turn-on-flyspell);; flyspell is ispell on-the-fly
;; flyspell comments and strings in programming modes
;; (preventing it from finding mistakes in the code)
(add-hook 'autoconf-mode-hook   'flyspell-prog-mode)
(add-hook 'autotest-mode-hook   'flyspell-prog-mode)
(add-hook 'c++-mode-hook        'flyspell-prog-mode)
(add-hook 'c-mode-hook          'flyspell-prog-mode)
(add-hook 'cperl-mode-hook      'flyspell-prog-mode)
(add-hook 'emacs-lisp-mode-hook 'flyspell-prog-mode)
(add-hook 'makefile-mode-hook   'flyspell-prog-mode)
(add-hook 'nxml-mode-hook       'flyspell-prog-mode)
(add-hook 'python-mode-hook     'flyspell-prog-mode)
(add-hook 'sh-mode-hook         'flyspell-prog-mode)
(add-hook 'ess-mode-hook        'flyspell-prog-mode)


; Don't add lines on the end of lines unless we want.
(setq next-line-add-newlines nil)
;; Indentation can insert tabs if this is non-nil.
(setq-default indent-tabs-mode nil)

;; turn on auto (de)compression
(auto-compression-mode t)

(put 'downcase-region 'disabled nil)

;; Adjust load path to include $HOME/lib/emacs/, etc
(setq load-path
      (cons (concat (getenv "HOME") "/.emacs.d/")
            (cons "/usr/local/share/emacs/site-lisp/" load-path)))

;; http://www.emacswiki.org/emacs/PerWindowPoint
;; NOTE: This package is obsolete as of v24. Use the built-in option switch-to-buffer-preserve-window-point instead.
(if (< emacs-major-version 24)
    (when (try-require 'per-window-point)
      (pwp-mode 1)))

;; http://www.emacswiki.org/emacs/FillColumnIndicator
(when (try-require 'fill-column-indicator)
  (setq-default fci-rule-column 80)
  ;; (define-globalized-minor-mode global-fci-mode fci-mode (lambda () (fci-mode 1)))
  ;; (global-fci-mode 1)
  (add-hook 'prog-mode-hook 'fci-mode)
  ;; For some reason, ESS[S] mode does not use prog-mode-hook
  (add-hook 'ess-mode-hook 'fci-mode)
  (add-hook 'text-mode-hook 'fci-mode)
  (add-hook 'diff-mode-hook 'fci-mode)
  )

;;(add-hook 'gdb-mode-hook '(lambda () (try-require 'gdb-highlight)))
(add-hook 'gdb-mode-hook 'compilation-shell-minor-mode)
;; FIXME: for some reason, if some key is pressed the fontification of
;; compilation-shell-minor-mode is lost, you have to call
;; font-lock-fontify-buffer

(when (try-require 'autopair)
  (autopair-global-mode) ;; enable autopair in all buffers
  (setq autopair-autowrap t) ;; select a word, press ", and automatically it's turned into "word"
  )

;; Does not trigger error if we do not have the following
(when (try-require 'ess-site)
  ;; Turn off annoying comment behaviour
  (setq ess-fancy-comments nil)
  ;; http://code.google.com/p/ess-tracebug
  (setq ess-use-tracebug t)
  (setq ess-tracebug-prefix "\M-c")
  ;; Bug in ESS, very slow eval-and-go
  (setq ess-eval-visibly-p nil)

  ;; http://www.kieranhealy.org/blog/archives/2009/10/12/make-shift-enter-do-a-lot-in-ess/
  ;; Starting with an R file in the buffer, hitting shift-enter
  ;; vertically splits the window and starts R in the right-side
  ;; buffer. If R is running and a region is highlighted, shift-enter
  ;; sends the region over to R to be evaluated. If R is running and no
  ;; region is highlighted, shift-enter sends the current line over to
  ;; R. Repeatedly hitting shift-enter in an R file steps through each
  ;; line (sending it to R), skipping commented lines. The cursor is
  ;; also moved down to the bottom of the R buffer after each
  ;; evaluation.
  (setq ess-ask-for-ess-directory nil)
  (setq ess-local-process-name "R")
  (setq ansi-color-for-comint-mode 'filter)
  (setq comint-scroll-to-bottom-on-input t)
  (setq comint-scroll-to-bottom-on-output t)
  (setq comint-move-point-for-output t)
  (defun my-ess-start-R ()
    (interactive)
    (if (not (member "*R*" (mapcar (function buffer-name) (buffer-list))))
        (progn
          (delete-other-windows)
          (setq w1 (selected-window))
          (setq w1name (buffer-name))
          (setq w2 (split-window w1 nil t))
          (R)
          (set-window-buffer w2 "*R*")
          (set-window-buffer w1 w1name))))
  (defun my-ess-eval ()
    (interactive)
    (my-ess-start-R)
    (if (and transient-mark-mode mark-active)
        (call-interactively 'ess-eval-region)
      (call-interactively 'ess-eval-line-and-step)))
  (defun my-ess-mode-keys ()
    (local-set-key [(shift return)] 'my-ess-eval)
    )
  (defun my-inferior-ess-mode-keys ()
    (local-set-key [C-up] 'comint-previous-input)
    (local-set-key [C-down] 'comint-next-input)
    )

  (add-hook 'ess-mode-hook 'my-inferior-ess-mode-keys)
  (add-hook 'inferior-ess-mode-hook 'my-inferior-ess-mode-keys)
  (add-hook 'Rnw-mode-hook 'my-inferior-ess-mode-keys)
  )

; FIXME: use try-require
;(load "$HOME/.emacs.d/comet-mode")

;;;  Jonas.Jarnestrom<at>ki.ericsson.se A smarter
;;;  find-tag that automagically reruns etags when it can't find a
;;;  requested item and then makes a new try to locate it.
;;;  Fri Mar 15 09:52:14 2002
(defadvice find-tag (around refresh-etags activate)
  "Rerun etags and reload tags if tag not found and redo find-tag.
   If buffer is modified, ask about save before running etags."
  (let ((extension (file-name-extension (buffer-file-name))))
    (condition-case err
        ad-do-it
      (error (and (buffer-modified-p)
                  (not (ding))
                  (y-or-n-p "Buffer is modified, save it? ")
                  (save-buffer))
             (refresh-etags extension)
             ad-do-it))))

(defun refresh-etags (&optional extension)
  "Run etags on all peer files in current dir and reload them silently."
  (interactive)
  (shell-command (format "etags *.%s" (or extension "el")))
  (let ((tags-revert-without-query t))  ; don't query, revert silently
    (visit-tags-table default-directory nil)))
; Don't ask to revert for TAGS
(setq revert-without-query (cons "TAGS" revert-without-query))

;;------------------------
;; ISPELL / ASPELL
;;------------------------
;; (setq ispell-local-dictionary-alist
;;       '(
;;      ("spanish"
;;       "[A-Za-zÁÉÍÓÚÜÑáéíóúüñ]" "[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ]" "[']" t
;;       ("-d" "spanish" "-T" "latin1") "~latin1" iso-latin-9)
;;      ("spanish-html"
;;       "[A-Za-zÁÉÍÓÚÜÑáéíóúüñ]" "[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ]" "" nil
;;       ("-B" "-H" "-d" "spanish" "-T" "latin1") "~latin1" iso-latin-9)
;;      )
;; )




;;---------------------------------------------------
;; WHITESPACE Deletes trailing whitespace in email/files when save/send
;; See: http://www.splode.com/~friedman/software/emacs-lisp/
;;---------------------------------------------------
;; (if (require 'whitespace "whitespace" t)
;;     (progn (add-hook 'write-file-hooks 'whitespace-write-file-hook)
;;            (setq whitespace-auto-cleanup t)
;;            (setq whitespace-display-in-modeline nil) )
;;   (message "Warning: .emacs: whitespace.el not available!"))

;; (if (and (require 'nuke-trailing-whitespace "nuke-trailing-whitespace" t)
;;          (fboundp 'nuke-trailing-whitespace))
;;     (progn  (autoload 'nuke-trailing-whitespace "nuke-trailing-whitespace" nil t)
;;             (message "OK: .emacs: nuke-trailing-whitespace in  nuke-trailing-whitespace.el!"))
;;   ;;   (if (and (require 'whitespace "whitespace" t)
;;   ;;            (fboundp 'whitespace-cleanup))
;;   ;;       (progn  (autoload 'whitespace-cleanup "whitespace" nil t)
;;   ;;               (defun nuke-trailing-whitespace () (delete-trailing-whitespace))
;;   ;;               (message "OK: .emacs: whitespace-cleanup in whitespace.el!"))
;;   (if (and (require 'whitespace "whitespace" t)
;;            (fboundp 'nuke-trailing-whitespace))
;;       (progn  (autoload 'nuke-trailing-whitespace "whitespace" nil t)
;;               (message "OK: .emacs: nuke-trailing-whitespace in whitespace.el!"))
;;     (if (fboundp 'delete-trailing-whitespace)
;;         (progn (defun nuke-trailing-whitespace () (delete-trailing-whitespace))
;;                (message "Warning: .emacs: nuke-trailing-whitespace not available, using delete-trailing-whitespace!"))
;;       (message "Warning: .emacs: nuke-trailing-whitespace not available!"))
;;     ))
;;(setq whitespace-modes (cons 'bibtex-mode (cons 'bibtex-mode
;;                                                whitespace-modes)))

;; ;;(add-hook 'mail-send-hook 'nuke-trailing-whitespace)
;(add-hook 'write-file-hooks 'nuke-trailing-whitespace)

;Show path info in otherwise identical filenames
(when (try-require 'uniquify)
  (setq uniquify-buffer-name-style 'post-forward)
  (setq uniquify-after-kill-buffer-p t)
)

(defun uniquify-all-lines-region (start end)
  "Find duplicate lines in region START to END keeping first occurrence."
  (interactive "*r")
  (save-excursion
    (let ((end (copy-marker end)))
      (while
          (progn
            (goto-char start)
            (re-search-forward "^\\(.*\\)\n\\(\\(.*\n\\)*\\)\\1\n" end t))
        (replace-match "\\1\n\\2")))))
  
(defun uniquify-all-lines-buffer ()
  "Delete duplicate lines in buffer and keep first occurrence."
  (interactive "*")
  (uniquify-all-lines-region (point-min) (point-max)))

;; ido-mode without customizations is better than iswitchb.
(when (try-require 'ido)
  (ido-mode t)
  (setq ido-enable-flex-matching t); flexibly match names
  (setq ido-everywhere t); use ido-mode everywhere, in buffers and for finding files
  (setq ido-use-filename-at-point 'guess); for find-file-at-point
  (add-hook 'ido-setup-hook 'ido-my-keys)
  (defun ido-my-keys ()
    "Add my keybindings for ido."
    (define-key ido-file-dir-completion-map [C-return] 'ido-enter-dired)
    (define-key ido-file-dir-completion-map [down] 'ido-next-work-directory)
    (define-key ido-file-dir-completion-map [up]   'ido-prev-work-directory)
  )
)
;; -----------------------------------------------------
;; iswitchb -- switch buffers
;; -----------------------------------------------------
;; (iswitchb-mode t)
;; (setq iswitchb-buffer-ignore '("^ " "*Buffer"))
;; (add-hook
;;  'iswitchb-define-mode-map-hook
;;  '(lambda ()
;;     (define-key iswitchb-mode-map [up] 'iswitchb-next-match)
;;     (define-key iswitchb-mode-map [down] 'iswitchb-prev-match)
;;     (define-key iswitchb-mode-map [right] 'iswitchb-next-match)
;;     (define-key iswitchb-mode-map [left] 'iswitchb-prev-match)))

;; (defadvice iswitchb-kill-buffer (after rescan-after-kill activate)
;;   "*Regenerate the list of matching buffer names after a kill.
;;     Necessary if using `uniquify' with `uniquify-after-kill-buffer-p'
;;     set to non-nil."
;;   (setq iswitchb-buflist iswitchb-matches)
;;   (iswitchb-rescan))

;; (defun iswitchb-rescan ()
;;   "*Regenerate the list of matching buffer names."
;;   (interactive)
;;   (iswitchb-make-buflist iswitchb-default)
;;   (setq iswitchb-rescan t))

;; -----------------------------------------------------

;;I never use this
;;Make a "recent file list"
;; (if (require 'recentf "recentf" t)
;;     (recentf-mode 1)
;;   (message "Warning: .emacs: recentf file list not available!"))


;; word-count mode
(when (try-require 'wc-mode)
  ;; Suggested setting
  (global-set-key "\C-cw" 'wc-mode)
)

(when (try-require 'ffap) ; Enhace C-x C-f to open file from text.
  ;; rebind C-x C-f and others to the ffap bindings (see variable ffap-bindings)
  (global-set-key  [S-mouse-3]  'ffap-at-mouse)
  (global-set-key  [C-S-mouse-3]  'ffap-menu)
 (global-set-key "\C-xf" 'find-file-at-point)
  )

;; Keep yank in middle-button, use right-button for list of corrections
(eval-after-load "flyspell"
  '(progn
     (define-key flyspell-mouse-map [mouse-2] #'undefined)
     (define-key flyspell-mouse-map [down-mouse-2] #'mouse-yank-primary)
     (define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word)
     (define-key flyspell-mouse-map [mouse-3] #'undefined)))

;; Save minibuffer history between sessions
(when (try-require 'savehist)
  (savehist-mode t))


(autoload 'tidy-buffer "tidy" "Run Tidy HTML parser on current buffer" t)
(autoload 'tidy-parse-config-file "tidy" "Parse the `tidy-config-file'" t)
(autoload 'tidy-save-settings "tidy" "Save settings to `tidy-config-file'" t)
(autoload 'tidy-build-menu  "tidy" "Install an options menu for HTML Tidy." t)
(defun my-html-helper-mode-hook () "Customize my html-helper-mode."
  (tidy-build-menu html-helper-mode-map)
  (local-set-key [(control c) (control c)] 'tidy-buffer)
  (setq sgml-validate-command "tidy")
  (tidy-build-menu))

(defun my-html-mode-hook () "Customize my html-mode."
  (tidy-build-menu html-mode-map)
  (local-set-key [(control c) (control c)] 'tidy-buffer)
  (setq sgml-validate-command "tidy")
  (tidy-build-menu)
  (set (make-local-variable 'time-stamp-active) t)
  (set (make-local-variable 'time-stamp-pattern)
       "-20/Last modified:[\t ]+%:d %:b %Y[\n\t ]*<!-- hhmts end -->")
  )
(add-hook 'html-helper-mode-hook 'my-html-helper-mode-hook)
;; Disable html-helper-mode
;; html-helper-mode does not have close-tag!!!
(add-to-list 'magic-mode-alist 
    '("\\(?:<\\?xml\\s +[^>]*>\\)?\\s *<\\(?:!--\\(?:[^-]\\|-[^-]\\)*-->\\s *<\\)*\\(?:!DOCTYPE\\s +[^>]*>\\s *<\\s *\\(?:!--\\(?:[^-]\\|-[^-]\\)*-->\\s *\<\\)*\\)?[Hh][Tt][Mm][Ll]"
        . html-mode))
(defun html-helper-custom-insert-timestamp ()
  "Custom timestamp insertion function."
  (insert "Last modified: ")
  (insert (format-time-string "%e %B %Y")))
(setq html-helper-timestamp-hook 'html-helper-custom-insert-timestamp)
(eval-after-load 'sgml-mode
  '(add-hook 'html-mode-hook 'my-html-mode-hook))
(add-hook 'write-file-hooks 'time-stamp)

;; CSS-mode
(setq cssm-indent-level 4)
(setq cssm-newline-before-closing-bracket t)
(setq cssm-indent-function 'cssm-c-style-indenter)
(setq cssm-mirror-mode nil)

;; (add-hook 'html-helper-mode-hook
;;           (lambda ()
;;             (defun tidy-html ()
;;               "Run Tidy HTML parser on current region."
;;               (interactive)
;;               (let ((start (mark))
;;                     (end (point))
;;                     (command "tidy -i -q --tidy-mark n --gnu-emacs y --indent-spaces 1 --wrap 80 --replace-color y"))
;;                 (shell-command-on-region start end command t t
;;                                          "tidy-errors")))
;;             (define-key html-helper-mode-map [(meta q)] 'tidy-html)))


;; auto-raise and -lower. If mouse moves into/out of the emacs frame it gets
;; raised/lowered automatically:
;; IT DOES NOT WORK FOR ME
;(auto-raise-mode 1)
;(auto-lower-mode 1)

;;----------------
;; AUTO-SAVE
;;----------------
(setq
 auto-save-interval 60 ;auto-save every minute
 auto-save-timeout nil
; version-control 'never
)

;; This is too slow when closing files! Disabled for now.
;; Save positions in files between sessions
;; (when (try-require 'saveplace) 
;;   (setq save-place-file "~/.emacs.d/saved-places")
;;   (setq-default save-place t)
;;   ;; For server
;;   ;;(add-hook 'server-visit-hook 'save-place-find-file-hook t)
;; )

;; FIXME: This blocks the gdb buffer
;; (add-hook 'gud-mode-hook
;;           (function (lambda ()
;;                       (setq comint-output-filter-functions 'comint-truncate-buffer
;;                             comint-buffer-maximum-size 5000
;;                             comint-scroll-show-maximum-output t
;;                             comint-input-ring-size 500))))
(add-hook 'gud-mode-hook 'turn-off-auto-fill)
;; Clear buffer in GDB, shell, etc.
(defun clear-comint-buffer()
  (interactive)
  (delete-region (point-min)
                 (save-excursion
                   (goto-char (point-max))
                   (forward-line 0)
                   (point))))

;;----------------
;;  AucTeX
;;----------------
;; FIXME: What of this stuff is really needed?
(when (try-require 'tex-site)
  ;; some basic customizations
  (setq TeX-auto-save t)
  (setq TeX-parse-self t)
  (setq-default TeX-master nil) ; Query for master file.
  ;; default Style and Options.
  (setq LaTeX-default-options "a4paper")
  ;; don't modify font size
  (setq font-latex-title-fontify 'color)
  ;; some small but handy macros
  (defun LaTeX-insert-footnote ()
    "Insert a \\footnote{} macro in a LaTeX-document."
    (interactive)
    (TeX-insert-macro "footnote"))
  (defun LaTeX-insert-note ()
    "Insert a \\note{} macro in a LaTeX-document."
    (interactive)
    (TeX-insert-macro "note"))
  (defun LaTeX-insert-index ()
    "Insert a \\index{} macro in a LaTeX-document."
    (interactive)
    (TeX-insert-macro "index"))
  (defun my-auctex-settings ()
    "Some local modifications to AucTeX variables."
    (setq TeX-master nil) ; Query for master file.
    )
  (defvar LaTeX-mode-setup-hook nil
    "Hook for things to do before LaTeX-mode is defined.")
  (defadvice latex-mode (before latex-mode-setup-advice)
    (run-hooks 'LaTeX-mode-setup-hook))
  (add-hook 'LaTeX-mode-setup-hook 'my-auctex-settings t)

  (defun my-auctex-keys ()
    "Some local modifications to AucTeX keybindings."
    ;; Local Functions above
    (local-set-key "\C-cf" 'LaTeX-insert-footnote)
    (local-set-key "\C-cn" 'LaTeX-insert-note)
    (local-set-key [(control s)] 'isearch-forward-regexp)
    (local-set-key [(control meta s)] 'isearch-forward)
    (local-set-key [(control r)] 'isearch-backward-regexp)
    (local-set-key [(control meta r)] 'isearch-backward)
    ;;  (local-set-key "\C-s" 'word-search-forward)
    ;;  (local-set-key "\C-r" 'word-search-backward)
    ;; use latex-help
    (define-key LaTeX-mode-map "\C-ci" 'latex-help)
    )


  (defun my-latex-add-ons ()
    "Anything you ever wanted in LaTeX-mode."
    ;; load some additional packages
    (try-require 'bib-cite)
    (try-require 'font-latex)

    ;; modify keys and vars
    (my-auctex-keys)
    (local-set-key [mouse-3] 'reftex-mode-menu)

    ;;----------------------------------------
    ;; RefTeX handling of \ref, \label, \cite
    ;;----------------------------------------
    ;; configure RefTeX before loading it.
    (setq
     reftex-enable-partial-scans t ; only parse current file
     reftex-save-parse-info t      ; save parsing results
     reftex-use-multiple-selection-buffers t ; diff buffs for label select.
     reftex-plug-into-AUCTeX t     ; interact with AucTeX, of course
     reftex-extra-bindings t       ; use additional C-c bindings
     )
   ;;  (when (try-require 'reftex)
   ;;    (autoload 'reftex-mode "reftex" "RefTeX minor mode" t)
   ;;    (autoload 'turn-on-reftex "reftex" "RefTeX Minor Mode" t)
   ;;  )
    ;; now really use RefTeX
    (turn-on-reftex)


    ;; ensure auto-fill is done, enable outline and don't do func-menu
    (turn-off-auto-fill)
    ;;(outline-minor-mode 1)
    ;; (remove-func-menu-auto-rescan)

    (defvar LaTeX-align-current-environments
      (mapcar 'car '(("tabbing")
                     ("spreadtab")
                     ("tabular")
                     ("tabular*")))
      "List of LaTeX environments to do align.")

    (defun LaTeX-align-or-fill-function (&optional justify)
      "Variant of 'fill-paragraph-function' based on current
environment. In tabular-like environments, align
columns. Otherwise, fill as normal."
      (interactive "P")
      (if (member (LaTeX-current-environment)
                  LaTeX-align-current-environments)
          (save-excursion
            (LaTeX-mark-environment)
            (align-current) t)
        (LaTeX-fill-paragraph)))

    (setq fill-paragraph-function 'LaTeX-align-or-fill-function)
    (message "Making private modifications ..."))

  (add-hook 'LaTeX-mode-hook 'my-latex-add-ons)
  (add-hook 'TeX-mode-hook   'turn-off-auto-fill)
  )


;;---------------------------
;;  JavaScript MODE
;;  http://www.brgeight.se/downloads/emacs/javascript.el
;;---------------------------
(add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode))
(autoload 'javascript-mode "javascript" nil t)
(setq javascript-indent-level 8)

;;---------------------------
;;  C/C++  MODE
;;---------------------------
(c-add-style
 "my-c-common-style"
 '("k&r"
   ;;    (setq tab-width 3
   ;; make sure spaces are used instead of tabs
   ;;            indent-tabs-mode nil)
   (c-basic-offset . 4)
   (c-set-offset 'case-label 2)
   ))

(defun my-c-mode-common-hook ()
 "C/C++ mode with adjusted defaults."
 (c-set-style "my-c-common-style")
 (setq c++-tab-always-indent t)
 (setq c-backslash-column 79)
 (setq c-backslash-max-column 79)
 ;; Use C-c C-o to find out what to adjust.
 (c-set-offset 'case-label 2)
 (c-set-offset 'inextern-lang 0) ; Do not indent extern "C" blocks.
 (c-set-offset 'inline-open 0) ; Do not indent braces inline
 (c-set-offset 'innamespace 0) ; Do not indent within namespace
 ;(c-set-offset 'member-init-intro *) ; Half-indent ":" in member initializer list
 (message "Loading my-c-common-mode-hook...")
 (swap-compile-comment-keys)
 )

(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

(defun linux-c-mode ()
  "C mode with adjusted defaults for use with the Linux kernel."
  (interactive)
  (c-mode)
  (c-set-style "k&r")
  (setq c-basic-offset 3)
  (swap-compile-comment-keys)
  (message "Loading linux-c-mode...")
)

(defun gcc-c-mode-hook ()
  "C mode for GCC development."
  (which-function-mode t)       ; Show function name in modeline
  (setq which-func-maxout 0)  ; No limit
  (c-set-style "gnu")
  (setq c-basic-offset 2)
  (c-set-offset 'inline-open 0)
  (setq-default indent-tabs-mode t)
  (swap-compile-comment-keys)
  (message "Loading gcc-c-mode...")
  )

(defun gcc-c-mode ()
  "C mode for GCC development."
  (interactive)
  (remove-hook 'c-mode-common-hook 'my-c-mode-common-hook)
;  (c-set-style "gnu")
;  (c-set-offset 'inline-open 0)
  (add-hook 'c-mode-common-hook 'gcc-c-mode-hook)
  (text-mode)
  (c-mode)
  )

; By default files ending in .h are treated as c files rather than c++ files. 
(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))

;; -------------------------------------------
;; gnuplot mode
;; -------------------------------------------
(defun my-gnuplot-mode-keys ()
  (define-key gnuplot-mode-map "\C-c\C-c" 'gnuplot-send-buffer-to-gnuplot))
(eval-after-load "gnuplot"
  (add-hook 'gnuplot-mode-hook 'my-gnuplot-mode-keys))


;;
;; C-, 'flyspell-next-error
;; C-. 'flyspell-auto-correct-word
;; (eval-after-load "flyspell"
;;   '(local-set-key [(control ?\;)] 'flyspell-auto-correct-word)
;;   )

;;----------------------
;; PERL MODE
;;----------------------
;; Use cperl-mode instead of the default perl-mode
(add-to-list 'auto-mode-alist '("\\.\\([pP][Llm]\\|al\\)\\'" . cperl-mode))
(add-to-list 'interpreter-mode-alist '("perl" . cperl-mode))
(add-to-list 'interpreter-mode-alist '("perl5" . cperl-mode))
(add-to-list 'interpreter-mode-alist '("miniperl" . cperl-mode))
;;
(defun n-cperl-mode-hook ()
  "cPerl mode with adjusted defaults."
  (setq cperl-indent-level 4)
  (setq cperl-continued-statement-offset 0)
  (setq cperl-extra-newline-before-brace t)
  (set-face-background 'cperl-array-face "dark slate gray")
  (set-face-background 'cperl-hash-face "dark slate gray")
  )
(add-hook 'cperl-mode-hook 'n-cperl-mode-hook t)
;;(setq cperl-auto-newline t)
(setq cperl-invalid-face (quote off))
;; expands for keywords such as foreach, while, etc...
;;(setq cperl-electric-keywords t)


;;------------------------------------------------------------------------
;; Save a buffer in a specified EOL format with the C-x RET f
;;------------------------------------------------------------------------
;; For example, to save a buffer with Unix EOL format, type:
;;     C-x RET f unix RET C-x C-s.
;; To save it as DOS EOL format, type:  C-x RET f dos RET C-x C-s.
;;------------------------------------------------------------------------
(defun find-non-ascii ()
  "Find any non-ascii characters in the current buffer."
  (interactive)
  (occur "[^[:ascii:]]"))


(defun count-words-region (beginning end)
  "Print number of words in the region."
  (interactive "r")
  (message "Counting words in region ... ")
;;; 1. Set up appropriate conditions.
  (save-excursion
    (let ((count 0))
      (goto-char beginning)
;;; 2. Run the while loop.
      (while (and (< (point) end)
                  (re-search-forward "\\w+\\W*" end t))
        (setq count (1+ count)))
;;; 3. Send a message to the user.
      (cond ((zerop count)
             (message
              "The region does NOT have any words."))
            ((= 1 count)
             (message
              "The region has 1 word."))
            (t
             (message
              "The region has %d words." count)))))
  )

(when (try-require 'printing)           ; load printing package
  (pr-update-menus t))          ; update now printer and utility menus

;; This is a macro I use in my research but it is useless for anyone else.
(fset 'pump_replace
   [?\C-  C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right ?\C-w down C-right ?  ?\C-y ?\C-k ?\C-  home ?\C-w delete up return up ?\C-y home down])

;; Unset the debug option when there is trouble...
;;(setq debug-on-error nil)

;; warn that some packages were missing
(if missing-packages-list
    (progn (message "Packages not found: %S"
                    (nreverse missing-packages-list))))

;; Doesn't work in Emacs 24. :-(
;; (message "My .emacs loaded in %d s" 
;;          (destructuring-bind (hi lo ms) (current-time)
;;            (- (+ hi lo) (+ (first *emacs-load-start*)
;;                            (second *emacs-load-start*)))))
;; More information with the info file (Control-h i)
;;
;;--------------------------------------------
;;  END of .emacs $Revision: 1361 $
;;--------------------------------------------