Last active
August 29, 2015 14:05
-
-
Save nsmaciej/3b59ef19487e32466990 to your computer and use it in GitHub Desktop.
My broken emacs config
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;; init.el - Maciej's Emacs config | |
| ;; Copyright (C) 2014 Maciej Goszczycki | |
| ;; This program is free software; you can redistribute it and/or | |
| ;; modify it under the terms of the GNU General Public License | |
| ;; as published by the Free Software Foundation; either version 2 | |
| ;; of the License, or (at your option) any later version. | |
| ;; This program is distributed in the hope that it will be useful, | |
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| ;; GNU General Public License for more details. | |
| ;; You should have received a copy of the GNU General Public License | |
| ;; along with this program; if not, write to the Free Software | |
| ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| ;; Here for you since 2014.. and to think I used to use Vim | |
| ;; === TODO === | |
| ;; * Add a _Good_ project management system | |
| ;; * MORE Org-mode! Easy note taking | |
| ;; * Custom mode-line | |
| ;; * Setup TRAMP in detail | |
| ;; * Open NeoTree at current location | |
| ;; * YuoTube player - not kidding | |
| ;; * Popwin.el for Helm and others | |
| ;; * Better highlight symbol, highlight jump | |
| ;; * A different eshell for each workspace | |
| ;; * Emacs IRC, RSS, Email | |
| ;; * Set up calendar | |
| ;; * Eaasier alias for repeat | |
| ;; * Learn to stop using God-mode | |
| ;; * Remember mode | |
| ;; * More welcome scratch buffer: fortune, my keybindings and stuff to learn | |
| ;; First saved change was on 25th of August 2014 | |
| ;; Proper sectioning and this log was added on 8th of November 2014 | |
| ;; Copyright notice was added on 18th of November 2014 - I also discovered TRAMP | |
| ;; God-mode was replace with Evil-mode on 28th of Devember 2014 | |
| ;; Stopped using Emacs for AIPO in January 2015 | |
| ;; Came back to Emac for Haskell on 31st of May 2015 | |
| ;; All in one file.. It's not versatile if moving your config requires you | |
| ;; to scp whole folders. Split into sections instead. | |
| ;; on sections, almost copied from: http://metasandwich.com/2013/01/19/emacs-config-youre-doing-it-wrong/ | |
| ;; Jump menu is globally bound to "C-c i" but with God mode it's just "c <space> i" | |
| ;; This file contains volume control which means you/I can safely switch Mac OS X to Function mode without | |
| ;; sacrificing volume control.. Control is bound to <f11> and <f12> just like by default. Half-step increase | |
| ;; is achieved by adding a raw prefix argument before pressing the function keys | |
| ;;;; Early setup | |
| ;; Disable stupid GUI things quickly before anything else loads | |
| (tool-bar-mode -1) | |
| (scroll-bar-mode -1) | |
| (blink-cursor-mode -1) | |
| ;; Mouse in the terminal | |
| ;; Makes it hard to select text :( | |
| ;; (xterm-mouse-mode 1) | |
| ;; Also disable the stupid Terminal elemenst | |
| (menu-bar-mode -1) | |
| (column-number-mode 1) | |
| ;; Load packages for stuff below | |
| (package-initialize) | |
| ;; Setup extra package reopsitories | |
| (require 'package) | |
| (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t) | |
| ;;;; Config functions | |
| (defun ensure-installed (name) | |
| "Ensure a package is installed" | |
| (unless (package-installed-p name) | |
| (package-install name))) | |
| (defun require-and-ensure-installed (name &rest body) | |
| "Require a package, if not installed, install it" | |
| (ensure-installed name) | |
| (apply 'require name body)) | |
| (defmacro defun-hook (hooks arguments &rest body) | |
| "Syntaxtic sugar for add-hook with lambda, for convinience" | |
| (unless (listp hooks) (setq hooks (list hooks))) | |
| (cons 'progn (mapcar (lambda (hook) | |
| `(add-hook (quote ,hook) (lambda ,arguments ,@body))) hooks))) | |
| (defun add-hooks (hooks function &optional append local) | |
| "Add multiple hooks at the same time" | |
| (mapc (lambda (hook) (add-hook hook function append local)) hooks)) | |
| ;;;; Config variables | |
| ;;; Note to self: I should mostly get rid of this section.. with imenu it's easier | |
| ;;; to just look variables up than having them all in a giant mess here | |
| (defvar modes-without-electric-indent '(fundamental-mode python-mode org-mode) | |
| "Modes in which to not enable eletric indent") | |
| (defvar custom-fringe-size 5 | |
| "Size my init.el will use for fringes") | |
| (defvar extra-path-locations (list "/applications/racket v6.1/bin" | |
| "/usr/local/bin" | |
| (expand-file-name "~/library/haskell/bin")) | |
| "folders to add to various emacs path variables") | |
| (defvar my-default-indention 4 "Default indention my init.el should try to use") | |
| ;; WTF! Emacs-lisp-mode isn't derived from Lisp-mode? | |
| (defvar modes-with-eletric-pair '(lisp-mode emacs-lisp-mode) | |
| "Modes for which `electric-pair-mode' should be enabled. | |
| Modes are checked using `derived-mode-p'.") | |
| (defvar my-chosen-shell "bash" | |
| "Shell the launch bash-shell with.. The executable should be in Emacs's PATH | |
| As of the day I'm witting this, all it takes is adding the path do `extra-path-locations'. | |
| Or you can just specify explicit path.. but that's going to break someday") | |
| ;;;; Misc handy functions | |
| (defun switch-to-modified (&optional frame) | |
| "Looks for modified buffers in `buffer-list' that has a file associated and switches to it" | |
| (interactive) | |
| (let ((buffers (buffer-list)) | |
| (found-buffer nil)) | |
| (while (not (or (null buffers) | |
| found-buffer)) | |
| (when (and (buffer-modified-p (car buffers)) | |
| (buffer-file-name (car buffers))) | |
| (setq found-buffer (car buffers))) | |
| (setq buffers (cdr buffers))) | |
| (if found-buffer | |
| (switch-to-buffer found-buffer) | |
| (message "No modified buffer found")))) | |
| (defun test-function () | |
| "This is a blank test function. You can change it's definition. | |
| It is bound to \\[test-function] for convenience" | |
| (interactive) | |
| (message "You called the test function with %s") this-command-keys-vector) | |
| (defun jump-to-scratch (p) | |
| "Jump to scratch buffer.. adding a prefix argument creates an extra buffer | |
| named *scratchN* \(where N is the prefix argument\(. No prefix or 1 prefix jumps | |
| to the standard buffer. Handy for quick note taking | |
| Bound to \\[jump-to-scratch] for ease of access. | |
| It also fires `change-major-mode-hook'.. Really it's just a nice generic | |
| way to activate God-mode.. that ensures if I ever change my mind this function | |
| will remain valid" | |
| (interactive "p") | |
| (switch-to-buffer (format "*scratch%s*" (if (> p 1) p ""))) | |
| (run-hooks 'change-major-mode-hook)) | |
| (defun jump-to-eshell (p) | |
| "Close cousin of `jump-to-scratch'. Specify prefix argument to jump to *eshell*<N>. | |
| 1 or no prefix argument jump to just *eshell*. It's bound to \\[jump-to-eshell] for easy access" | |
| (interactive "p") | |
| (if (> p 1) (eshell p) (eshell))) | |
| (defun jump-back-to-buffer () | |
| "The opposite of `jump-to-scratch' and `jump-to-eshell'. Jumps to the \"other buffer\" | |
| that isn't an \"asterisk\" buffer. The \"other buffer\" is acquired using `window-prev-buffers' | |
| which means that I can quickly jump to scratch and eshell and then get back to the same file." | |
| (interactive) | |
| (let ((prev-buffers (window-prev-buffers)) | |
| (found-buffer nil)) | |
| (while (not (or (null prev-buffers) found-buffer)) | |
| (when (not (or | |
| (string-match-p "^\\*.*\\*\\(<[0-9]+>\\)?$" (buffer-name (caar prev-buffers))) | |
| (eq (current-buffer) (caar prev-buffers)))) | |
| (setq found-buffer (caar prev-buffers))) | |
| (setq prev-buffers (cdr prev-buffers))) | |
| (switch-to-buffer found-buffer))) | |
| (defun words-in-paragraph () | |
| "Count the number of words in the paragraph (selected with `mark-paragraph')" | |
| (interactive) | |
| (save-excursion | |
| (mark-paragraph) | |
| (call-interactively 'count-words-region))) | |
| (defun kill-buffer-save (&optional buffer-name) | |
| "Like to `kill-ring-save' but selects the whole buffer automatically" | |
| (interactive) | |
| (copy-region-as-kill (point-min) (point-max))) | |
| (defun unfill-paragraph () | |
| "Takes a multi-line paragraph and makes it into a single line of text. | |
| Stefan Monnier <foo at acm.org>" | |
| (interactive) | |
| (let ((fill-column (point-max))) | |
| (fill-paragraph nil))) | |
| ;; One day I got pissed of Emacs can't control volume on my mac when function keys | |
| ;; are enabled for it.. well now it can | |
| ;;TODO: Make it possible to increase/decrease volume in half-steps | |
| (defvar volume-change-by 10 | |
| "How much to increase and round volume up to in `volume-increase' and `volume-decrease'") | |
| (defvar volume-alternate 0 | |
| "Alternate volume to go into after pressing mute button. It's hard-coded to be 0 | |
| in code, so don't bother changing, it wouldn't be mute if it wasn't 0") | |
| ;; Rounding routine is really mensed up.. because of how round works we need to multiply | |
| ;; by volume-change-by again | |
| (defun volume-add (by &optional divide) | |
| "Increases volume by BY. Used by `volume-increase' and `volume-dcecrease'. | |
| DIVIDE specifies by how to divide the volume increase by. Uses for half step volume increasing " | |
| (interactive) | |
| (unless divide (setq divide 1)) | |
| (setq by (round (/ by divide))) | |
| (volume-set (* (round (+ (volume-get) by) by) by))) | |
| (defun volume-decrease (&optional half-step) | |
| "Decrease volume by `volume-change-by'" | |
| (interactive "P") | |
| (volume-add (- volume-change-by) (if half-step 2 1))) | |
| (defun volume-increase (&optional half-step) | |
| "Increase volume by `volume-change-by'" | |
| (interactive "P") | |
| (volume-add volume-change-by (if half-step 2 1))) | |
| (defun volume-mute () | |
| "Mute the volume to 0, if at 0 already restore volume to `volume-alternate' | |
| This is standard behavior taken from Mac OS X" | |
| (interactive) | |
| (let ((current-volume (volume-get))) | |
| (if (= current-volume 0) | |
| (progn (volume-set volume-alternate) | |
| (setq volume-alternate 0) | |
| (message "Volume restored")) | |
| (setq volume-alternate (volume-get)) | |
| (volume-set 0) | |
| (message "Volume muted")))) | |
| (defun volume-set (volume) | |
| "Set sound volume to a number | |
| Uses 'N' interactive code so prefix argument can be used. " | |
| (interactive "NVolume level? ") | |
| (cond ((string= system-type "darwin") (if (= 0 (call-process-shell-command (format "osascript -e 'set volume output volume %d'" volume))) | |
| (message "Volume set to %d" volume) | |
| (message "Error occurred while setting volume"))) | |
| (t (message "Not implemented for '%s'" system-type)))) | |
| (defun volume-get () | |
| "Get current volume, very system specific" | |
| (interactive) | |
| (let* ((command "get output volume of (get volume settings)") | |
| (volume (string-to-number (cond ((string= system-type "darwin") | |
| (car (process-lines "osascript" "-e" command))))))) | |
| (when (called-interactively-p 'any) (message "Current volume is %d" volume)) | |
| volume)) | |
| ;;;; Important setup | |
| ;; Set up indention | |
| (setq-default indent-tabs-mode nil | |
| tab-width 4) | |
| ;; Delete all whitespace on backspace | |
| (setq backward-delete-char-untabify-method 'hungry) | |
| ;; FXIME! Breaks stuff | |
| ;;(setq indent-line-function 'insert-tab) | |
| ;; | |
| ;; Show various kinds of whitespace | |
| (global-whitespace-mode 1) | |
| ;; What kind of stuff to show | |
| (setq whitespace-style '(face ; Use custom faces | |
| trailing ; Show trailing whitespace | |
| tabs ; Shows tabs | |
| empty ; Empty lines at start or end of buffer | |
| ; lines-tail ; Show long lines | |
| tab-mark)) ; Tabs have special symbols | |
| ;; Get rid of whitespace on save | |
| (add-hook 'before-save-hook 'whitespace-cleanup) | |
| ;; Emacs path | |
| (setq exec-path (append extra-path-locations exec-path)) | |
| ;; I would enable type-break mode here but it seems to break Emacs's | |
| ;; I might try to write my own lightweight alterantive | |
| ;; One way fullscreen toggle | |
| (unless (frame-parameter nil 'fullscreen) | |
| (toggle-frame-fullscreen)) | |
| ;; Disable alarms | |
| (setq ring-bell-function 'ignore) | |
| ;; Make all yes/no questions y/n questions | |
| (defalias 'yes-or-no-p 'y-or-n-p) | |
| (setq use-dialog-box nil) | |
| ;; Try to set up better scrolling | |
| ;; Slightly jaggy but better than default | |
| ;; Note: Commented out because seems to break stuff - fix later | |
| ;; (setq scroll-step 1 | |
| ;; scroll-conservatively 200 | |
| ;; mouse-wheel-progressive-speed nil) | |
| (setq mouse-wheel-progressive-speed nil ; Don't speed up | |
| mouse-wheel-scroll-amount '(4 ((shift) . 1)) ; Scroll by 4 unless pressing shift | |
| scroll-margin 6 ; Margin off scroll | |
| scroll-conservatively 100) ; Don't re-centre so dramatical | |
| ;; Right fringe is nearly never needed, disable it | |
| (fringe-mode (cons custom-fringe-size 0)) | |
| ;; Make command meta in OSX | |
| (setq mac-command-modifier 'control) | |
| ;; Change Gui font | |
| (set-frame-font "Monaco-12") | |
| ;; Disbale the startup screen | |
| (setq inhibit-startup-message t | |
| initial-scratch-message "") | |
| ;;;; Helm config | |
| ;; Attempt as using helm | |
| (require-and-ensure-installed 'helm) | |
| (require 'helm-config) ; Supposed to fix upgrades | |
| (helm-mode 1) | |
| ;; Make tab more freindly-ish | |
| (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action) | |
| (define-key helm-map (kbd "C-z") 'helm-select-action) | |
| ;; Use mdfind on OSX by default | |
| (setq helm-c-locate-command | |
| (case system-type | |
| ('gnu/linux "locate -i -r %s") | |
| ('berkeley-unix "locate -i %s") | |
| ('windows-nt "es %s") | |
| ('darwin "mdfind -name %s %s") | |
| (t "locate %s"))) | |
| ;; Better describe bindings | |
| (require-and-ensure-installed 'helm-descbinds) | |
| (helm-descbinds-mode 1) | |
| (require-and-ensure-installed 'evil) | |
| (evil-mode 1) | |
| ;;;; God mode | |
| ;; Alterantive to evil-mode.. Still here for historicall reasons :D | |
| ;; I got fed up with Emacs not having a decent editor | |
| ;; (require-and-ensure-installed 'god-mode) | |
| ;; (god-mode-all) | |
| ;; ;; Sets cursor to be bar by default.. it's a horrible hack | |
| ;; ;; Emacs has no nice way of calling functions after buffer creation | |
| ;; ;; and I got used to seeing box cursor with God mode. This ensures | |
| ;; ;; that if God mode is not enabled cursor stays consistent | |
| ;; (setq cursor-type 'bar) | |
| ;; ;; Few different ways of exiting in terminal | |
| ;; (global-set-key (kbd "<escape>") 'god-local-mode) | |
| ;; (global-set-key (kbd "<ESC> <ESC>") 'god-local-mode) | |
| ;; ;; Update the cursor depending on god mode | |
| ;; (defun-hook (god-mode-enabled-hook god-mode-disabled-hook) () | |
| ;; (setq cursor-type (if god-local-mode 'box 'bar))) | |
| ;; ;; Allow god mode to run everywhere | |
| ;; (setq god-exempt-predicates '()) | |
| ;; ;; Make sure it's enabled in all new buffers | |
| ;; (defun-hook (find-file-hook change-major-mode-hook) () | |
| ;; (god-local-mode 1)) | |
| ;; When I press enter but I'm in God-mode disable it.. I want to enter data | |
| ;; use C-o instead for adding new lines | |
| (defun newline-wihtout-god () | |
| "Newlines don't believe in God! Disable God! Insert new line to replace God! | |
| Rejoice for you don't have to escape God to enter data after a new line." | |
| (interactive) | |
| (when god-local-mode (god-local-mode -1)) | |
| (newline 1 t)) | |
| ;; (global-set-key (kbd "<RET>") 'newline-wihtout-god) | |
| ;;;; Color theme | |
| ;; (require-and-ensure-installed 'monokai-theme) | |
| ;; (unless (memq 'monokai custom-enabled-themes) ; Allow nice eval-buffer | |
| ;; (load-theme 'monokai t)) | |
| (require-and-ensure-installed 'monokai-theme) | |
| (unless (memq 'monokai custom-enabled-themes) ; Allow nice eval-buffer | |
| (load-theme 'monokai t)) | |
| ;; Python mode settings | |
| (setq python-indent-offset my-default-indention) | |
| ;; C mode settings | |
| (setq-default c-basic-offset my-default-indention | |
| c-default-style "linux") | |
| ;;; Disable auto-newline for now.. it doesn't really help | |
| ;; (defun-hook 'c-mode-common-hook () ; Hungry state sounded fun.. but it makes it hard | |
| ;; (c-toggle-auto-newline 1)) ; to make empty lines :( | |
| ;; Indent stuff by default | |
| ;; Enable indent mode everywhere but not in fundamental and python | |
| ;; If in Python simply newline-and-indent instead | |
| ;; this might be obsolete by now.. I think Emacs 24.4 made it a default option | |
| ;; but it will stay here because it's awesome.. I like to see my init.el evolve.. and not | |
| ;; everyone uses Emacs 24.4 | |
| (electric-indent-mode 1) | |
| (defun-hook electric-indent-functions (char) | |
| (if (member major-mode modes-without-electric-indent) 'no-indent nil)) | |
| (defun-hook python-mode-hook () (local-set-key (kbd "RET") 'newline-and-indent)) | |
| ;; Out of order while paredit kicks ass | |
| ;; Auto insert parens | |
| ;; (electric-pair-mode 1) | |
| ;; Make electric pair a little bit more reasonable: only enable in certain modes | |
| ;; (setq electric-pair-inhibit-predicate (lambda (c) | |
| ;; (if (some 'derived-mode-p modes-with-eletric-pair) | |
| ;; (electric-pair-default-inhibit c) | |
| ;; 'no-pair))) | |
| ;; Enable rainbow parens | |
| (require-and-ensure-installed 'rainbow-delimiters) | |
| (add-hook 'prog-mode-hook 'rainbow-delimiters-mode) | |
| ;; Auto complete setup | |
| (require-and-ensure-installed 'smart-tab) | |
| (setq completion-auto-help 'lazy) | |
| (global-smart-tab-mode 1) | |
| ;; Disable truncate lines by default | |
| (set-default 'truncate-lines nil) | |
| ;; Org-mode setup | |
| (require 'org) | |
| (setq org-log-done t) | |
| (global-set-key (kbd "C-c l") 'org-store-link) | |
| (global-set-key (kbd "C-c a") 'org-agenda) | |
| (define-key org-mode-map (kbd "C-c w") 'words-in-paragraph) | |
| (setq org-startup-indented t) | |
| (add-hook 'org-mode-hook 'refill-mode) | |
| ;; Text mode setup | |
| (setq-default fill-column 90) | |
| (defun-hook text-mode-hook () | |
| (if (y-or-n-p "Enable refill mode?") | |
| (refill-mode 1) | |
| (visual-line-mode 1))) | |
| (add-hook 'text-mode-hook 'flyspell-mode) | |
| (define-key text-mode-map (kbd "C-c w") 'words-in-paragraph) | |
| (define-key text-mode-map (kbd "C-c W") 'count-words) | |
| (define-key text-mode-map (kbd "C-c u") 'unfill-paragraph) | |
| ;; Backup setup | |
| (setq backup-directory-alist `((".*" . ,(concat user-emacs-directory ".backups")))) | |
| (setq backup-by-copying t ; Keeps permisions the same and stuff | |
| version-control t ; Doesn't matter because we save in a different dir | |
| delete-old-versions t ; Too much of a good thing... | |
| kept-old-versions 2 ; Keep the first two versions ever made | |
| kept-new-versions 4) ; Keep the last 4 versions | |
| (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) | |
| ;;;; Eshell setup | |
| ;; Make sure this is above (require 'esehll) - eshell inherits PATH for eshell-path-env | |
| ;; By now most of this code is obsolete, I switched to ansi-term because eshell just | |
| ;; wasn't cutting it, in the world where all hip commands have color output.. | |
| ;; not to mention lack of shell redirection and bad performance of built in commands | |
| (setenv "PATH" | |
| (mapconcat 'identity | |
| `(,@(mapcar 'shell-quote-argument extra-path-locations) ,(getenv "PATH")) ":")) | |
| ;; Preload all things for eshell | |
| (require 'eshell) | |
| ;; Commands that require visual | |
| (setq eshell-visual-subcommands '(("npm" "init"))) | |
| ;; Gets around a bug in eshell | |
| ;; see https://lists.gnu.org/archive/html/bug-gnu-emacs/2013-03/msg00533.html | |
| (setq eshell-prompt-function (lambda () | |
| (let* ((cwd-part (abbreviate-file-name (eshell/pwd))) | |
| (dollar (if (= (user-uid) 0) "#" "$")) | |
| (prompt (concat | |
| (propertize cwd-part 'face 'shadow) | |
| " " | |
| (propertize dollar 'face 'font-lock-function-name-face 'face 'bold) | |
| " "))) | |
| (propertize prompt | |
| 'front-sticky '(face read-only) | |
| 'read-only t | |
| 'rear-nonsticky '(face read-only))))) | |
| (setq eshell-highlight-prompt nil) ; Don't allow eshell to override our colors | |
| ;; Each chnage in prompt function also needs prompt regex | |
| (setq eshell-prompt-regexp "^[^$#]* [$#] ") | |
| ;; Disable banner message | |
| (setq eshell-banner-message "") | |
| ;; Commands | |
| (defun eshell/clear () | |
| "Clears the eshell buffer" | |
| (let ((inhibit-read-only t)) | |
| (erase-buffer))) | |
| (defun eshell/emacs (&rest args) | |
| "Opens a file in emacs.\n | |
| If a file isn't given, just burries the ehsell buffer using `bury-buffer'\n | |
| See URL `http://www.emacswiki.org/emacs/EshellFunctions' for more info on the extra clutter" | |
| (if (null args) | |
| (bury-buffer) | |
| (mapc #'find-file (mapcar #'expand-file-name (eshell-flatten-list (reverse args)))))) | |
| ;;;; Keybindings | |
| ;;; Swap C-x b with C-x C-b - easier in God mode | |
| (global-set-key (kbd "C-x C-b") 'helm-buffers-list) | |
| (global-set-key (kbd "C-x b") 'list-buffers) | |
| (global-set-key (kbd "C-x C-k") 'kill-buffer) | |
| ;;; Helm evrything! | |
| (global-set-key (kbd "M-x") 'helm-M-x) | |
| (global-set-key (kbd "C-h f") 'helm-apropos) | |
| (global-set-key (kbd "C-h v") 'helm-apropos) | |
| (global-set-key (kbd "C-x C-f") 'helm-find-files) | |
| (define-key comint-mode-map (kbd "C-c C-l") 'helm-comint-input-ring) | |
| ;; Other custom extensions | |
| (global-set-key (kbd "M-y") 'browse-kill-ring) | |
| ;;; Custom ones | |
| (global-set-key (kbd "C-c o") 'overwrite-mode) | |
| (global-set-key (kbd "C-c k") 'kill-this-buffer) | |
| (global-set-key (kbd "C-c g") 'goto-line) | |
| (global-set-key (kbd "C-c m") 'pop-global-mark) | |
| (global-set-key (kbd "C-c i") 'helm-imenu) | |
| (global-set-key (kbd "C-c h") 'hexl-find-file) | |
| (global-set-key (kbd "C-c t") 'toggle-truncate-lines) | |
| ;; Searching stuff | |
| (global-set-key (kbd "C-c r r") 'rgrep) | |
| (global-set-key (kbd "C-c r l") 'lgrep) | |
| (global-set-key (kbd "C-c r o") 'helm-occur) | |
| ;;; Function keys.. for the really handy stuff | |
| ;; The ff-find-other-file is really handy. I discovered it while working | |
| ;; on kismac @ Open Wifi. It jumps to the corresponding other file. Like *.h to *.c | |
| (global-set-key (kbd "<f4>") 'ff-find-other-file) | |
| (global-set-key (kbd "<f5>") 'highlight-symbol-mode) | |
| ;; Handy for jumping to stuff | |
| ;; by my convention prefix argument is used to select buffer number | |
| (global-set-key (kbd "<f1>") 'jump-to-scratch) | |
| (global-set-key (kbd "<f2>") 'jump-to-eshell) | |
| (global-set-key (kbd "<f3>") 'jump-back-to-buffer) | |
| ;; Volume control | |
| (global-set-key (kbd "<f12>") 'volume-increase) | |
| (global-set-key (kbd "<f11>") 'volume-decrease) | |
| (global-set-key (kbd "<f10>") 'volume-mute) | |
| ;;;; Various extension bits | |
| ;; General packages | |
| (ensure-installed 'markdown-mode) | |
| (ensure-installed 'neotree) | |
| (ensure-installed 'restclient) | |
| ;; Highlight symbol mode | |
| (setq highlight-symbol-idle-delay 0 | |
| highlight-symbol-on-navigation-p t) | |
| ;; Tramp mode | |
| (setq tramp-default-method "ssh" | |
| tramp-default-user "root") | |
| ;; Disover my Major | |
| (require-and-ensure-installed 'discover-my-major) | |
| (global-set-key (kbd "C-h C-m") 'discover-my-major) | |
| ;; Undo tree setup | |
| ;; (require-and-ensure-installed 'undo-tree) | |
| ;; (global-undo-tree-mode 1) | |
| ;; (setq undo-tree-auto-save-history t | |
| ;; undo-tree-history-directory-alist nil | |
| ;; undo-tree-visualizer-diff t | |
| ;; undo-tree-visualizer-timestamps t | |
| ;; undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo/"))) | |
| ;; Tetris score file! | |
| (setq tetris-score-file "~/.emacs.d/tetris.scores") | |
| ;; Browse kill-ring | |
| (require-and-ensure-installed 'browse-kill-ring) | |
| (setq browse-kill-ring-highlight-current-entry t) | |
| ;; Just require ace-jump-mode | |
| (require-and-ensure-installed 'ace-jump-mode) | |
| (global-set-key (kbd "C-'") 'ace-jump-mode) | |
| (global-set-key (kbd "M-'") 'ace-jump-mode-pop-mark) | |
| ;; Haskell mode setup | |
| (require-and-ensure-installed 'haskell-mode) | |
| (add-hook 'haskell-mode-hook 'interactive-haskell-mode) | |
| (add-hook 'haskell-mode-hook 'structured-haskell-mode) | |
| (setq haskell-process-log t) | |
| ;; Ispell mode setup | |
| (require 'flyspell) | |
| (setq ispell-program-name (executable-find "ispell")) | |
| (add-hook 'prog-mode-hook 'flyspell-prog-mode) | |
| (add-hook 'org-mode-hook 'flyspell-mode) | |
| (define-key flyspell-mode-map [mouse-3] 'flyspell-correct-word) | |
| ;; Subword mode (aka camelCase words mode) | |
| (defun-hook prog-mode-hook () | |
| (subword-mode 1) | |
| (diminish 'subword-mode)) | |
| ;; Diminish useless minor mode indicators | |
| (require-and-ensure-installed 'diminish) | |
| (mapc 'diminish '(undo-tree-mode | |
| helm-mode | |
| smart-tab-mode | |
| flyspell-mode | |
| global-whitespace-mode)) | |
| ;; Perspective mode | |
| (persp-mode) | |
| (global-set-key (kbd "C-z") 'persp-switch) | |
| (global-set-key (kbd "C-S-z") 'persp-kill) | |
| ;; Paredit mode setup! | |
| (require-and-ensure-installed 'paredit) | |
| (add-hooks '(emacs-lisp-mode-hook lisp-mode-hook) 'paredit-mode) | |
| ;; Emmtet and web mode for web dev | |
| (require-and-ensure-installed 'emmet-mode) | |
| (add-hook 'emmet-mode 'emmet-mode) | |
| ;; Make ansi-term start bash by default and in line mode | |
| (defun bash-term () | |
| "Launch `ansi-term' in line mode and with bash by default \(or whatever | |
| `my-chosen-shell' is set to\)" | |
| (interactive) | |
| (ansi-term (executable-find my-chosen-shell)) | |
| (term-line-mode)) | |
| ;;;; USACO-mode | |
| (defvar usaco-user-id nil | |
| "User id to use in the USACO headers, when using `usaco-insert-header'") | |
| ;; Used to be local.. see usaco-run description for details | |
| (defvar usaco-input-buffer nil | |
| "Local to current usaco-mode file buffer to use as input during `usaco-run'") | |
| ;; Once again used because compile functions hook changes the current buffer *sigh* | |
| (defvar usaco-code-buffer nil | |
| "Name of the buffer which contains the code being run by `usaco-run'") | |
| (defvar-local usaco-compiler "gcc" | |
| "The compiler `usaco-make' should use by default") | |
| (defvar-local usaco-c-flags "-Wall -Wextra -pedantic -ld" | |
| "Extra flags `usaco-c-flags-function' should use. I consider those sensible defaults") | |
| (defvar-local usaco-cpp-flags "-Wall -Wextra -Wshadow" | |
| "Extra flags `usaco-cpp-flags-function' should use. I consider those sensible defaults") | |
| (defvar usaco-c-flags-function (lambda () | |
| (format "%s -std=c99 -O%d" | |
| usaco-c-flags | |
| usaco-optimize-level)) | |
| "Function that generates flags `usaco-compiler' should use by default when compiling C files.") | |
| (defvar usaco-cpp-flags-function (lambda () | |
| (format "-Wall -Wextra -std=%s -pedantic -ansi -Wshadow -O%d" | |
| (if usaco-use-cpp11 "C++11" "C++98") | |
| usaco-optimize-level)) | |
| "Function that generates flags `usaco-make' should use by default when compiling C++ files. | |
| By default takes `usaco-use-cpp11' into account and switches the -std flag accordingly") | |
| (defvar usaco-use-cpp11 t | |
| "Should `usaco-insert-header' specify language to \"C++11f\" when editing C++ files | |
| and should `usaco-make' use \"C++98\" or \"C++11\" standard") | |
| (defvar-local usaco-optimize-level 0 | |
| "Tells `usaco-make' how much to optimize \(-Ox flag). | |
| 0 by default because it makes program nicer to debug") | |
| (defmacro if-cpp (cpp &optional justc) | |
| "Macro for quickly executing different code depending on | |
| buffer being in c++ or c mode | |
| Example: \(if-cpp \"C++\" \"C\" \"Not C or C++\")" | |
| `(if (string= (file-name-extension (or (buffer-file-name) (buffer-name))) "cpp") | |
| ,cpp ,justc)) | |
| ;; Nice for quickly starting USACO tasks | |
| (defun usaco-insert-header (task-id) | |
| "Insert the required USACO heading" | |
| (interactive "sTask ID: ") | |
| (unless usaco-user-id | |
| (setq usaco-user-id (read-string "Your USACO user ID: "))) | |
| (let ((language (if-cpp (if usaco-use-cpp11 "C++11f" "C++") "C"))) | |
| (goto-char 1) | |
| (insert (format "/*\nID: %s\nLANG: %s\nTASK: %s\n*/\n" usaco-user-id language task-id)) | |
| (goto-char (point-max)))) | |
| (defun usaco-make () | |
| "Compile the current C++ or C buffer using `compile'. | |
| Useful for when compiling a single file in a folder of files (like with USACO) | |
| The program is compiled using the `compile' with `usaco-compiler' as compiler and | |
| `usaco-c-flags' or `usaco-cpp-flags' - both being buffer local variables. | |
| Flags passed to `compile' are generated by `usaco-cpp-flags-function' or | |
| `usaco-c-flags-function' they takes into account `usaco-cpp-flags' and `usaco-c-flags' | |
| as well as `usaco-optimize-level' and `usaco-use-cpp11' so it's best to not change them | |
| The binaries' name is the result of `file-name-sans-extension'. And optimization level | |
| is chosen using `usaco-optimize-level'" | |
| (interactive) | |
| (usaco-mode) | |
| (compile (format "%s %s %s -o %s" | |
| usaco-compiler | |
| (if-cpp | |
| (funcall usaco-cpp-flags-function) | |
| (funcall usaco-c-flags-function)) | |
| (buffer-file-name) | |
| (file-name-sans-extension (buffer-file-name))))) | |
| ;; This gets tricky. Since usaco-actaully-run is called somewhere else I can't pass | |
| ;; variables using the dynamic scope.. the call also changes the current buffer so buffer | |
| ;; local variables fail (out variable _is_ a buffer - Catch 22). It seems the easiest solution | |
| ;; is just to assume I won't be running multiple programs at once and use a global variable | |
| (defun usaco-run (input-buffer) | |
| "Run the C/C++ source in the current buffer using a buffer as input. | |
| Buffer is compiled using `usaco-make' and then run | |
| INPUT-BUFFER is a buffer that contains the text to be send to the running process | |
| When called interactively usaco-run allows user to specify the buffer" | |
| (interactive "bBuffer to use as input: ") | |
| (usaco-mode) | |
| (setq usaco-input-buffer input-buffer) | |
| (setq usaco-code-buffer (buffer-name)) | |
| (unless (buffer-file-name) (save-buffer)) ; Make sure it's saved | |
| (add-hook 'compilation-finish-functions 'usaco-actaully-run) | |
| (usaco-make)) | |
| (defun usaco-actaully-run (buffer cstatus) | |
| "Run this once we tried compiling. Ran as `compilation-finish-functions' hook" | |
| (when (string= cstatus "finished\n") ; Compiled nicely | |
| (message "Running process...") | |
| (remove-hook 'compilation-finish-functions 'usaco-actaully-run) | |
| (let* ((proc-name (file-name-sans-extension usaco-code-buffer)) | |
| (buffer-name "*usaco-output*") | |
| (input-text (with-current-buffer usaco-input-buffer | |
| (buffer-substring-no-properties (point-min) (point-max)))) | |
| (proc (start-process-shell-command proc-name buffer-name (concat "./" proc-name)))) | |
| ;; This was tricky to debug.. it turns out in emacs (current-buffer) doesn't need to be in | |
| ;; (selected-window).. aka when this hook was fired it was in *compilation* buffer but the | |
| ;; selected window was the source. Using (display-buffer) instead of (switch-buffer) fixes | |
| ;; the issue and makes usaco-mode better in general: now my cursor stays in source files at | |
| ;; all times, just as with (compile)! | |
| (display-buffer buffer-name) | |
| (with-current-buffer buffer-name | |
| (erase-buffer) | |
| (special-mode)) | |
| (message "Sending input text from %s to process.." usaco-input-buffer) | |
| (process-send-string proc-name (if (string= (substring input-text -1) "\n") | |
| input-text | |
| (concat input-text "\n"))) ; Add newline - just in case | |
| (process-send-eof proc-name)))) | |
| (define-minor-mode usaco-mode | |
| "Convenient key bindings for working with USACO submissions | |
| Allows specifying arbitrary buffers as input, quickly running | |
| \(and compiling using `compile' and seeing output of programs)" | |
| :lighter " Usaco" | |
| :keymap `((,(kbd "C-c C-m") . usaco-make) | |
| (,(kbd "C-c C-i") . usaco-insert-header) | |
| (,(kbd "C-c C-r") . usaco-run))) | |
| ;; Setup imenu on opening emacs-lisp mode.. See note on top of the config | |
| (defun-hook emacs-lisp-mode-hook () | |
| (setq imenu-prev-index-position-function nil) | |
| (add-to-list 'imenu-generic-expression '("Sections" "^;;;; \\(.+\\)$" 1) t)) | |
| ;;;; Mode line | |
| ;; TODO: Replace with something more custom | |
| (require-and-ensure-installed 'smart-mode-line) | |
| (setq sml/no-confirm-load-theme t) | |
| (sml/setup) | |
| (unless (memq 'smart-mode-line-respectful custom-enabled-themes) | |
| (sml/apply-theme 'respectful)) | |
| ;; Battery mode line | |
| (display-battery-mode 1) | |
| (column-number-mode -1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment