
(add-to-list 'load-path "~/.emacs.d")

(require 'cmake-mode)
(setq auto-mode-alist
      (append '(("CMakeLists\\.txt\\'" . cmake-mode)
		("\\.cmake\\'" . cmake-mode))
	      auto-mode-alist))

;(set-default-font "7x13")

;(setq make-backup-files nil)
(setq inhibit-startup-message t)
;(setq auto-save-default nil)
;(setq auto-save-interval 0)


; default indendation to 2 for most languages
(add-hook 'c-mode-common-hook
	  '(lambda ()
	     (set-variable 'c-basic-offset 2)
;	     (set-variable 'c-tab-always-indent nil)
             (setq c-label-minimum-indentation 0)
             (set-variable 'c-auto-align-backslashes nil)
             (setq show-trailing-whitespace t)
             (c-set-offset 'case-label '+)
             (c-set-offset 'statement-case-open '+)
             (c-set-offset 'innamespace 0)
             (c-set-offset 'inline-open 0)
	   )
)
(add-hook 'perl-mode-common-hook
	  '(lambda ()
	     (set-variable 'c-basic-offset 2)
;	     (set-variable 'c-tab-always-indent nil)
	   )
)
(set-variable 'tcl-indent-level 2)
(set-variable 'perl-indent-level 2)
(set-variable 'standard-indent 2)

; indent case statements ala BSD KNF / K&R style regardless of mode
(c-set-offset 'case-label '+)
(c-set-offset 'statement-case-open '+)
(c-set-offset 'innamespace 0)
(c-set-offset 'inline-open 0)

; Turn on font-lock mode and support large files
(set-variable 'font-lock-maximum-size 18024000) 
(global-font-lock-mode t)
(transient-mark-mode t)
(turn-on-font-lock)

; Stop at the end of the file, not just add lines
(setq next-line-add-newlines nil)

; make sure goto labels can be placed on column 0
(setq c-label-minimum-indentation 0)

; display column numbers in addition to line numbers
(set-variable 'column-number-mode t)

; to not read-only lock other people's cvs files (and not go into vc-mode)
(set-variable 'vc-handle-cvs nil)

(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.
 '(gud-gdb-command-name "gdb --annotate=1")
 '(htmlize-generate-hyperlinks nil)
 '(htmlize-output-type (quote font))
 '(indent-tabs-mode nil)
 '(large-file-warning-threshold nil)
 '(load-home-init-file t t)
 '(ps-lpr-command "lpr")
 '(safe-local-variable-values (quote ((codeing . utf-8) (standard-indent . 4) (sh-indentation . 4) (sh-basic-offset . 4) (tcl-indent-level . 4))))
 '(sh-indentation 4)
 '(visible-bell t))


;;;;;;;;;;;;;;;;
; key bindings ;
;;;;;;;;;;;;;;;;

(global-set-key [end] 'end-of-line)
(global-set-key [home] 'beginning-of-line)

; bind "C-x g" to be M-x goto-line
(global-set-key "\C-xg" 'goto-line)

; bind "C-h" to be a backwards delete (instead of help)
(global-set-key "\C-h" 'delete-backward-char)

; bind "C-?" to be a backwards delete
(global-set-key "\C-?" 'delete-backward-char)

; delete forward instead of backwards?
;(global-set-key [delete] 'delete-char)
;(global-set-key [kp-delete] 'delete-char)

; swap the delete and backspace keys
;(keyboard-translate ?\C-h ?\C-?)

; overrides mark-whole-buffer
(global-set-key "\C-xh" 'help-command)

; bookmark shortcuts
(global-set-key '[f9] 'list-bookmarks)
(add-hook 'window-setup-hook 'list-bookmarks)
;(switch-to-buffer "*Bookmark List*")


;;;;;;;;;;;;;
; functions ;
;;;;;;;;;;;;;

(defun top-of-window () (move-to-window-line 1))
(defun bottom-of-window () (move-to-window-line -1) )

(defun dos-unix ()
  "Convert DOS CR-LF to UNIX NL"
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (search-forward "\r" nil t) (replace-match ""))))

(defun unix-dos ()
  "Convert UNIX NL to DOS CR-LF"
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (search-forward "\n" nil t) (replace-match "\r\n"))))

(defun ws ()
  "Make sure there is a space after every comma"
  (interactive)
  (save-excursion
    (set-variable 'case-fold-search nil)
    (goto-char (point-min))
    (while (re-search-forward "\\([,(]\\)\\([^[:space:]\n,]\\)" nil t) (replace-match "\\1 \\2"))
    (goto-char (point-min))
    (while (re-search-forward "([ 	]+" nil t) (replace-match "("))
    (goto-char (point-min))
    (while (re-search-forward "[ 	]+)" nil t) (replace-match ")"))
    (goto-char (point-min))
    (while (re-search-forward ")[ 	]+\\([a-zA-Z]\\)" nil t) (replace-match ") \\1"))
    (goto-char (point-min))
    (while (re-search-forward "}[ 	]*else[ 	]*{" nil t) (replace-match "} else {"))
    (goto-char (point-min))
    (while (search-forward "if[ 	]*(" nil t) (replace-match "if ("))
    (goto-char (point-min))
    (while (search-forward "for[ 	]*(" nil t) (replace-match "for ("))
    (goto-char (point-min))
    (while (search-forward "while[ 	]*(" nil t) (replace-match "while ("))
    (goto-char (point-min))
    (while (search-forward ")[ 	]*{" nil t) (replace-match ") {"))
    (goto-char (point-min))
    (while (re-search-forward ")[[:space:]]*{" nil t) (replace-match ") {"))
    (goto-char (point-min))
    (while (re-search-forward "
\\(};?\\)[ 	]*
[
 	]+" nil t) (replace-match "
\\1


"))
    (goto-char (point-min))
    (while (re-search-forward "
[ 	]*
[ 	
]+
" nil t) (replace-match "


"))
    (c-set-offset 'case-label '+)
    (c-set-offset 'statement-case-open '+)
    (c-set-offset 'innamespace 0)
    (c-set-offset 'inline-open 0)
    (indent-region (point-min) (point-max) nil)
    ))

(defun ws2 ()
  "Removes embedded white space (particularly tabs)"
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (query-replace-regexp "\\([[:alnum:]_*(\[{@<>+#!\"'-]\\)[ 	]*	[ 	]*\\([[:alnum:]_*(\[{@<>+#!\"'-][[:alnum:]_*(\[{@<>+#!\"'-]?\\)[	 ]+" "\\1 \\2 "))
    (goto-char (point-min))
    (while (query-replace-regexp "\\([[:alnum:]_*(\[{@<>+#!\"'-]\\)[ 	]*	[ 	]*\\([[:alnum:]_*(\[{@<>+#!\"'-]\\)" "\\1 \\2"))
    (goto-char (point-min))
    (while (query-replace-regexp "\\([[:alnum:]_*(\[{@<>+#!\"'-]\\)[ 	]+ +[ 	]*\\([[:alnum:]_*(\[{@<>+#!\"'-]\\)" "\\1 \\2"))
    ))

(defun ws3 ()
  "collapses multiple empty lines and ensures two after every global block"
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (query-replace-regexp "
\\(};?\\)[ 	]*
[
 	][
 	]+" "
\\1


"))
    (goto-char (point-min))
    (while (query-replace-regexp "
[ 	]*

[ 	
]+
" "


"))
    ))

(defun embrace ()
  "fix else statements and braces to be K&R style"
  (interactive)
  (save-excursion
    (goto-char (point-min))
    ; move comment before brace to after (curlie on same line)
    (while (query-replace-regexp "[[:space:]]*\\(/\\*.*\\*/\\)[[:space:]]*{
\\([[:space:]]+\\)" " {
\\2\\1
\\2"))
    (goto-char (point-min))
    ; move comment before brace to after (curlie on next line)
    (while (query-replace-regexp "[[:space:]]*\\(/\\*.*\\*/\\)[[:space:]]*
\\([[:space:]]+\\){" " {
\\2\\1"))
    (goto-char (point-min))
    ; move comment after brace to next line (curlie on same line)
    (while (query-replace-regexp "[[:space:]]*{[[:space:]]*\\(/\\*.*\\*/\\)[[:space:]]*
\\([[:space:]]+\\)" " {
\\2\\1
\\2"))
    ))


(defun embrace2 ()
  "fix else statements and braces to be K&R style"
  (interactive)
  (save-excursion
    (goto-char (point-min))
    ; pull up else after close brace
    (while (query-replace-regexp "}[[:space:]]*
[[:space:]]+\\(else\\)" "} \\1"))
    (goto-char (point-min))
    ; pull up open braces to do/else
    (while (query-replace-regexp "\\(do\\|else\\)[[:space:]]*
[[:space:]]+{" "\\1\\2 {"))
    (goto-char (point-min))
    ; try to only match braced lines for expressions
    (while (query-replace-regexp "\\(if\\|while\\|switch\\|for\\)[[:space:]]+(\\(.*?\\)[[:space:]]*
[[:space:]]+{" "\\1 (\\2 {"))
    ))

; custom bindings to support our style idiosyncrasies
(global-set-key "\M-0" 'ws)
(global-set-key "\M-9" 'ws2)
(global-set-key "\M-8" 'embrace)
(global-set-key "\M-7" 'ws3)
(global-set-key "\M-6" 'embrace2)

(defun compile-normal ()
  (interactive)
  (setq compile-command "make"
        compilation-ask-about-save nil
        compilation-window-height 15
        compilation-read-command nil
        compilation-scroll-output t))

(defun compile-clean ()
  (interactive)
  (setq compile-command "make clean"
        compilation-ask-about-save nil
        compilation-window-height 15
        compilation-read-command nil
        compilation-scroll-output t))

(defun compile-make ()
  "Make"
  (interactive)
  (compile-normal)
  (compile "make"))


(defun compile-make-clean ()
  "Make clean"
  (interactive)
  (compile-clean)
  (compile-normal)
  (compile "make clean"))

; compile
(global-set-key '[f7] 'compile-make-clean)
(global-set-key '[f8] 'compile-make)
(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.
 )
