;;; -*- mode: emacs-lisp; mode: outline-minor -*-

;;; * Preface
;;; ** hanumizzle's .emacs: Emacs is rice. The volume goes to 11 here.
;;; *** Rationale

;; I have heavily commented my .emacs for my own educational purposes and
;; likewise for your didactic pleasure. Any questions, comments, or suggested
;; improvements can be sent to <hanumizzle AT gmail DOT com>.

;;; * General System and File Management
;;; ** Library Management
;;; *** Sitewide Autoloads

;; Load the loaddefs.el file, containing autoloads for every Emacs LISP file
;; in `load-path'. This seems not to be done by default, at least not in Emacs
;; 22, which ostensibly only loads default autoload definitions that were
;; made when Emacs was built.
;;
;; To regenerate loaddefs.el for the most recent (as of this writing) CVS
;; Emacs, go into Emacs as root and evaluate:
;;
;;   (setq source-directory "$PREFIX/share/emacs/22.0.50")
;;   (dolist (path load-path) (update-directory-autoloads load-path))
;; 
;; ...where $PREFIX will be swapped for the prefix of the installation.
(load "loaddefs")

;;; ** File Backup

;; All backups will fall within the .backup directory under the same directory
;; as the file itself, and Emacs will automagically deal with conflicting file
;; names and what not
(push '("." . ".backup") backup-directory-alist)

;; Backup by copying; save all my permissions and that other good shit
(setq backup-by-copying t)

;;; ** Persistence

;; Enable desktop.el; it's just this easy in Emacs 22. Kick ass.
(desktop-save-mode t)

;; Remove old variables from desktop-globals-to-save that no longer exist in
;; Emacs; you would think they would have updated this by now??
(delete 'search-ring desktop-globals-to-save)
(delete 'regexp-search-ring desktop-globals-to-save)

;; Directory-local sessions are not much good for me. The default value of
;; desktop-path puts "." (working directory) before "~". This reduces it
;; strictly to my home directory.
(setq desktop-path (list (expand-file-name "~")))

;; Likewise save various kinds of minibuffer history
(savehist-mode t)

;;; *** Intransient Buffers

(setq desktop-files-not-to-save
      ;; desktop-files-not-to-save will become a regexp consisting of a shy
      ;; group with more elements in it, of course separated by "\\|". These
      ;; groups are to be defined in the `let' stanza above.
      (concat "\\(?:"
              (mapconcat (lambda (x) x) ;; Fixed-point, if you will
                         '("\\(?:^/mnt\\)")
                         "\\|")
              "\\)"))

;;; ** Encoding

;; Just in case, make sure we can use multibyte characters
(setq-default enable-multibyte-characters t)

;;; *** Prefer UTF-8

