#+TITLE: Emacs Configuration #+AUTHOR: Mitch Tishmack #+STARTUP: hidestars #+STARTUP: odd #+BABEL: :cache yes #+PROPERTY: header-args :cache yes #+PROPERTY: header-args :padline no #+PROPERTY: header-args :mkdirp yes #+PROPERTY: header-args :comments no #+PROPERTY: header-args :results replace #+PROPERTY: header-args :tangle tmp/.emacs.d/init.el * prelude Startup related tasks/setup that might be used later on. *** emacs package setup Setup the builtin emacs package manager. #+BEGIN_SRC emacs-lisp :tangle tmp/.emacs.d/init.el :mkdirp yes (require 'package) (package-initialize) #+END_SRC Add in standard package archive urls. Marmalade is gone as its ssl cert expired in 2018, so don't think its even worth using. #+BEGIN_SRC emacs-lisp (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t) (add-to-list 'package-archives '("stable-melpa" . "https://stable.melpa.org/packages/") t) (add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/") t) #+END_SRC *** tangle functions Duplicated from tangle.el just to make using org easier. TODO: make this stuff work sanely in emacs org mode and via external tangling. Not tangled for now. #+BEGIN_SRC emacs-lisp (defun tangle/yn (p) (if (bound-and-true-p p) "yes" "no")) (defun tangle/file (file p) (if (bound-and-true-p p) (concat "tmp/" file) "no")) #+END_SRC *** emacs gc speedup #+BEGIN_SRC emacs-lisp (defun my-minibuffer-setup-hook () (setq gc-cons-threshold most-positive-fixnum)) (defun my-minibuffer-exit-hook () (setq gc-cons-threshold 8000000)) (add-hook 'minibuffer-setup-hook #'my-minibuffer-setup-hook) (add-hook 'minibuffer-exit-hook #'my-minibuffer-exit-hook) #+END_SRC *** use-package bootstrap This configuration is using *use-package* extensively. Install it earlyso we can use it elsewhere. #+BEGIN_SRC emacs-lisp (package-refresh-contents) (unless (package-installed-p 'use-package) (progn (package-refresh-contents) (package-install 'use-package) (package-initialize))) (require 'use-package) (setq use-package-verbose t) #+END_SRC *** TODO test diminish updates :validation: Keep the mode line less cluttered with crap from modes I don't care about. #+BEGIN_SRC emacs-lisp (use-package diminish :ensure t :config (diminish 'flyspell-mode) (diminish 'whitespace-mode) (diminish 'visual-line-mode) ) #+END_SRC *** match end of string function #+BEGIN_SRC emacs-lisp (defun string/ends-with (string suffix) "Return t if STRING ends with SUFFIX." (and (string-match (rx-to-string `(: ,suffix eos) t) string) t) ) #+END_SRC *** debug on error Not having to start *emacs* with *--debug-init* is useful. #+BEGIN_SRC emacs-lisp (setq debug-on-error t) #+END_SRC *** emacs server Start up the emacs server if it isn't running. #+BEGIN_SRC emacs-lisp (load "server") (unless (server-running-p) (server-start)) #+END_SRC *** theme Solarized light is decent. I'll just use that. Note, to prevent flicker this is setup early in startup. #+BEGIN_SRC emacs-lisp (use-package solarized-theme :ensure t :init (load-theme 'solarized-light 't)) #+END_SRC *** os detection Make it easier to determine what os we're running on. #+BEGIN_SRC emacs-lisp (defvar on-mswindows (string-match "windows" (symbol-name system-type)) "Am I running under windows?") (defvar on-osx (string-match "darwin" (symbol-name system-type)) "Am I running under osx?") (defvar on-linux (string-match "gnu/linux" (symbol-name system-type)) "Am I running under linux?") #+END_SRC *** disable pointless startup stuff Like the startup screen and the echo hooey. #+BEGIN_SRC emacs-lisp (custom-set-variables '(inhibit-startup-screen t) '(inhibit-startup-message t) '(inhibit-startup-echo-area-message t) ) #+END_SRC *** temporary files Keep temporary stuff isolated from everyone else. It infects everything otherwise. As bad as the .DS_Store files on osx. #+BEGIN_SRC emacs-lisp (custom-set-variables '(temporary-file-directory "/tmp") '(backup-directory-alist `((".*" . ,temporary-file-directory))) '(auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) '(create-lockfiles nil) '(make-backup-files nil) '(auto-save-default nil) '(backup-by-copying t) '(auto-save-list-file-prefix temporary-file-directory) '(backup-directory-alist `((".*" . ,temporary-file-directory))) '(auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) ) #+END_SRC *** auto revert Update files in open buffers as they're changed on disk, freaking annoying without this on. #+BEGIN_SRC emacs-lisp (custom-set-variables '(global-auto-revert-mode t)) #+END_SRC *** dired Use dired-x. #+BEGIN_SRC emacs-lisp (add-hook 'dired-load-hook (function (lambda () (load "dired-x")))) #+END_SRC *** ediff For those rare times I use it, make it a bit less derp on output. #+BEGIN_SRC emacs-lisp (setq ediff-window-setup-function 'ediff-setup-windows-plain) (setq ediff-split-window-function 'split-window-horizontally) #+END_SRC *** always remove trailing whitespace Trailing whitespace is not normally useful. Remove it always on save in the *before-save-hook*. #+BEGIN_SRC emacs-lisp (add-hook 'before-save-hook 'delete-trailing-whitespace) #+END_SRC *** chmod u+x on save for scripts Because its derp to have to chmod 755 stuff after I save. Honestly, do it for me kthxbai. #+BEGIN_SRC emacs-lisp (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p) #+END_SRC *** misc text related #+BEGIN_SRC emacs-lisp (put 'upcase-region 'disabled nil) #+END_SRC *** line wrap Line wrapping is useful. Enable it globally for a start. Need word-wrap so kill line kills the line, not the displayed line. #+BEGIN_SRC emacs-lisp (global-visual-line-mode t) (custom-set-variables '(word-wrap t)) #+END_SRC *** default major mode So if we don't know, call it text-mode. #+BEGIN_SRC emacs-lisp (custom-set-variables '(default-major-mode 'text-mode)) #+END_SRC *** encoding utf8 is the best. Default to it. #+BEGIN_SRC emacs-lisp (use-package unicode-escape :ensure t) (set-language-environment "UTF-8") #+END_SRC #+BEGIN_SRC emacs-lisp (custom-set-variables '(locale-coding-system 'utf-8)) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8) #+END_SRC *** text selection If I selected text, delete the selection, I probably meant it emacs. #+BEGIN_SRC emacs-lisp (delete-selection-mode 1) #+END_SRC *** line width 80 char line columns not 72. #+BEGIN_SRC emacs-lisp (custom-set-variables '(fill-column 80)) #+END_SRC *** we aren't banging rocks together anymore emacs Double spacing after a line isn't needed. We aren't animals emacs, we have computers. #+BEGIN_SRC emacs-lisp (set-default 'sentence-end-double-space nil) #+END_SRC *** long line speedups Improve the performance of emacs with files that contain long lines. Disable left to right and right to left in the same buffer support. Until or if I learn a language that needs this I can deal with it then. #+BEGIN_SRC emacs-lisp (setq-default bidi-paragraph-direction 'left-to-right) #+END_SRC Also disable this algorithm, which may unbalance ()'s in bidirectional language detection. But again as I don't use/speak/read them. Ok tradeoff. #+BEGIN_SRC emacs-lisp (if (version<= "27.1" emacs-version) ((setq bidi-inhibit-bpa t) (global-so-long-mode 1))) #+END_SRC Ref: https://200ok.ch/posts/2020-09-29_comprehensive_guide_on_handling_long_lines_in_emacs.html *** sentence end Semi related to the above, make the sentence endings a bit more code-ish. #+BEGIN_SRC emacs-lisp (custom-set-variables '(sentence-end "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*") '(sentence-end-double-space nil) ) #+END_SRC *** default tab-width Two seems sensible, cause well, tabs are evil incarnate. Lets use a tab width of 2 by default. #+BEGIN_SRC emacs-lisp (custom-set-variables '(default-tab-width 2)) #+END_SRC *** whitespace Customize whitespace mode to make tabs obvious as boxes, and to highlight lines over 80 characters in length. #+BEGIN_SRC emacs-lisp (require 'whitespace) (setq whitespace-style '(face tabs trailing)) (set-face-attribute 'whitespace-tab nil :foreground "#2075c7" :background "lightgrey") (set-face-attribute 'whitespace-line nil :foreground "#2075c7" :background "lightgrey") #+END_SRC *** uncategorized I have no idea how to label these. Highlight parens. #+BEGIN_SRC emacs-lisp (show-paren-mode) #+END_SRC Typing out *yes* or *no* is stupid. #+BEGIN_SRC emacs-lisp (fset 'yes-or-no-p 'y-or-n-p) #+END_SRC Disable the stupid prompt added in 23.2 that asks if you want to kill a buffer with a process attached. Yes, obviously, shut up and do it. #+BEGIN_SRC emacs-lisp (setq kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)) #+END_SRC TESTING tooltip mode Puts all tooltips in the echo arear. #+BEGIN_SRC emacs-lisp (tooltip-mode -1) (custom-set-variables '(tooltip-use-echo-area t)) #+END_SRC TESTING redisplay Have emacs not redraw the display before processing input events. #+BEGIN_SRC emacs-lisp (custom-set-variables '(redisplay-dont-pause t)) #+END_SRC *** osx specific **** no yes-or-no gui windows On osx, don't ever display the gui dialog box. Taken from http://superuser.com/questions/125569/how-to-fix-emacs-popup-dialogs-on-mac-os-x #+BEGIN_SRC emacs-lisp (when (and on-osx (window-system)) (defadvice yes-or-no-p (around prevent-dialog activate) "Prevent yes-or-no-p from activating a dialog" (let ((use-dialog-box nil)) ad-do-it)) (defadvice y-or-n-p (around prevent-dialog-yorn activate) "Prevent y-or-n-p from activating a dialog" (let ((use-dialog-box nil)) ad-do-it)) ) #+END_SRC **** make osx gui emacs keyboard setup match console Command should be meta on cocoa emacs like the old carbon/macports version. #+BEGIN_SRC emacs-lisp (when (and on-osx (window-system)) (custom-set-variables '(mac-command-key-is-meta t) '(mac-option-key-is-meta nil) '(mac-command-key-is-meta t) '(mac-command-modifier 'meta) '(mac-option-modifier 'none) ) ) #+END_SRC *** global key bindings Global key bindings. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-x ,") 'kill-whole-line) (global-set-key (kbd "C-x C-m") 'compile) #+END_SRC *** x copy/paste #+BEGIN_SRC emacs-lisp (when (and on-linux (window-system)) (progn (setq interprogram-paste-function 'x-cut-buffer-or-selection-value) (setq x-select-enable-clipboard t) ) ) #+END_SRC * appearance *** gui When i'm running in a terminal emacs, most of this junk isn't needed. For that matter gui counts for most. Basically, never show the tool bar or the scroll bar in gui or tty. In gui its ok to show the menu-bar. Also have the scratch buffer be empty instead of have the derp message I never read anyway. #+BEGIN_SRC emacs-lisp (tool-bar-mode -1) (scroll-bar-mode -1) (when (not window-system) (menu-bar-mode -1)) (custom-set-variables '(initial-scratch-message nil)) #+END_SRC *** TODO fonts setup doesn't work :broken: List of fonts in order of preference. Set preferred font list when we're in a gui emacs session. TODO is this doesn't loop through the gui fonts right and set based on the alist order of the first matching font in macos. #+BEGIN_SRC emacs-lisp :tangle no (defvar my/gui-fonts '( "ComicCode" "Comic Code" "PragmataPro" "Pragmata Pro" ;; Seems to register differently on osx than X "Source Code Pro" "Menlo" "Monaco" ) ) (with-no-warnings (when window-system (if (find-font (font-spec :name (car my/gui-fonts))) (progn (set-frame-font (car my/gui-fonts)) (set-face-attribute 'default nil :height 180)) (progn (set-gui-font (cdr my/gui-fonts)))) ) ) #+END_SRC *** tty Enable mouse mode for the console and use the mousewheel if possible. #+BEGIN_SRC emacs-lisp (unless window-system (require 'mouse) (xterm-mouse-mode t) (global-set-key [mouse-4] '(lambda () (interactive) (scroll-down 1))) (global-set-key [mouse-5] '(lambda () (interactive) (scroll-up 1))) (defun track-mouse (e)) ) #+END_SRC * packages All the packages I use. *** editorconfig If editorconfig is around use it. #+BEGIN_SRC emacs-lisp (use-package editorconfig :ensure t :config (editorconfig-mode 1)) #+END_SRC *** tramp #+BEGIN_SRC emacs-lisp (use-package tramp :defer t :custom (tramp-default-method "ssh") :config (add-to-list 'tramp-default-proxies-alist '(".*" "\`root\'" "/ssh:%h:")) ) #+END_SRC *** exec-path-from-shell Turns out that someone wrote this exact thing already. Yay get to drop my own crap. #+BEGIN_SRC emacs-lisp (use-package exec-path-from-shell :ensure t :init (if on-osx (exec-path-from-shell-initialize)) ) #+END_SRC *** osx-clipboard-mode #+BEGIN_SRC emacs-lisp (when on-osx (use-package osx-clipboard :ensure t :config (progn (osx-clipboard-mode +1) ) ) ) #+END_SRC *** spaceline theme Just use the silly spacemacs smart modeline theme cause I'm lazy. #+BEGIN_SRC emacs-lisp :tangle no (use-package spaceline :ensure t :init (progn (require 'spaceline-config) (spaceline-spacemacs-theme))) #+END_SRC *** yasnippet #+BEGIN_SRC emacs-lisp (use-package yasnippet :diminish yas-minor-mode :ensure t :init (setq yas-snippet-dirs '("~/.emacs.d/snippets" "~/.emacs.d/snippets-upstream" )) :config (yas/reload-all) (add-hook 'prog-mode-hook '(lambda () (yas-minor-mode))) (add-hook 'org-mode-hook '(lambda () (yas-minor-mode))) ) #+END_SRC *** semantic Note that not all these functions are defined at package install time #+BEGIN_SRC emacs-lisp (use-package semantic :ensure t :config ;; (add-to-list 'semantic-default-submodes 'global-semantic-stickyfunc-mode) (custom-set-variables '(global-semantic-decoration-mode t) '(global-semantic-highlight-func-mode t) '(global-semantic-idle-scheduler-mode t) '(global-semantic-idle-local-symbol-highlight-mode t) ) :init (semantic-mode t) ) #+END_SRC *** expand-region #+BEGIN_SRC emacs-lisp (use-package expand-region :ensure t :bind ("C-]" . er/expand-region)) #+END_SRC *** ivy/swiper/projectile Switching to ivy mode+swiper #+BEGIN_SRC emacs-lisp (use-package projectile :diminish projectile-mode :ensure t :init (projectile-global-mode) ) (use-package counsel :ensure t :bind (("C-x C-f" . counsel-find-file) ("C-c g" . counsel-git) ("C-c j" . counsel-git-grep) ("C-c k" . counsel-ag) ("C-x l" . counsel-locate) ("C-S-o" . counsel-rhythmbox) ("C-c C-r" . ivy-resume)) :custom (counsel-find-file-at-point t) ) (use-package swiper :ensure t :diminish ivy-mode :bind (("C-s" . swiper) ("M-x" . counsel-M-x)) :config (ivy-mode 1) :custom (projectile-completion-system 'ivy) (magit-completing-read-function 'ivy-completing-read) (ivy-use-virtual-buffers t) (ivy-height 10) (ivy-count-format "(%d/%d) ") ) #+END_SRC *** magit Make git not ass to use. At least in emacs. magit is the best git interface... in the world. #+BEGIN_SRC emacs-lisp (use-package magit :diminish magit-mode :ensure t :commands (magit-init magit-status magit-diff magit-commit) :bind ("C-x m" . magit-status) :custom (magit-auto-revert-mode nil) (magit-last-seen-setup-instructions "1.4.0") :config (defadvice magit-status (around magit-fullscreen activate) (window-configuration-to-register :magit-fullscreen) ad-do-it (delete-other-windows)) (defadvice magit-quit-window (around magit-restore-screen activate) ad-do-it (jump-to-register :magit-fullscreen)) ) #+END_SRC *** TODO workgroups2 :broken: Save workgroup layouts. Similar..ish to desktop-save. #+BEGIN_SRC emacs-lisp :tangle no (use-package workgroups2 :ensure t :diminish (workgroups-mode . "") :custom (wg-session-file "~/.emacs.d/workgroups") (wg-prefix-key (kbd "C-c C-w")) (wg-mode-line-display-on nil) :init (workgroups-mode 1) ) #+END_SRC *** autopair Highlight matching ()'s []'s etc... #+BEGIN_SRC emacs-lisp (use-package autopair :ensure t :custom (autopair-blink 'nil) ) #+END_SRC *** TODO org-mode :validation:testing: Org-mode keybindings and settings, pretty sparse really. Todo is to figure out what needs to happen for the capture templates and validate the agenda changes. #+BEGIN_SRC emacs-lisp (use-package org :ensure t :bind (("C-c a" . org-agenda) ("C-c b" . org-iswitchb) ("C-c c" . org-capture) ("C-c l" . org-store-link) ("C-c p" . org-latex-export-to-pdf)) :custom (org-agenda-span 'fortnight) (org-log-done t) (org-hide-leading-stars t) (org-hide-emphasis-markers t) (org-confirm-babel-evaluate nil) (org-src-strip-leading-and-trailing-blank-lines t) (org-src-preserve-indentation t) (org-directory "~/src/org") (org-archive-directory "~/src/org/attic") (org-default-notes-file (concat org-directory "/notes.org")) ;; Ref https://orgmode.org/manual/Template-elements.html for more detail. (org-agenda-files (list "~/src/org" "~/src/git.functionalidiot.com/mitchty/dotfiles")) (org-capture-templates '( ("d" "deadline" entry (file+headline org-default-notes-file "Todos") "* PRIO %? \nDEADLINE: %t" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("t" "todo" entry (file+headline org-default-notes-file "Todos") "* TODO %?\n %i\n %a\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("n" "note" entry (file+headline org-default-notes-file "Notes") "\n* %?\nRandom Note entered on %U\n %i\n %a\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("m" "email todo" entry (file+headline org-default-notes-file "Inbox") "\n* TODO %?, Link: %a\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("u" "urls" entry (file+headline org-default-notes-file "Urls") "\n* %? :url:\n%i\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("i" "interruption" entry (file+headline org-default-notes-file "Interruptions") "\n* BLOCKED by %? :BLOCKED:\n%t" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("j" "journal" entry (file (concat org-directory "/journal.org")) "* %?\n%U\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) )) :config (add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC" "")) (add-to-list 'org-structure-template-alist '("hs" "#+BEGIN_SRC haskell\n?\n#+END_SRC" "")) (add-to-list 'org-structure-template-alist '("pl" "#+BEGIN_SRC perl\n?\n#+END_SRC" "")) (add-to-list 'org-structure-template-alist '("py" "#+BEGIN_SRC python\n?\n#+END_SRC" "")) (add-to-list 'org-structure-template-alist '("sh" "#+BEGIN_SRC sh\n?\n#+END_SRC" "")) (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '( (C . t) (ditaa . t) (emacs-lisp . t) (haskell . t) (latex . t) (perl . t) (python . t) (ruby . t) (shell . t) ))) (add-hook 'after-init-hook (lambda () (org-reload))) ) #+END_SRC **** TODO Org-roam testing :validation: DEADLINE: <2020-09-11 Fri> :LOGBOOK: CLOCK: [2020-09-07 Mon 10:59]--[2020-09-07 Mon 11:00] => 0:01 :END: Figure out how the hell to use this thing. Ref: - https://github.com/org-roam/org-roam - https://www.orgroam.com/manual/ #+BEGIN_SRC emacs-lisp :tangle no (use-package org-roam :after org :ensure t :hook (after-init . org-roam-mode) :custom (org-roam-directory "~/src/org/roam") :bind (:map org-roam-mode-map (("C-c n l" . org-roam) ("C-c n f" . org-roam-find-file) ("C-c n g" . org-roam-graph-show)) :map org-mode-map (("C-c n i" . org-roam-insert)) (("C-c n I" . org-roam-insert-immediate)))) #+END_SRC **** TODO org babel ob-async testing :validation: Validate that this installs from scratch fine, blocking babel executions is ass. #+BEGIN_SRC emacs-lisp (use-package ob-async :after org :ensure t) #+END_SRC **** TODO org-habit customization :testing: Figure out the customization needed here. #+BEGIN_SRC emacs-lisp (use-package org-habit :after org :diminish :custom (org-habit-graph-column 44) (org-habit-preceding-days 31) (org-habit-following-days 7)) #+END_SRC **** TODO org-bullets review if alternative is worth it :validation: https://github.com/integral-dw/org-superstar-mode #+BEGIN_SRC emacs-lisp (use-package org-bullets :after org :ensure t :custom (org-bullets-bullet-list '("①" "②" "③" "④" "⑤")) :config (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))) (when window-system (let* ((variable-tuple (cond ((x-list-fonts "Source Sans Pro") '(:font "Source Sans Pro")) ((x-list-fonts "Lucida Grande") '(:font "Lucida Grande")) ((x-list-fonts "Verdana") '(:font "Verdana")) ((x-family-fonts "Sans Serif") '(:family "Sans Serif")) (nil (warn "Cannot find a Sans Serif Font.")))) (base-font-color (face-foreground 'default nil 'default)) (headline `(:inherit default :weight bold :foreground ,base-font-color))) (custom-theme-set-faces 'user `(org-level-8 ((t (,@headline ,@variable-tuple)))) `(org-level-7 ((t (,@headline ,@variable-tuple)))) `(org-level-6 ((t (,@headline ,@variable-tuple)))) `(org-level-5 ((t (,@headline ,@variable-tuple)))) `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1)))) `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.25)))) `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.5)))) `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.75)))) `(org-document-title ((t (,@headline ,@variable-tuple :height 1.5 :underline nil))))))) (font-lock-add-keywords 'org-mode '(("^ +\\([-*]\\) " (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) ) #+END_SRC **** TODO Keep ox-latex in org setup? :validation:broken: Its tangle is set to no... #+BEGIN_SRC emacs-lisp :tangle no (require 'ox-latex) ox-latex (unless (boundp 'org-latex-classes) (setq org-latex-classes nil)) nil (add-to-list 'org-latex-classes '("article" "\\documentclass{article}" ("\\section{%s}" . "\\section*{%s}"))) #+END_SRC *** flycheck Flycheck for on the fly checking of code. #+BEGIN_SRC emacs-lisp (use-package flycheck :diminish flycheck-mode :ensure t :custom (flycheck-indication-mode 'left-fringe) :config (add-hook 'prog-mode-hook 'flycheck-mode) ) #+END_SRC **** TODO pkg-config lib stuff for flycheck :broken: Need to vet this, used it more when I did more c. But its handy for non standard pkg-config setups. Not tangled into the config intentionally. #+BEGIN_SRC emacs-lisp :tangle no (defun pkg-config-add-lib-cflags (pkg-config-lib) "This function will add necessary header file path of a specified by `pkg-config-lib' to `flycheck-clang-include-path', which make it completionable by auto-complete-clang" (interactive "spkg-config lib: ") (if (executable-find "pkg-config") (if (= (shell-command (format "pkg-config %s" pkg-config-lib)) 0) (setq flycheck-clang-include-path (append flycheck-clang-include-path (split-string (shell-command-to-string (format "pkg-config --cflags-only-I %s" pkg-config-lib))))) (message "Error, pkg-config lib %s not found." pkg-config-lib)) (message "Error: pkg-config tool not found."))) #+END_SRC *** TODO auto-complete not tangled :validation:broken: Auto complete functionality is nice to have. #+BEGIN_SRC emacs-lisp :tangle no (use-package auto-complete :diminish auto-complete-mode :ensure t :init (require 'auto-complete-config) (ac-config-default) (global-auto-complete-mode t) ) #+END_SRC *** smartparens Helpfully inserts matching parens, can be a pita too. #+BEGIN_SRC emacs-lisp (use-package smartparens :diminish smartparens-mode :ensure t :config (add-hook 'prog-mode-hook 'smartparens-mode) ) #+END_SRC *** rainbow delimiters Makes matching parens easier. #+BEGIN_SRC emacs-lisp (use-package rainbow-delimiters :ensure t :config (add-hook 'prog-mode-hook 'rainbow-delimiters-mode) ) #+END_SRC *** uniquify Make buffer names unique based on their directory and not have or other nonsense. #+BEGIN_SRC emacs-lisp (require 'uniquify) (custom-set-variables '(uniquify-buffer-name-style 'post-forward)) #+END_SRC *** desktop-save Desktop saving of session information handy to keep the same buffers between sessions. #+BEGIN_SRC emacs-lisp (require 'desktop) (desktop-save-mode 1) (custom-set-variables '(desktop-restore-eager 5) '(desktop-path '("~/.emacs.d")) '(desktop-dirname "~/.emacs.d") '(desktop-base-file-name "desktop") ) (defun local-desktop-save () (interactive) (if (eq (desktop-owner) (emacs-pid)) (desktop-save desktop-dirname))) #+END_SRC *** TODO super-save :validation:testing: REMOVE ME && TODO IF THIS WORKS Saves buffers like with auto-save but on focus loss, when idle etc... #+BEGIN_SRC emacs-lisp (use-package super-save :diminish super-save-mode :ensure t :config (super-save-mode +1) (setq super-save-auto-save-when-idle t) (setq auto-save-default nil) ) #+END_SRC *** TODO fic-mode :broken: Highlight TODO/FIXME type messages in comments. #+BEGIN_SRC emacs-lisp :tangle no (use-package fic-mode :ensure t :init (add-hook 'prog-mode-hook 'turn-on-fic-mode) ) #+END_SRC *** git gutter #+BEGIN_SRC emacs-lisp (use-package git-gutter :diminish git-gutter-mode :ensure t :config (global-git-gutter-mode t) ) #+END_SRC *** clang-format #+BEGIN_SRC emacs-lisp (use-package clang-format :ensure t :bind (([C-M-tab] . clang-format-region)) ) #+END_SRC *** hideshow #+BEGIN_SRC emacs-lisp (use-package hideshow :ensure t :bind ("C-c s" . hs-toggle-hiding) ) #+END_SRC *** TODO ggtags :broken: #+BEGIN_SRC emacs-lisp :tangle no (use-package ggtags :ensure t) #+END_SRC *** TODO company-mode :broken: Completion tips. #+BEGIN_SRC emacs-lisp :tangle no (use-package company-mode :ensure t :config (add-hook 'after-init-hook 'global-company-mode) ) #+END_SRC *** yaml-mode For.. yaml #+BEGIN_SRC emacs-lisp (use-package yaml-mode :ensure t) #+END_SRC *** writegood-mode So I write gooder. Me fail English? Thats unpossible. #+BEGIN_SRC emacs-lisp (use-package writegood-mode :ensure t) #+END_SRC *** rust-mode #+BEGIN_SRC emacs-lisp (use-package rust-mode :commands rust-mode :mode ("\\*.rs\\'" . rust-mode) :defer t) #+END_SRC *** TODO python-mode :broken: Compress down python configuration a bit. #+BEGIN_SRC emacs-lisp :tangle no (use-package python :after company-mode :commands python-mode :mode ("\\.py\\'" . python-mode) :config (add-hook 'python-mode-hook' (lambda () (push '("lambda" . ?λ) prettify-symbols-alist) (push '("<=" . ?≤) prettify-symbols-alist) (push '(">=" . ?≥) prettify-symbols-alist) (push '("==" . ?≡) prettify-symbols-alist) (push '("/=" . ?≢) prettify-symbols-alist) (push '("&&" . ?∧) prettify-symbols-alist) (push '("||" . ?∨) prettify-symbols-alist) (push '("not" . ?¬) prettify-symbols-alist) (push '("None" . ?⊥) prettify-symbols-alist) (prettify-symbols-mode) ) ) ) (use-package company-anaconda :after python :config (add-to-list 'company-backends 'company-anaconda) (add-hook 'python-mode-hook 'anaconda-mode) ) (use-package pytest :after python :bind ("C-c t" . pytest-one) ) (use-package pymacs :after python) #+END_SRC *** haskell-mode Need to make haskell source be all pretty. #+BEGIN_SRC emacs-lisp (use-package haskell-mode :defer t :diminish haskell-mode :config (add-hook 'haskell-mode-hook 'interactive-haskell-mode) (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation) (add-hook 'haskell-mode-hook' (lambda () (push '("()" . ?∅) prettify-symbols-alist) (push '("\\" . ?λ) prettify-symbols-alist) (push '("pi" . ?π) prettify-symbols-alist) (push '("=>" . ?⇒) prettify-symbols-alist) (push '("->" . ?→) prettify-symbols-alist) (push '("<-" . ?←) prettify-symbols-alist) (push '("<=" . ?≤) prettify-symbols-alist) (push '(">=" . ?≥) prettify-symbols-alist) (push '("==" . ?≡) prettify-symbols-alist) (push '("/=" . ?≢) prettify-symbols-alist) (push '("!!" . "‼") prettify-symbols-alist) (push '("&&" . ?∧) prettify-symbols-alist) (push '("||" . ?∨) prettify-symbols-alist) (push '("~>" . ?⇝) prettify-symbols-alist) (push '("-<" . ?↢) prettify-symbols-alist) (push '("not" . ?¬) prettify-symbols-alist) (push '("forall" . ?∀) prettify-symbols-alist) (push '("sqrt" . ?√) prettify-symbols-alist) (push '("undefined" . ?⊥) prettify-symbols-alist) (prettify-symbols-mode) ) ) (add-to-list 'completion-ignored-extensions ".hi") :custom (haskell-program-name "ghci") (haskell-process-type 'cabal-repl) (haskell-tags-on-save t) ) (use-package dante :after haskell-mode :diminish dante-mode :config (add-hook 'haskell-mode-hook 'dante-mode) ) (use-package hindent :if (executable-find "hindent") :diminish hindent-mode :after haskell-mode :config (add-hook 'haskell-mode-hook 'hindent-mode) ) (use-package flycheck-haskell :after haskell-mode) (use-package flycheck-hdevtools :after haskell-mode :config (add-hook 'haskell-mode-hook 'flycheck-mode) ) (use-package ghc :if (executable-find "ghc-mod") :after haskell-mode :config (autoload 'ghc-init "ghc" nil t) (autoload 'ghc-debug "ghc" nil t) (add-hook 'haskell-mode-hook (lambda () (ghc-init))) ) #+END_SRC *** idris-mode #+BEGIN_SRC emacs-lisp (use-package idris-mode :defer t :config (add-to-list 'completion-ignored-extensions ".ibc") (add-hook 'idris-mode-hook' (lambda () (push '("()" . ?∅) prettify-symbols-alist) (push '("\\" . ?λ) prettify-symbols-alist) (push '("pi" . ?π) prettify-symbols-alist) (push '("=>" . ?⇒) prettify-symbols-alist) (push '("->" . ?→) prettify-symbols-alist) (push '("<-" . ?←) prettify-symbols-alist) (push '("<=" . ?≤) prettify-symbols-alist) (push '(">=" . ?≥) prettify-symbols-alist) (push '("==" . ?≡) prettify-symbols-alist) (push '("/=" . ?≢) prettify-symbols-alist) (push '("!!" . "‼") prettify-symbols-alist) (push '("&&" . ?∧) prettify-symbols-alist) (push '("||" . ?∨) prettify-symbols-alist) (push '("~>" . ?⇝) prettify-symbols-alist) (push '("-<" . ?↢) prettify-symbols-alist) (push '("not" . ?¬) prettify-symbols-alist) (push '("forall" . ?∀) prettify-symbols-alist) (push '("sqrt" . ?√) prettify-symbols-alist) (push '("undefined" . ?⊥) prettify-symbols-alist) (prettify-symbols-mode) ) ) ) #+END_SRC *** undo-tree Make undo more useful, and treelike. #+BEGIN_SRC emacs-lisp (use-package undo-tree :ensure t :config (global-undo-tree-mode) (defadvice undo-tree-visualize (around undo-tree-split-side-by-side activate) "Split undo-tree side-by-side" (let ((split-height-threshold nil) (split-width-threshold 0)) ad-do-it) ) :bind ("C-x u" . undo-tree-visualize) ) #+END_SRC *** color-identifiers-mode Color variables for easy identification, its like a rainbow puked over everything opened in prog-mode-hook. #+BEGIN_SRC emacs-lisp (use-package color-identifiers-mode :defer t :diminish color-identifiers-mode :config (add-hook 'prog-mode-hook 'color-identifiers-mode) ) #+END_SRC *** idle-highlight-mode Highlight a variable when you're selecting it, helps in reviewing code to see where it exists. #+BEGIN_SRC emacs-lisp (use-package idle-highlight-mode :defer t :diminish idle-highlight-mode :config (add-hook 'prog-mode-hook 'idle-highlight-mode) ) #+END_SRC *** nix Instead of text might as well get a decent mode hook going here. #+BEGIN_SRC emacs-lisp (use-package nixos-options :defer t) (use-package company-nixos-options :after company :defer t) #+END_SRC **** TODO nix-mode :broken: #+BEGIN_SRC emacs-lisp :tangle no (use-package nix-mode :config (setq flycheck-command-wrapper-function (lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command)) flycheck-executable-find (lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd))) (add-to-list 'company-backends 'company-nixos-options) ) #+END_SRC *** docker-mode #+BEGIN_SRC emacs-lisp (use-package dockerfile-mode :defer t) #+END_SRC *** TODO cscope or rtags or nuke :testing:validation: Switch to rtags, or maybe even nuke entirely? #+BEGIN_SRC emacs-lisp (use-package xcscope :defer t :config (cscope-setup)) #+END_SRC *** TODO ag :validation: #+BEGIN_SRC emacs-lisp (use-package ag :defer t) #+END_SRC * mode related *** common defaults Common mode defaults I think are sensible. ***** TODO prog-mode hooks to use-package :broken: ALl this crap should be moved into use-package declarations. #+BEGIN_SRC emacs-lisp (add-hook 'prog-mode-hook '(lambda () (interactive) (hl-line-mode) (whitespace-mode) (visual-line-mode) (flyspell-prog-mode) (custom-set-variables '(indent-tabs-mode nil) '(tab-width 2) ) ) ) #+END_SRC ***** c #+BEGIN_SRC emacs-lisp (add-to-list 'auto-mode-alist '("\\.[chm]\\'" . c-mode)) (add-hook 'c-mode-common-hook '(lambda () (global-set-key "\C-x\C-m" 'compile) (setq flycheck-clang-language-standard "c11") (setq flycheck-idle-change-delay 2) (setq flycheck-highlighting-mode 'symbols) ;; later... ;; (add-hook 'before-save-hook 'clang-format-buffer nil t) (c-toggle-auto-state 1) (setq-default c-basic-offset 2 tab-width 2 indent-tabs-mode nil c-electric-flag t indent-level 2 c-default-style "bsd" backward-delete-function nil) )) #+END_SRC ***** TODO elisp :broken: Why is this broken? Figure out why its tangle is no. #+BEGIN_SRC emacs-lisp :tangle no (add-hook 'emacs-lisp-hook (lambda () (define-key emacs-lisp-map "\C-x\C-e" 'pp-eval-last-sexp) (define-key emacs-lisp-map "\r" 'reindent-then-newline-and-indent))) #+END_SRC ***** python-mode #+BEGIN_SRC emacs-lisp (add-hook 'python-mode-hook '(lambda () (flycheck-select-checker 'python-flake8) ) ) #+END_SRC ***** shell #+BEGIN_SRC emacs-lisp (autoload 'sh--mode "sh-mode" "mode for shell stuff" t) (add-to-list 'auto-mode-alist '("\\.sh$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\.[zk]sh$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\.bash$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\[.].*shrc$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("sourceme$\\'" . sh-mode)) (add-hook 'sh-mode-hook '(lambda () (setq sh-basic-offset 2 sh-indentation 4 sh-indent-for-case-label 0 sh-indent-for-case-alt '+))) #+END_SRC ***** perl #+BEGIN_SRC emacs-lisp (fset 'perl-mode 'cperl-mode) (add-hook 'cperl-mode-hook '(lambda () (setq indent-tabs-mode t) (setq tab-width 8) (setq cperl-indent-level 4) (setq tab-stop-list (number-sequence 4 200 4)) (setq cperl-tab-always-indent t) (setq cperl-indent-parens-as-block t) ) ) #+END_SRC *** TODO auto-insert-mode new file templates :broken: Review if this is worth keeping around, methinks there should be something better like yasnippet out there, this is all old af hacks Use auto-insert-mode to insert in templates for blank files. So first up, add auto-insert to *find-file-hooks* so we insert straight away. Also setup the copyright bit to minimally put in name. #+BEGIN_SRC emacs-lisp (add-hook 'find-file-hooks 'auto-insert) (defvar auto-insert-copyright (user-full-name)) #+END_SRC Create *auto-insert-alist* so all the mode lists are the same #+BEGIN_SRC emacs-lisp (defvar auto-insert-alist '(())) #+END_SRC ***** c #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((c-mode . "c") nil "/*\n" "File: " (file-name-nondirectory buffer-file-name) "\n" "Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "Description: " _ "\n" "*/\n" "#include \n" "#include \n\n" "int main(int argc, char **argv) {\n" " return 0;\n" "}\n" ) ) auto-insert-alist) ) #+END_SRC ***** elisp #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((emacs-lisp-mode . "elisp") nil ";;-*-mode: emacs-lisp; coding: utf-8;-*-\n" ";; File: " (file-name-nondirectory buffer-file-name) "\n" ";; Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" ";; Description: " _ "\n" ) ) auto-insert-alist) ) #+END_SRC ***** python #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '(((python-mode . "python") nil "#!/usr/bin/env python\n" "# -*-mode: Python; coding: utf-8;-*-\n" "# File: " (file-name-nondirectory buffer-file-name) "\n" "# Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "# Description: " _ "\n\n" ) ) auto-insert-alist) ) #+END_SRC ***** shell #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((sh-mode . "sh") nil "#!/usr/bin/env sh\n" "#-*-mode: Shell-script; coding: utf-8;-*-\n" "# File: " (file-name-nondirectory buffer-file-name) "\n" "# Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "# Description: " _ "\n" "_base=$(basename \"$0\")\n" "_dir=$(cd -P -- \"$(dirname -- \"$(command -v -- \"$0\")\")\" && pwd -P || exit 126)\n" "export _base _dir\n" ) ) auto-insert-alist) ) #+END_SRC * custom Load this up last to allow for local customization if needed and to keep from custom writing to the init.el file. #+BEGIN_SRC emacs-lisp (setq custom-file "~/.emacs.d/custom.el") (load custom-file 'noerror) #+END_SRC * TODO Load any local definitions :broken: Probably need to check if this file exists first... #+BEGIN_SRC emacs-lisp :tangle no (load-file "~/.emacs.d/local.el") #+END_SRC