My .emacs file is a collection of hacks, both stolen from the internet and
written myself.
In addition to my .emacs file, you may also be interested in my quasi-project system, find-things-fast , which provides git accelerated find-file-in-project
and grepsource
commands (with reasonable fallbacks in non-git controlled repositories).
In case you’re into RealLive hacking, I also wrote rldev-el , which is a few very simple major-modes for working with rldev disassembled files.
Below is the file syntax highlighted; if you want a raw text version, click here .
;; -----------------------------------------------------------------------
;; Elliot's .emacs file
;; -----------------------------------------------------------------------
;; This file is divided into the five groups that configure emacs:
;;
;; I) A prelude which sets up the package system and installs use-package.
;; II) A list of use-package statements.
;; III) A list of things which should be factored out into packages.
;; IV) A list mode hooks.
;; V) Customize.
;; -----------------------------------------------------------------------
;; I) Prelude (Configuration for Configuration)
;; -----------------------------------------------------------------------
;;
;; The first thing we do is set up the package system and then ensure that
;; use-package is installed and set up. We do this before anything else,
;; including loading per-operating system/per-machine configuration so we can
;; make use of the packaging system in them.
;;
;; ------------------------------------- [ Initialize the package system ]
( setq package-archives ' (( "melpa" . "http://melpa.milkbox.net/packages/" )
( "gnu" . "http://elpa.gnu.org/packages/" )))
( package-initialize nil )
;; In Emacs 25.1, use `package-install-selected-packages'.
;; ------------------------------------------- [ Bootstrap `use-package' ]
;; This ensures `use-package' is installed.
( unless ( package-installed-p 'use-package )
( package-refresh-contents )
( package-install 'use-package ))
;; Ensures that we have the features `use-package' requires:
( eval-when-compile
( require 'use-package ))
( require 'diminish )
( require 'bind-key )
;; ----------------------------------------------- [ Top Level Load Path ]
( add-to-list 'load-path ( expand-file-name "~/.elliot-unix/emacs/site-lisp" ))
;; ------------------------------------------------- [ Load private data ]
( load "~/.elliot-unix/emacs/private-details" )
;; ----------------------------------------- [ Whether we're using Apple ]
( if ( string-match "apple" system-configuration )
( load-file ( expand-file-name "~/.elliot-unix/System/Darwin/emacs" ))
;; If we're not on OSX, hide the menu.
( menu-bar-mode -1 ))
;; --------------------------------------- [ Local machine configuration ]
;; This loads configuration for this specific machine or network that
;; isn't put in the git repository.
( let (( conf-file ( expand-file-name "~/.elliot-unix/local/emacs" )))
( if ( file-exists-p conf-file )
( load-file conf-file )))
;; -----------------------------------------------------------------------
;; II) Packages Used
;; -----------------------------------------------------------------------
;;
;; Loads and configures all the packages that I could use.
;;
;; ------------------------------------------------------------ [ abbrev ]
( use-package abbrev
:diminish abbrev-mode )
;; -------------------------------------------------- [ browse-kill-ring ]
( use-package browse-kill-ring
:bind (( "C-c k" . browse-kill-ring ))
:config
( setq browse-kill-ring-show-preview nil ))
;; ------------------------------------------------- [ comment-separator ]
( use-package comment-separator
:bind (( "C-c s s" . separator-insert-line )
( "C-c s h" . separator-insert-header-section )
( "C-c s b" . separator-insert-header-big ))
:commands ( separator-insert-line
separator-insert-header-section
separator-insert-header-big )
:init ( setq cs-fill-column 73 )
;; Personal package not in elpa
:load-path "site-lisp/" )
;; ----------------------------------------------------------- [ company ]
( use-package company
:commands ( my-indent-or-complete )
:bind ( "TAB" . my-indent-or-complete )
:diminish ""
:config
( setq company-backends
' ( company-bbdb company-nxml company-css company-eclim
company-semantic company-xcode company-cmake
company-capf
( company-dabbrev-code company-gtags company-etags
company-keywords )
company-oddmuse company-files company-dabbrev ))
( global-company-mode )
( setq company-dabbrev-downcase nil
company-dabbrev-ignore-case nil )
( defun my-indent-or-complete ()
( interactive )
( if ( looking-at "\\_>" )
( company-complete-common )
( indent-according-to-mode ))))
;; ------------------------------------------------------ [ dummy-h-mode ]
( use-package dummy-h-mode
:mode ( "\\.h$" . dummy-h-mode )
:config ( setq dummy-h-mode-default-major-mode 'c++-mode ))
;; --------------------------------------------------------- [ echo-bell ]
( use-package echo-bell
:defer t
:config
( progn
( setq echo-bell-string "ding"
echo-keystrokes 2 )
( echo-bell-mode t )))
;; -------------------------------------------------------------- [ emms ]
( use-package emms
:commands ( emms-streams )
:config
( progn
( setq emms-playlist-buffer-name "*Music*"
emms-stream-bookmarks-file "~/.elliot-unix/emacs/emms-streams"
emms-stream-default-action "play" )
( emms-standard )
( emms-default-players )
( require 'emms-streams )
( define-key emms-stream-mode-map ( kbd "s" ) 'emms-stop )
( require 'emms-playing-time )
( emms-playing-time 1 )))
;; --------------------------------------------------------------- [ erc ]
( use-package erc
:commands ( erc )
:config
( progn
( setq erc-button-buttonize-nicks nil
erc-format-nick-function 'erc-format-@nick
erc-hide-list ' ( "JOIN" "PART" "QUIT" )
erc-interpret-mirc-color t
erc-modules ' ( autojoin button completion fill irccontrols list
match menu move-to-prompt netsplit networks
noncommands readonly ring scrolltobottom
services stamp spelling track )
erc-nick-uniquifier "_"
erc-prompt-for-nickserv-password nil
erc-track-exclude-types ' ( "JOIN" "NICK" "PART" "QUIT" "MODE" "324"
"329" "332" "333" "353" "477" )
erc-track-position-in-mode-line ( quote after-modes ))
;; Let's not worry about accidentally spamming channels; disable middle
;; mouse yank.
( defun erc-disabled-mouse-yank ()
( interactive )
( message "Mouse yank disabled in ERC buffers to avoid spam. Use C-y." ))
( define-key erc-mode-map [mouse-2] 'erc-disabled-mouse-yank )
( define-key erc-mode-map [M-mouse-2] 'erc-disabled-mouse-yank )
;; Lots of default messages say the whole hostname of a user. Instead,
;; use short forms.
( erc-define-catalog-entry 'english 'JOIN
"%n has joined channel %c" )
( erc-define-catalog-entry 'english 'NICK
"%n is now known as %N" )
( erc-define-catalog-entry 'english 'MODE
"%n has change mode for %t to %m" )
( erc-define-catalog-entry 'english 'QUIT
"%n has quit: %r" )
( erc-define-catalog-entry 'english 'TOPIC
"%n has set the topic for %c: \"%T\"" )
;; TODO(erg): Use the following to make an automated kickban command.
( defadvice erc-cmd-IGNORE ( after ignore-replys-to ( &optional user ) activate )
"After every ignore, copy the list `erc-ignore-list' to
`erc-ignore-reply-list'. When I ignore someone, I want them *gone*."
( erc-with-server-buffer ( setq erc-ignore-reply-list erc-ignore-list )))
( defadvice erc-cmd-UNIGNORE ( after ignore-replys-to ( &optional user )
activate )
"In case of mistakes made with /ignore."
( erc-with-server-buffer ( setq erc-ignore-reply-list erc-ignore-list )))
( defun erc-cmd-OPME ()
"tell chanserv to op me (from: http://paste.lisp.org/display/97466)"
( interactive )
( erc-message "PRIVMSG"
( format "chanserv op %s %s"
( erc-default-target )
( erc-current-nick )) nil ))
( defun erc-cmd-DEOPME ()
"deop myself (from: http://paste.lisp.org/display/97466)"
( interactive )
( erc-cmd-DEOP ( format "%s" ( erc-current-nick ))))))
;; -------------------------------------------------- [ find-things-fast ]
( use-package find-things-fast
:bind (( "<f1>" . ftf-find-file )
( "<f2>" . ftf-grepsource )
( "<f4>" . ftf-gdb )
( "<f5>" . ftf-compile ))
:config
( setq ftf-filetypes
' ( "*.dart" "*.tmpl" "*.js" "*.gni" "*.gn" "*.mojom" "*.h" "*.hpp"
"*.cpp" "*.c" "*.cc" "*.cpp" "*.inl" "*.grd" "*.idl" "*.m" "*.mm"
"*.py" "*.sh" "*.cfg" "*SConscript" "SConscript*" "*.scons"
"*.vcproj" "*.vsprops" "*.make" "*.gyp" "*.gypi" "*.el" "*.md" )))
;; ---------------------------------------------------------- [ flyspell ]
( use-package flyspell
;; Carry our personal dictionary around in our dotfiles repository.
:diminish flyspell-mode
:init
( progn
( add-hook 'text-mode-hook 'flyspell-mode )
( add-hook 'prog-mode-hook 'flyspell-prog-mode ))
:config
( setq ispell-extra-args ' ( "--sug-mode=bad-spellers" )
ispell-personal-dictionary "~/.elliot-unix/emacs/aspell.en.pws" ))
;; --------------------------------------------------- [ git-commit-mode ]
( use-package git-commit
:init ( global-git-commit-mode )
:config ( setq git-commit-summary-max-length 72 ))
;; ---------------------------------------------------- [ gitconfig-mode ]
( use-package gitconfig-mode
:mode "gitconfig\\'" )
;; ----------------------------------------------------------- [ gn-mode ]
( if ( file-exists-p "/work/chrome/src/tools/gn/misc/emacs/gn-mode.el" )
( use-package gn-mode
:mode "\\.gn\\'"
:load-path "/work/chrome/src/tools/gn/misc/emacs/" ))
;; ---------------------------------------------------------- [ gyp-mode ]
( if ( file-exists-p "/work/chrome/src/tools/gyp/tools/emacs/gyp.el" )
( use-package gyp
:mode ( "\\.gypi?\\'" . gyp-mode )
:load-path "/work/chrome/src/tools/gyp/tools/emacs/" ))
;; ----------------------------------------------------------- [ ibuffer ]
( use-package ibuffer
:bind (( "C-x C-b" . ibuffer ))
:config
( setq ibuffer-show-empty-filter-groups nil )
( setq ibuffer-saved-filter-groups
' (( "default"
( "version control" ( or ( mode . svn-status-mode )
( mode . svn-log-edit-mode )
( name . "^\\*Annotate" )
( name . "^\\*git-" )
( name . "^\\*magit:" )
( name . "^\\*magit-" )
( name . "^\\*svn-" )
( name . "^\\*vc-" )
( name . "^\\*vc\\*$" )))
( "emacs" ( or ( name . "^\\*scratch\\*$" )
( name . "^\\*Messages\\*$" )
( name . "^\\*ELP Profiling Results\\*$" )
( name . "^TAGS\\(<[0-9]+>\\)?$" )
( name . "^\\*Help\\*$" )
( name . "^\\*info\\*$" )
( name . "^\\*Occur\\*$" )
( name . "^\\*grep\\*$" )
( name . "^\\*Apropos\\*$" )
( name . "^\\*Compile-Log\\*$" )
( name . "^\\*Backtrace\\*$" )
( name . "^\\*Packages\\*$" )
( name . "^\\*Process List\\*$" )
( name . "^\\*gud\\*$" )
( name . "^\\*Man" )
( name . "^\\*WoMan" )
( name . "^\\*Kill Ring\\*$" )
( name . "^\\*Completions\\*$" )
( name . "^\\*tramp" )
( name . "^\\*shell\\*$" )
( mode . term-mode )
( name . "^\\*compilation\\*$" )
( mode . Custom-mode )))
( "EMMS" ( or ( name . "^\\*Music\\*$" )
( name . "^\\*EMMS" )
( mode . emms-browser-mode )))
( "IRC" ( or ( name . "^\\*Finger" )
( mode . erc-mode )))
( "emacs source" ( or ( mode . emacs-lisp-mode )
( filename . "\\.el\\.gz$" )))
( "agenda" ( or ( name . "^\\*Calendar\\*$" )
( name . "^diary$" )
( name . "^\\*Agenda" )
( name . "^\\*org-" )
( name . "^\\*Org" )
( mode . org-mode )
( mode . muse-mode )))
( "latex" ( or ( mode . latex-mode )
( mode . LaTeX-mode )
( mode . bibtex-mode )
( mode . reftex-mode )))
( "dired" ( or ( mode . dired-mode ))))))
( add-hook 'ibuffer-mode-hook
( lambda ()
( ibuffer-switch-to-saved-filter-groups "default" )))
;; Order the groups so the order is : [Default], [agenda], [emacs]
( defadvice ibuffer-generate-filter-groups ( after reverse-ibuffer-groups ()
activate )
( setq ad-return-value ( nreverse ad-return-value ))))
;; --------------------------------------------------------------- [ ido ]
( use-package ido
:config
( ido-mode t )
( setq ido-auto-merge-work-directories-length -1
ido-default-buffer-method 'selected-window
ido-default-file-method 'selected-window
ido-enable-flex-matching t ))
;; ---------------------------------------------------------- [ js2-mode ]
( use-package js2-mode
:mode "\\.js$"
:config ( setq js2-basic-offset 2 ))
;; ------------------------------------------------------- [ kepago-mode ]
( use-package kepago-mode
;; Publicly available at https://github.com/eglaysher/rldev-el
:mode "\\.ke$"
:load-path "site-lisp/" )
;; ---------------------------------------------------------- [ kfn-mode ]
( use-package kfn-mode
;; Publicly available at https://github.com/eglaysher/rldev-el
:mode "\\.kfn$"
:load-path "site-lisp/" )
;; ------------------------------------------------------------- [ magit ]
( use-package magit
:commands magit-get-top-dir
:bind (( "C-c g" . magit-status )
( "C-c C-g l" . magit-log-buffer-file )
( "C-c f" . magit-grep ))
:config ( magit-auto-revert-mode ))
;; ----------------------------------------------------- [ markdown-mode ]
( use-package markdown-mode
:mode ( "\\.\\(m\\(ark\\)?down\\|md\\)$" . markdown-mode )
:config ( add-hook 'markdown-mode-hook 'visual-line-mode ))
;; ---------------------------------------------------------- [ midnight ]
( use-package midnight
:defer 5
:config
( setq clean-buffer-list-kill-buffer-names
' ( "*Annotate " "*Help*" "*Apropos*" "*Buffer List*" "*Compile-Log*"
"*info*" "*vc*" "*vc-diff*" "*diff*" ))
( setq clean-buffer-list-kill-never-buffer-names
' ( "#mojo" "#chromium" "emacs" "*scratch*" "*Messages*" )))
;; --------------------------------------------------------------- [ org ]
( use-package org
:bind (( "C-c a" . org-agenda )
( "C-c l" . org-store-link )
( "C-c o" . org-jump-to-project-todo ))
:init
( progn
( defvar my-org-project-name "" )
( put 'my-org-project-name 'safe-local-variable #' stringp ))
:config
( progn
( setq org-agenda-files ' ( "~/org/" )
org-hide-leading-stars t
org-log-done 'time
org-odd-levels-only t )
( defun org-jump-to-project-todo ()
( interactive )
( cond (( not ( string= "" my-org-project-name ))
( find-file-other-window
( expand-file-name ( concat "~/org/" my-org-project-name ".org" ))))
( t ( message ( concat "No project set! Set `my-org-project-name' in "
"dir-locals.el to enable this." )))))))
;; --------------------------------------------------------- [ powerline ]
( use-package powerline
:ensure t
:config
( setq powerline-default-separator 'contour
powerline-display-buffer-size nil
powerline-display-hud nil
powerline-display-mule-info nil )
;; Use 'LIGHT SHADE' (U+2591) which should be in unpatched fonts.
( setq powerline-utf-8-separator-left 9618
powerline-utf-8-separator-right 9618 )
( setq-default mode-line-format
' ( "%e"
( :eval
( let* (( active ( powerline-selected-window-active ))
( mode-line ( if active 'mode-line 'mode-line-inactive ))
( face1 ( if active 'powerline-active1 'powerline-inactive1 ))
( face2 ( if active 'powerline-active2 'powerline-inactive2 ))
( separator-left ( intern ( format "powerline-%s-%s"
( powerline-current-separator )
( car powerline-default-separator-dir ))))
( separator-right ( intern ( format "powerline-%s-%s"
( powerline-current-separator )
( cdr powerline-default-separator-dir ))))
( lhs ( list ( powerline-raw "%*" nil )
( powerline-raw
( if ( window-dedicated-p ) "@" " " ) nil )
( powerline-buffer-id nil 'l )
( powerline-raw " " )
( funcall separator-left mode-line face1 )
( powerline-major-mode face1 'l )
( powerline-process face1 )
( powerline-minor-modes face1 'l )
( powerline-narrow face1 'l )
( powerline-raw " " face1 )
( funcall separator-left face1 face2 )
( powerline-vc face2 'r )
( when ( bound-and-true-p nyan-mode )
( powerline-raw ( list ( nyan-create )) face2 'l ))))
( rhs ( list ( funcall separator-right face2 face1 )
;; TODO(erg): Add long running crud here.
( powerline-raw global-mode-string face1 'r )
( unless window-system
( powerline-raw ( char-to-string #xe0a1 ) face1 'l ))
( when ( and ( boundp 'erc-track-minor-mode ) erc-track-minor-mode )
( powerline-raw erc-modified-channels-object face1 'l ))
( powerline-raw " " face1 )
( funcall separator-right face1 mode-line )
( powerline-raw " (%03l," nil )
( propertize "%02c" 'face
( if ( >= ( current-column ) 80 )
'error
nil ))
( powerline-raw ")" nil 'r )
( when powerline-display-hud
( powerline-hud face2 face1 )))))
( concat ( powerline-render lhs )
( powerline-fill face2 ( powerline-width rhs ))
( powerline-render rhs )))))))
;; ----------------------------------------- [ pager-default-keybindings ]
( require 'pager-default-keybindings )
;; ---------------------------------------------------- [ sticky-windows ]
( use-package sticky-windows
:bind (( "C-x 0" . sticky-window-delete-window )
( "C-x 1" . sticky-window-delete-other-windows )
( "C-x 9" . sticky-window-keep-window-visible ))
:load-path "site-lisp/" )
;; ---------------------------------------------------------- [ uniquify ]
( use-package uniquify
;; Use angle brackets in buffer names (ie "BUILD.gn<chrome>")
:config ( setq uniquify-buffer-name-style 'post-forward-angle-brackets ))
;; --------------------------------------------------------- [ yasnippet ]
( use-package yasnippet
:diminish yas-minor-mode
:defer 1
:init
( progn
( setq yas-indent-line 'fixed
yas-snippet-dirs ' ( "~/.elliot-unix/emacs/snippets" ))
( yas-global-mode )))
;; --------------------------------------------------------------- [ yow ]
( use-package yow
;; Tradition: It is important to remember from where we came. As people,
;; we sometimes do things for no other reason but to assert that we are
;; part of a tribe. Have some blatant group affiliation signaling.
:commands ( yow )
:load-path "site-lisp/"
:config ( setq yow-file "~/.elliot-unix/emacs/yow.lines" ))
;; -----------------------------------------------------------------------
;; III) Things to Refactor
;; -----------------------------------------------------------------------
;;
;; This section contains snippets that really should be turned into packages
;; and then stuffed in the above.
;;
;; --------------------------------------------------------- [ find-file ]
;; This should be the same as the default value of `cc-other-file-alist' except
;; for the addition of Objective-C ".m" and ".mm" files.
( setq cc-other-file-alist
' (( "\\.cc\\'" ( ".h" ".hh" ))
( "\\.hh\\'" ( ".cc" ".C" ))
( "\\.c\\'" ( ".h" ))
( "\\.h\\'" ( ".cc" ".c" ".C" ".CC" ".cxx" ".cpp" ".m" ".mm" ))
( "\\.m\\'" ( ".h" ))
( "\\.mm\\'" ( ".h" ))
( "\\.C\\'" ( ".H" ".hh" ".h" ))
( "\\.H\\'" ( ".C" ".CC" ))
( "\\.CC\\'" ( ".HH" ".H" ".hh" ".h" ))
( "\\.HH\\'" ( ".CC" ))
( "\\.c\\+\\+\\'" ( ".h++" ".hh" ".h" ))
( "\\.h\\+\\+\\'" ( ".c++" ))
( "\\.cpp\\'" ( ".hpp" ".hh" ".h" ))
( "\\.hpp\\'" ( ".cpp" ))
( "\\.cxx\\'" ( ".hxx" ".hh" ".h" ))
( "\\.hxx\\'" ( ".cxx" ))))
;; ---------------------------------------------------- [ Helper methods ]
( defun intelligent-close ()
"quit a frame the same way no matter what kind of frame you are on.
This method, when bound to C-x C-c, allows you to close an emacs frame the
same way, whether it's the sole window you have open, or whether it's
a \"child\" frame of a \"parent\" frame. If you're like me, and use emacs in
a windowing environment, you probably have lots of frames open at any given
time. Well, it's a pain to remember to do Ctrl-x 5 0 to dispose of a child
frame, and to remember to do C-x C-x to close the main frame (and if you're
not careful, doing so will take all the child frames away with it). This
is my solution to that: an intelligent close-frame operation that works in
all cases (even in an emacs -nw session).
Stolen from http://www.dotemacs.de/dotfiles/BenjaminRutt.emacs.html."
( interactive )
( if ( eq ( car ( visible-frame-list )) ( selected-frame ))
;;for parent/master frame...
( if ( > ( length ( visible-frame-list )) 1 )
;;close a parent with children present
( delete-frame ( selected-frame ))
;;close a parent with no children present
( save-buffers-kill-emacs ))
;;close a child frame
( delete-frame ( selected-frame ))))
( defun diary-entry ( filename )
"Creates a new jekyll post in the diary directory."
( interactive "MEntry name: " )
( if ( not ( boundp 'erg-diary-directory ))
( error "`erg-diary-directory' is not set." ))
( let (( path ( concat erg-diary-directory
"_posts/"
( format-time-string "%Y-%m-%d" ) "-"
( downcase ( replace-regexp-in-string " " "-" filename ))
".md" )))
( switch-to-buffer ( find-file-noselect path ))))
( defun visit-ansi-term ()
"If the current buffer is:
1) a running ansi-term named *ansi-term*, rename it.
2) a stopped ansi-term, kill it and create a new one.
3) a non ansi-term, go to an already running ansi-term
or start a new one while killing a defunt one.
TODO: Switch around exactly what DWIM. It should switch to an
existing buffer in the current frame if it exists.
Stolenated from: www.enigmacurry.com/2008/12/26/emacs-ansi-term-tricks/"
( interactive )
( require 'term )
( with-ftf-project-root
( let (( is-term ( string= "term-mode" major-mode ))
( is-running ( term-check-proc ( buffer-name )))
( term-cmd "/bin/bash" )
( anon-term ( get-buffer "*ansi-term*" )))
( if is-term
( if is-running
( if ( string= "*ansi-term*" ( buffer-name ))
( call-interactively 'rename-buffer )
( if anon-term
( switch-to-buffer "*ansi-term*" )
( ansi-term term-cmd )))
( kill-buffer ( buffer-name ))
( ansi-term term-cmd ))
( if anon-term
( if ( term-check-proc "*ansi-term*" )
( switch-to-buffer "*ansi-term*" )
( kill-buffer "*ansi-term*" )
( ansi-term term-cmd ))
( ansi-term term-cmd ))))))
;; ------------------------------------------- [ my-start-scripting-mode ]
( defun my-start-scripting-mode ( file-extension hash-bang )
;; Build a startup template for this mode.
( require 'tempo )
( tempo-define-template ( concat file-extension "startup" )
( list ( concat hash-bang "\n\n" )))
( push ( cons ( concat "\\." file-extension "$" )
( intern ( concat "tempo-template-" file-extension "startup" )))
auto-insert-alist )
;; Make the script executable on save
( add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p
nil t ))
;; ---------------------------------------------- [ Personal Keybindings ]
( bind-key "<f3>" 'visit-ansi-term )
( bind-key "C-c d" 'diary-entry )
( bind-key "C-x C-c" 'intelligent-close )
( bind-key "M-g c" 'goto-char )
( bind-key "S-<end>" ' ( lambda () ( interactive ) ( other-window 1 )))
( bind-key "S-<home>" ' ( lambda () ( interactive ) ( other-window -1 )))
;; Middle clicking on the mode line shouldn't close all other frames.
( global-set-key [mode-line mouse-2] 'ignore )
;;; Unbind the stupid minimize that I always hit.
( global-unset-key ( kbd "C-z" ))
( global-unset-key ( kbd "C-x C-z" ))
( global-unset-key ( kbd "M-/" ))
( global-unset-key ( kbd "M-SPC" ))
;; --------------------------------------- [ Coding system configuration ]
( prefer-coding-system 'utf-8 )
( modify-coding-system-alist 'file "\\.sjs\\'" 'shift_jis )
;; --------------------------------------------------- [ auto-mode-alist ]
( setq auto-mode-alist
( append ' (( "cl_description" . commit-message-mode )
( "\\.mm?$" . objc-mode )
( "\\.mak$" . makefile-mode )
( "\\.conf$" . conf-mode )
( "\\.uncompressed$" . hexl-mode )
( "\\.scons$" . python-mode )
( "SCons\\(cript\\|truct\\)" . python-mode )
) auto-mode-alist ))
;; Ignore haskell interface files.
( add-to-list 'completion-ignored-extensions ".hi" )
;; yasnippet usage.
( defun my/autoinsert-yas-expand ()
"Replace text in yasnippet template."
( yas/expand-snippet ( buffer-string ) ( point-min ) ( point-max )))
( define-derived-mode commit-message-mode text-mode "CommitMsg"
"A quick hack to set the fill line to 72 characters."
( setq fill-column 72 ))
( add-hook 'suspend-hook 'do-auto-save ) ;; Auto-Save on ^Z
( put 'eval-expression 'disabled nil )
( fset 'yes-or-no-p 'y-or-n-p ) ;; Make all yes-or-no questions as y-or-n
;; -----------------------------------------------------------------------
;; IV) Mode Hooks (aka the other way to make loading emacs fast)
;; -----------------------------------------------------------------------
;; ------------------------------------------------ [ my-start-prog-mode ]
( defun my-prog-startup ()
;; In programming modes, M-i should do ido based imenu switching, to let us
;; quickly jump around a buffer.
( local-set-key ( kbd "M-i" ) 'idomenu )
;; All trailing whitespace needs to be highlighted so it can die.
( setq show-trailing-whitespace t ))
( add-hook 'prog-mode-hook 'my-prog-startup )
;; ----------------------------------------------------- [ LaTeX startup ]
( defun my-LaTeX-startup ()
"Change the default LaTeX environment."
( interactive )
;; Set up {fly,i}spell to do the right thing
( flyspell-mode t )
( setq-local ispell-parser 'tex ))
( add-hook 'LaTeX-mode-hook 'my-LaTeX-startup ) ;; AUCTex latex mode
( add-hook 'latex-mode-hook 'my-LaTeX-startup ) ;; Emacs latex mode
;; --------------------------------------------------- [ Haskell startup ]
( defun my-haskell-startup ()
"Change the default haskell environment."
( interactive )
( ftf-add-filetypes ' ( "*.hs" ))
( turn-on-haskell-doc-mode )
( turn-on-haskell-indentation )
( turn-on-haskell-decl-scan ))
( add-hook 'haskell-mode-hook 'my-haskell-startup )
;; ---------------------------------------------------- [ Help Mode Hook ]
( defun my-help-mode-hook ()
( interactive )
;; This one needs some explanation. `describe-personal-keybindings' is the
;; only help-mode using buffer which overflows lines. So truncate them since
;; otherwise it messes up the tabular data there.
( setq truncate-lines t ))
( add-hook 'help-mode-hook 'my-help-mode-hook )
;; -------------------------------------------------- [ Makefile startup ]
( defun my-makefile-startup ()
"Setup Makefile."
( interactive )
;; Override yasnippet in makefile mode.
( bind-key "TAB" 'tab-to-tab-stop makefile-mode-map ))
( add-hook 'makefile-mode-hook 'my-makefile-startup )
;; ------------------------------------------------------ [ Perl Startup ]
( defun my-perl-startup ()
"Setup perl."
( interactive )
( local-set-key ( kbd "<f4>" ) 'perldb )
( setq tab-width 8 )
( setq indent-tabs-mode nil ) ; Autoconvert tabs to spaces
( my-start-scripting-mode "pl" "#!/usr/bin/perl" ))
( add-hook 'perl-mode-hook 'my-perl-startup )
;; ---------------------------------------------- [ Shell script startup ]
( defun my-shellscript-startup ()
"Setup shell script mode."
( interactive )
( my-start-scripting-mode "sh" "#!/bin/bash" ))
( add-hook 'sh-mode-hook 'my-shellscript-startup )
;; ---------------------------------------------------- [ Python startup ]
( defun my-python-startup ()
"Setup Python style."
( interactive )
( local-set-key ( kbd "<f4>" ) 'pdb )
( setq tab-width 2 )
( setq indent-tabs-mode nil ) ; Autoconvert tabs to spaces
( my-start-scripting-mode "py" "#!/usr/bin/python" ))
( add-hook 'python-mode-hook 'my-python-startup )
;; ------------------------------------------- [ my-common-c-ish-startup ]
( defun my-common-c-ish-startup ()
( interactive )
( require 'google-c-style )
( google-set-c-style )
( local-set-key ( kbd "C-o" ) 'ff-get-other-file ))
( add-hook 'c-mode-common-hook 'my-common-c-ish-startup )
;; ------------------------------------------------- [ Term Mode Startup ]
( defun my-term-send-backward-word ()
"Move backward word in term mode."
( interactive )
( term-send-raw-string "\eb" ))
( defun my-term-send-forward-word ()
"Move backward word in term mode."
( interactive )
( term-send-raw-string "\ef" ))
( defun my-term-mode-startup ()
( interactive )
;; Stuff that term.el says you should set but doesn't set for you by default.
( setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *" )
( setq-local mouse-yank-at-point t )
( setq-local transient-mark-mode nil )
( auto-fill-mode -1 )
( setq tab-width 8 )
;; Translate some keys which would otherwise screw up.
( define-key term-raw-map ( kbd "C-<left>" ) 'my-term-send-backward-word )
( define-key term-raw-map ( kbd "C-<right>" ) 'my-term-send-forward-word )
( define-key term-raw-map ( kbd "M-p" ) 'term-send-up )
( define-key term-raw-map ( kbd "M-n" ) 'term-send-down ))
( add-hook 'term-mode-hook 'my-term-mode-startup )
;; ------------------------------------------------ [ Emacs Lisp Startup ]
( defun my-elisp-startup ()
( interactive )
;; Byte compile this file as soon as its saved.
( make-local-variable 'after-save-hook )
( add-hook 'after-save-hook
' ( lambda () ( byte-compile-file buffer-file-name ))
nil t ))
( add-hook 'emacs-lisp-mode-hook 'my-elisp-startup )
;; -----------------------------------------------------------------------
;; IV) Customize
;; -----------------------------------------------------------------------
;;
;; I resisted using customize for a long time, but it seems like the best way
;; to set certain variables. We'll see how long this lasts.
;;
( 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.
' ( auto-insert-alist
( quote
(( "chrome\\/.*\\.cc$" .
[ "chrome-source-file.cc" my/autoinsert-yas-expand] )
( "chrome\\/.*\\.h$" .
[ "chrome-header-file.h" my/autoinsert-yas-expand] )
( "rlvm\\/.*\\.cc$" .
[ "rlvm-source-file.cc" my/autoinsert-yas-expand] )
( "rlvm\\/.*\\.h$" .
[ "rlvm-header-file.h" my/autoinsert-yas-expand] )
( "chrome\\/.*\\.gn$" .
[ "chrome-gn-file.gn" my/autoinsert-yas-expand] )
( "_posts\\/.*\\.md$" .
[ "jekyll-post.md" my/autoinsert-yas-expand] ))))
' ( auto-insert-directory "~/.elliot-unix/emacs/insert/" )
' ( auto-insert-mode t )
' ( auto-insert-query nil )
' ( backup-by-copying t )
' ( backup-directory-alist ( quote (( "." . "~/.emacs.d/saves" ))))
' ( blink-cursor-mode nil )
' ( byte-compile-warnings nil )
' ( column-number-mode t )
' ( compilation-scroll-output t )
' ( custom-enabled-themes ( quote ( dark-forest )))
' ( custom-safe-themes t nil nil "If I don't set this, this variable becomes an ever growing alist." )
' ( delete-old-versions t )
' ( enable-local-variables :safe )
' ( fill-column 79 )
' ( grep-use-null-device nil nil nil "Needed to prevent git grep from erroring the first time I call it." )
' ( indent-tabs-mode nil )
' ( inhibit-startup-screen t )
' ( lua-indent-level 2 )
' ( major-mode ( quote text-mode ))
' ( next-screen-context-lines 4 )
' ( package-selected-packages
( quote
( gitconfig-mode hexrgb company-auctex auctex ascii js2-mode use-package typescript-mode solidity-mode yasnippet yaml-mode scss-mode rainbow-mode pager-default-keybindings ninja-mode markdown-mode magit lua-mode idomenu haskell-mode google-c-style go-mode find-things-fast emms echo-bell dummy-h-mode diminish dart-mode company browse-kill-ring bison-mode powerline )))
' ( perl-continued-brace-offset -2 )
' ( perl-continued-statement-offset 2 )
' ( perl-indent-level 2 )
' ( perl-tab-always-indent nil nil nil "Indent if at left margin, else tab" )
' ( python-indent-offset 2 )
' ( require-final-newline t )
' ( show-paren-mode t )
' ( tab-width 4 )
' ( tags-revert-without-query t )
' ( tool-bar-mode nil )
' ( truncate-partial-width-windows nil )
' ( vc-follow-symlinks nil ))
( 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.
' ( default (( t ( :height 140 :family "Inconsolata" )))))