;; prefer-coding-system configures a number of options according to the
;; argument given to it. In this case, defaults such as the encoding for new
;; files and subprocess I/O should be Unicode UTF-8. I am personally not clear
;; on /all/ the details. :D
(prefer-coding-system 'mule-utf-8)

;;; ** Emacs Faces

;; Global Font Lock Mode, yay!
(global-font-lock-mode t)

;;; *** Default Face

;; I'll probably elaborate on the other faces and pimp everything out, but for
;; now, the grey toolbars 'n shit are OK
(eval `(set-face-attribute
        'default nil
        :family "fixed"
        ;; If running in a graphical windowing system, the :weight is
        ;; 'normal; otherwise, set 'bold for terminal (which increases the
        ;; brightness nicely).
        :weight (if window-system 'normal 'bold)
        ;; I have a custom rgb.txt...
        :foreground (if window-system "HotLaoGirl" "yellow")
        ;; Transparent in console
        ,@(if window-system '(:background "black"))
        :height 160))

;; Cursor configuration
(setq-default cursor-type 'bar)

;;; *** Font Scaling

;; What's the worst that could happen? A shitty typeface?
(setq scalable-fonts-allowed t)

;; For some reason, the CDAC fonts, which cover an array of Indic scripts have
;; small sizes at what should be 16 pts. This scales them up nicely.
(setq face-font-rescale-alist '(("-cdac$" . 1.5)
                                ("tis620" . 1.075)))

;; I downloaded Phaisarn Techajuwarong's fixed fonts collection and tried to
;; incorporate a rule for scaling into face-font-rescale-alist, but it didn't
;; work. However, I found it more effective just to alter the default fontset
;; like so, explicitly using the 18 point font for character set 'thai-tis620.
(set-fontset-font
 nil 'thai-tis620
 "-phaisarn-angsana-medium-r-normal--18-180-75-75-p-75-tis620.2533-0")

;;; * Natural Text Editing
;;; ** Text Mode

;; Default major mode is Text Mode
(setq default-major-mode 'text-mode)

;; Turn on Auto Fill Mode along with Text Mode
(add-hook 'text-mode-hook 'turn-on-auto-fill)

;;; ** Outline Mode
;;; *** Re-assign C-o

;; Move open-line to C-o o. There are a couple ways the keystrokes can
;; represented, but the `kbd' macro does all the work for you:
(global-unset-key (kbd "C-o"))
(global-set-key (kbd "C-o o") 'open-line)

;; Set the minor mode prefix to C-o
(setq outline-minor-mode-prefix (kbd "C-o"))

;;; *** Outline Header Recognition

;; The value of outline-regexp will vary according to the major mode. (The
;; regexp in the cdr of each cons in mode-details must contain at least one
;; submatch, whose length is used to calculate the depth of the heading.)
(dolist (mode-details '((emacs-lisp . ";;; \\(\\*+\\)")
                        (cperl . "### \\(\\*+\\)")))
  (add-hook
   ;; The hook itself: the symbol comprised of the name represented in
   ;; the car of `mode-details' prepended to "-mode-hook".
   (intern (concat (symbol-name (car mode-details)) "-mode-hook"))
   `(lambda () ;; The lambda function which sets `outline-regexp'
      (make-local-variable 'outline-regexp)
      (make-local-variable 'outline-level)
      (setq outline-regexp ,(cdr mode-details))
      (setq outline-level (lambda () (length (match-string 1)))))))

;;; ** AUCTeX Mode

;; AUCTeX does autoload properly after all. Thanks to Herr Giftpilz for his
;; gracious notification of poor form in my .emacs. I must never forget my
;; sacred duty to maintain the utmost vigilance during those pre-dawn hacking
;; sessions, lest I corrupt the mind of an innocent acolyte.
(load "auctex") ;; Forsooth

;; AUCTeX has this bad-ass toolbar as well. I'm usually more oriented towards
;; keystrokes, but they sure sold me on this:
(add-hook 'LaTeX-mode-hook 'LaTeX-install-toolbar)

;;; *** AUCTeX Customization

;; These were suggested by the AUCTeX info manual, and I thought they made
;; sense, so I added them:
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)

;;; ** Sentence Parsing

;; This influences the behavior of various commands within Emacs
(setq sentence-end-double-space nil)

;; Most of this otherwise comes from the default value returned by
;; (sentence-end), with sentence-end-double-space set to nil. I have, however,
;; made the important addition of the Devanagari sentence delimiter, ।
;; 
;; I should also set up conditions and shit to deal with Thai text, whose
;; sentences are delimited with whitespace only, but I'm just not that heavily
;; into it yet.
(setq sentence-end "[.?!।][]\"'””)}]*\\(?:$\\|[\t ]\\)[\t\n ]*")

;;; ** Spell Checking

;; I don't have ispell; I have aspell
(setq ispell-program-name "aspell")

;; Use my own dictionary for spelling. (Explain how I made it?)
(setq ispell-alternate-dictionary (expand-file-name "~/.emacs.d/big-dict"))

;;; ** Indentation And Filling

;; Set a default of 78 for `fill-column' (for this also is a buffer-local
;; variable). Think of the collective screen real-estate you would be losing
;; over time!
(setq-default fill-column 78)

;;; *** Eliminate Hard Tabs 

;; Insert spaces instead of tabs for indentation, unless there is an
;; overriding buffer-local binding.
(setq-default indent-tabs-mode nil)

;; Grrr, I just found out Emacs Lisp mode clobbers this!
(add-hook 'emacs-lisp-mode-hook (lambda () (setq indent-tabs-mode nil)))

;;; *** Tab Stop List

;; I do not wish to interfere with the default setting of tab-width, as it
;; will break compatibility with many documents that expect it to be 8. I
;; *do*, however, wish to use tab stops of 2, in spaces, for my *own*
;; documents. (TabsAreEvil.)
(setq tab-stop-list '(2 4 6 8 10 12 14 16 18 20))

;;; * Programming Support
;;; ** Tags Support

;; Add the main tags file for my Perl projects in CPerl mode buffers.
(dolist (source-type '((cperl-mode-hook . "perl")))
  (add-hook (car source-type) ;; The mode in which to enable tags support
            `(lambda ()
             (make-local-variable 'tags-file-name)
             ;; This is done in advance for project-name
             (hack-local-variables)
             ;; If there be a value for `project-name', it becomes the current
             ;; tag file in the directory ~/.emacs.d/tags/perl.
             (if (boundp 'project-name)
                 (setq tags-file-name 
                       (concat "~/.emacs.d/tags/" ,(cdr source-type) "/"
                               (symbol-name project-name)))))))
;;; ** CPerl Mode

;; Supplant the default perl-mode the dirty way with fset
(fset 'perl-mode 'cperl-mode)

;;; *** CPerl Variables

;; Here's a long list of settings for CPerl mode, which I would rather
;; configure the Hanumizzle way and use `cperl-hairy', but it overrides
;; cperl-clobber-lisp-bindings. :evil:

;; Because I 'clobber' the mode-lists myself (prefer to do it this way), this
;; is redundant
(setq cperl-clobber-mode-lists nil)

;; Enable 'electricity' in generating natural pairs, expanding keywords,
;; newlines, and also spacing between '$' and '{'
(setq cperl-electric-parens t
      cperl-electric-keywords t
      cperl-electric-linefeed t
      cperl-electric-lbrace-space t)

;; Automatically show help in the minibuffer for the element at point after a
;; certain timeout, namely 5 seconds
(setq cperl-lazy-help-time 5)

;; Don't underline trailing whitespace
(setq cperl-invalid-face nil)

;; Automagically insert newlines where appropriate (e.g., after colons and
;; braces)
(setq cperl-auto-newline t)

;; Sets defined by natural pairs (parentheses, braces, and curly braces) will
;; be indented as blocks.
(setq cperl-indent-parens-as-block t)

;; In lines where a right parenthesis closes a parenthesis in a previous line
;; (of the same multi-line statement), cperl-close-paren-offset is the offset
;; for indent. By default it is -1, but I would rather it were the opposite of
;; cperl-indent-level, which, in effect, brings the parenthesis flush with the
;; previous tab stop.
;;
;; The only problem is that I need to explicitly set cperl-indent-level
;; because it does not autoload. That's OK, just make it the same as the
;; default (which I prefer anyway).
(setq cperl-indent-level 2
      cperl-close-paren-offset (- cperl-indent-level))

;;; ** Lisp Modes

;; Emacs Lisp is not an exception to my setting for fill-column. Setting
;; emacs-lisp-docstring-fill-column to nil (or any other non-integer value)
;; makes it adhere to a uniform standard.
(setq emacs-lisp-docstring-fill-column nil)

;; Comments should always begin with double semicolons
(dolist (mode '(emacs-lisp-mode-hook lisp-mode-hook))
  (add-hook mode (lambda ()
                   (make-local-variable 'comment-start)
                   (setq comment-start ";; "))))

;; I am actually not going to mess with the default indentation for Lisp (as
;; of now). I don't understand what the variables do and it looks nice anyway.

;;; *** quack.el

(setq quack-default-program "gosh"
      quack-pretty-lambda-p t
      quack-programs '("gosh" "guile" "mzscheme" "mzscheme -M errortrace"))

;;; *** SLIME

;; Will be using SBCL 0.9.x, at least until I can get GNU Clisp to play nice
;; with the libraries I want to use (e.g., McCLIM).
(setenv "SBCL_HOME" "/usr/lib/sbcl") ;; Non-standard location of SBCL_HOME
(setq inferior-lisp-program "/usr/bin/sbcl")

;; SLIME does not seem to furnish any autoload cookies of its own. That's OK,
;; I'll make one instead.
(autoload 'slime "slime"
  "Start an inferior^_superior Lisp and connect to its Swank server."
  t)

;; Run `slime-setup' before M-x slime loads
(defadvice slime (before slime-setup-run)
  "Run `slime-setup' before executing autoloaded definition of `slime'."
  (slime-setup))

;;; ** Sh Mode

;; I standardized on an indent of 2 a long time ago and I'm 'set in my ways'
(setq sh-indentation 2 
      sh-basic-offset 2)

;;; ** Ruby Mode

;; Add a glob in auto-mode-alist for loading Ruby mode. The mode will be
;; associated with all *.rb files; likewise .irbrc
(setq auto-mode-alist (cons '("\\(?:\\.irbrc\\|\\.rb\\)$" . ruby-mode)
                            auto-mode-alist))

;; *** inf-ruby.el -- Inferior Ruby Mode

;; inf-ruby.el decided to be retarded and didn't furnish its own autoload
;; cookies
(autoload 'run-ruby "inf-ruby" 
  "Run an inferior Ruby process" t)
(autoload 'inf-ruby-keys "inf-ruby" 
  "Set local key defs for inf-ruby in ruby-mode" t)

;;; ** CC Mode

(setq c-basic-offset 2) ;; The default indent of 4 spaces is obnoxious

;;; ** JDEE

;; Invoke the autoloads file for JDEE; this apparently includes jde-mode in
;; auto-mode-alist!
(load "jde-autoload")

;; ...because I want it done automagically. (CEDET furnishes a bunch of
;; utilities and libraries for program development.)
(defadvice jde-mode (before jde-load-cedet)
  "Load CEDET utilities before invocation of `jde-mode'."
  (load "cedet"))

;;; *** JDEE Variables

(setq jde-enable-abbrev-mode t ;; Enable expansion of constructs like `ife'
      bsh-jar "/opt/java/lib/bsh-2.0b4.jar") ;; Location of BeanShell jar

;;; * Other
;;; ** EMMS

;; Require all the basic modules
(dolist (module '(emms-source-file
                  emms-source-playlist
                  emms-player-simple
                  emms-player-mplayer
                  emms-playlist-mode
                  emms-info
                  emms-info-mp3info
                  emms-info-ogginfo
                  emms-mode-line))
  (require module))

;; Now set up some basic player support. I haven't got MPD to work yet, so
;; other local programs will have to do in the mean time.
(setq emms-player-list '(emms-player-ogg123
                         emms-player-mpg321
                         emms-player-mplayer))

;; Set a few important options 
(setq emms-show-format "Now playing: %s" ;; "Currently playing" is too verbose
      emms-repeat-playlist t ;; I want music non-stop, dammit!
      emms-playlist-default-major-mode 'emms-playlist-mode) ;; Duh?

;; Randomize track selection
(remove-hook 'emms-player-finished-hook 'emms-next-noerror)
(add-hook 'emms-player-finished-hook 'emms-random)

;; Show 'Now playing ...' message at the beginning of each track
(add-hook 'emms-player-started-hook 'emms-show)

;; Register track information -- ripped off wholesale from emms-setup.el
(add-to-list 'emms-track-initialize-functions 'emms-info-initialize-track)
(add-to-list 'emms-info-functions 'emms-info-mp3info)
(add-to-list 'emms-info-functions 'emms-info-ogginfo)
(setq emms-track-description-function 'emms-info-track-description)

;; Add track info to the mode line -- this is pure rice
;; (emms-mode-line 1) ;; Took up too much space

;;; ** Wheel Mouse

;; My mouse is one of those vagiC-<DelBack>wheel mice, and I should like to
;; take advantage of its functionality

;; Enable teh mouse wheel
(mouse-wheel-mode t)

;; Mouse wheel scrolls buffer under pointer; this is useful for examining a
;; help buffer or something
(setq mouse-wheel-follow-mouse t)

;;; ** Disable CUA Keybindings

;; CUA keybindings is fo' n00bz, f00l!
(dolist (key (mapcar (lambda (raw) (eval `(kbd ,raw)))
                     '("<up>" "<down>" "<left>" "<right>"
                       "C-<left>" "C-<right>"
                       "<next>" "<prior>"
                       "<home>" "<end>")))
  (global-unset-key key))

;;; ** Miscellaneous

;; Files without terminating newlines really annoy me
(setq require-final-newline t)

;; Enable show-paren-mode, which kicks ass. This is chiefly useful for LISP
;; programming, obviously, but also applies to various other programming
;; modes.
(show-paren-mode t)

;; Start a single Emacs server; it's good enough for now
(server-start)

;; Truncate lines that don't fit in the buffer, rather than wrapping
(setq-default truncate-lines t) 

;; Turn on interpretation of ANSI color sequences in all comint-derived modes
(add-hook 'comint-mode-hook (lambda () (ansi-color-for-comint-mode-on)))

;; Do not scroll dramatically when moving one line at a time!
(setq-default scroll-conservatively 1)

;;; ** TODO

;; Replace C-e with C-e e; a prefix keymap for macros 'n shit will
;; supplant the default binding for C-e. Or, perhaps, make use of the arrow,
;; function, and numerical keypad characters that never seem to get used
;; around here.
;;
;; Also interesting is the idea of using a distinct frame for all my
;; emacsclient operations
