Mats Kjesrud - Emacs configuration

Information

The complete repository is available on Github: https://github.com/makjes/.emacs.d

Initialize

UTF-8

(prefer-coding-system 'utf-8)

Using a norwegian keyboard on linux may cause issues with dead keys. iso-transl fixes that.

(require 'iso-transl)

Package manager setup

Package sources

(require 'cl)
(require 'package)

(defvar gnu '("gnu" . "http://elpa.gnu.org/packages/"))
(defvar melpa '("melpa" . "http://melpa.org/packages/"))
(defvar melpa-stable '("melpa-stable" . "http://stable.melpa.org/packages/"))

(package-initialize)

(setq package-archives nil)
(add-to-list 'package-archives melpa-stable t)
(add-to-list 'package-archives melpa t)
(add-to-list 'package-archives gnu t)

(unless (and (file-exists-p "~/.emacs.d/elpa/archives/gnu")
             (file-exists-p "~/.emacs.d/elpa/archives/melpa")
             (file-exists-p "~/.emacs.d/elpa/archives/melpa-stable"))
  (package-refresh-contents))

Setup use-package

(unless (package-installed-p 'use-package)
  (package-install 'use-package))

(setq use-package-always-ensure t)
(require 'use-package)

(use-package auto-compile
  :config (auto-compile-on-load-mode))

Change autosave directory

(setq emacs-autosave-directory "~/.emacs.d/autosaves/")
(setq backup-directory-alist
      `((".*" . ,emacs-autosave-directory))
      auto-save-file-name-transforms
      `((".*" ,emacs-autosave-directory t)))

Reload buffers on file change

Reload buffers when files change outside emacs.

(global-auto-revert-mode t)
(diminish 'auto-revert-mode)

Load secrets

(load "~/Dropbox/secrets.el")

Navigation

Hydra

(use-package hydra
  :bind (("<f4>" . mk/hydra-macro/body)
         ("C-c i" . mk/hydra-indirect-buffers/body)
         ("C-x SPC" . mk/hydra-rectangle/body)
         ("C-c t" . mk/hydra-theme/body)
         ("C-c j" . mk/hydra-ace-jump/body)
         ("C-c g" . mk/hydra-qol/body)
         ("C-c u" . mk/hydra-case/body)
         ("C-c h" . mk/hydra-help/body)))

Hydra helper

(defhydra mk/hydra-help (:hint nil)
  "
  Hydra helper
  ------------
  _<f4>_    : Macros
  C-c _g_   : Google translate & Search engines
  C-c _i_   : Org indirect buffers
  C-c _j_   : Jump & Multiple cursors
  C-c _t_   : Themes
  C-c _u_   : Capitalization
  C-x _SPC_ : Rectangle mode
  "
  ("<f4>" mk/hydra-macro/body :exit t)
  ("i" mk/hydra-indirect-buffers/body :exit t)
  ("SPC" mk/hydra-rectangle/body :exit t)
  ("t" mk/hydra-theme/body :exit t)
  ("j" mk/hydra-ace-jump/body :exit t)
  ("g" mk/hydra-qol/body :exit t)
  ("u" mk/hydra-case/body :exit t))

Macros

I really want to use macros more, and making a hydra for it will help me remember to use it.

(defhydra mk/hydra-macro ()
  "Keyboard Macro"
  ("d" kmacro-start-macro "Define" :exit t)
  ("e" kmacro-end-macro "End")
  ("c" kmacro-call-macro "Call")
  ("i" kmacro-insert-counter "Insert counter" :exit t))

Rectangle Mode

  (defhydra mk/hydra-rectangle (:body-pre (rectangle-mark-mode 1) :post (deactivate-mark))
    "
    -----          |   ^_p_^   |    _d_elete    _k_ill
Rectangle Mode     | _b_   _f_ |    _s_tring    _y_ank
    -----          |   ^_n_^   |    _c_opy      _r_eset"
    ("p" rectangle-previous-line nil)
    ("n" rectangle-next-line nil)
    ("b" rectangle-backward-char nil)
    ("f" rectangle-forward-char nil)
    ("d" delete-rectangle nil)
    ("s" string-rectangle nil :exit t)
    ("k" kill-rectangle nil)
    ("y" yank-rectangle nil :exit t)
    ("c" copy-rectangle-as-kill nil)
    ("r" (progn (if (region-active-p)
                    (deactivate-mark))
                (rectangle-mark-mode 1)) nil))

Ace Window

(use-package ace-window)

Ace Jump & Multiple Cursors

(use-package ace-jump-mode)
(use-package ace-mc)

(defhydra mk/hydra-ace-jump ()
  "
  --    _w_ : Word   |       --------       _W_ : Word
 Jump   _l_ : Line   |   Multiple Cursors   _L_ : Line
  --    _c_ : Char   |       --------       _C_ : Char
        _p_ : Pop    |                      _s_ : Selected lines
        ^^                                  _i_ : iEdit
"
  ("w" ace-jump-word-mode nil :exit t)
  ("l" ace-jump-line-mode nil :exit t)
  ("c" ace-jump-char-mode nil :exit t)
  ("W" ace-mc-add-multiple-cursors nil :exit t)
  ("L" (progn
         (move-beginning-of-line 1)
         (setq current-prefix-arg '(16)) ; C-u C-u
         (call-interactively 'ace-mc-add-multiple-cursors)) nil :exit t)
  ("C" (progn
         (setq current-prefix-arg '(4)) ; C-u
         (call-interactively 'ace-mc-add-multiple-cursors)) nil :exit t)
  ("p" ace-jump-mode-pop-mark nil :exit t)
  ("i" iedit-mode :exit t)
  ("s" (call-interactively 'mc/edit-lines) nil :exit t))

Helm

(use-package helm
  :diminish helm-mode
  :init
  (require 'helm-config)
  (setq helm-ff-skip-boring-files t)
  (helm-mode)
  :bind (("C-h a" . helm-apropos)
         ("C-x C-b" . helm-mini)
         ("C-x b" . helm-mini)
         ("M-y" . helm-show-kill-ring)
         ("C-x C-f" . helm-find-files)
         ("M-x" . helm-M-x)
         ("C-s" . helm-occur)))

Swoop

(use-package helm-swoop
  :bind ("C-M-s" . mk/hydra-helm-swoop/body))

(defhydra mk/hydra-helm-swoop ()
  "Helm Swoop"
  ("s" helm-swoop "Swoop" :exit t)
  ("m" helm-multi-swoop "Multiple buffers" :exit t)
  ("a" helm-multi-swoop-all "All buffers" :exit t)
  ("o" helm-multi-swoop-org "All org-mode buffers" :exit t))

Which key

which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup. For example, after enabling the minor mode if you enter C-x and wait for the default of 1 second the minibuffer will expand with all of the available key bindings that follow C-x Github repo: justbur/emacs-which-key

(use-package which-key
  :diminish which-key-mode
  :config
  (which-key-mode))

Sometimes emacs crashes as described here: https://github.com/justbur/emacs-which-key/issues/130 Testing out workaround

(setq inhibit-compacting-font-caches nil)

Expand region

(use-package expand-region
  :ensure t
  :bind ("C-." . er/expand-region))

Custom keybindings

(defvar custom-bindings-map (make-keymap)
  "A keymap for custom bindings.")

;; Kills active buffer
(define-key custom-bindings-map (kbd "C-x k") 'kill-this-buffer)
;; Capture templates
(define-key custom-bindings-map (kbd "<f3>") 'org-capture)
;; Magit
(define-key custom-bindings-map (kbd "C-c m") 'magit-status)
;; Ace window
(define-key custom-bindings-map (kbd "C-<tab>") 'ace-window)
(define-key custom-bindings-map [remap other-window] 'ace-window)

(define-minor-mode custom-bindings-mode
  "A mode that activates custom-bindings."
  t nil custom-bindings-map)

Indirect buffers

Minor mode for indirect org-buffers

(define-minor-mode mk/org-indirect-mode
  "Toggle Org Indirect Mode"
  :lighter " mk/OIB"
  :keymap (let ((map (make-sparse-keymap)))
            (define-key map [remap kill-this-buffer] 'kill-buffer-and-window)
            map))

Hydra for easily create indirect buffers

(defhydra mk/hydra-indirect-buffers ()
  "Indirect Buffers"
  ("c" clone-indirect-buffer-other-window "Clone to other window")
  ("t" (progn (org-tree-to-indirect-buffer)
              (shrink-window-horizontally (- (window-size nil t) 50))
              (other-window 1)
              (mk/org-indirect-mode)) "Org tree to indirect buffer" :exit t)
  ("m" make-indirect-buffer "Make indirect buffer")
  ("s" (shrink-window-horizontally (- (window-size nil t) 50)) "Resize window" :exit t))

Capitalization

(defhydra mk/hydra-case (:hint nil) "
                                   Dwim^^   Previous word
     --------      |   Uppercase:  _u_      _U_
  Capitalization   |   Lowercase:  _l_      _L_                    E_x_it
     --------      |   Capitalize: _c_      _C_
  "
  ("u" upcase-dwim)
  ("l" downcase-dwim)
  ("c" capitalize-dwim)
  ("U" (upcase-word -1))
  ("L" (downcase-word -1))
  ("C" (capitalize-word -1))
  ("x" nil :exit t))

Look and feel

General emacs settings

Change some general settings

(menu-bar-mode 0) ; Turn off menu bar
(tool-bar-mode 0) ; Turn off tool bar
(scroll-bar-mode 0) ; Turn off scroll bar
(blink-cursor-mode 0) ; Stop blinking cursor
(column-number-mode 1) ; Activate column numbers
(show-paren-mode 1) ; Show matching parenthesis
(delete-selection-mode 1) ; Replace selected text
(setq inhibit-splash-screen t) ; Turn off splash screen
(setq inhibit-startup-message t) ; Turn off startup message
(setq initial-scratch-message nil) ; Clean the scratch buffer
(setq default-directory (concat (getenv "HOME") "/")) ; Set home directory as default
(fset 'yes-or-no-p 'y-or-n-p) ; Answer with y/n

Agressive indentation

(use-package aggressive-indent
  :config
  (global-aggressive-indent-mode 1))

Themeing

Load themes

(use-package darktooth-theme)
(use-package subatomic-theme)
(use-package flatui-theme)

(defvar mk/themes '(darktooth
                    subatomic
                    flatui))

;; Load themes without prompting and enabling
(mapc (lambda (x) (load-theme x t t)) mk/themes)

(defun mk/load-theme (name)
  "Switch theme"
  (progn
    ;; Load theme
    (if (boundp 'custom-enabled-themes)
        (custom-set-variables `(custom-enabled-themes '(,name)))
      (load-theme name t))
    ;; Fix hidden bullets in org-mode
    (let ((hide (face-foreground 'org-hide))
          (background (face-background 'default)))
      (if (not (equal hide background))
          (set-face-foreground 'org-hide background)))))

;; Load theme at startup
(mk/load-theme 'flatui)

Hydra for themes

(defhydra mk/hydra-theme ()
  "
Light themes:     Dark themes:      Fonts:            E_x_it
----------------  ----------------  ----------------  ----------------
_f_lat UI           _d_arktooth         _m_onospace
^^                  _s_ubatomic         _w_riting
"
  ("f" (mk/load-theme 'flatui) nil)
  ("d" (mk/load-theme 'darktooth) nil)
  ("s" (mk/load-theme 'subatomic) nil)
  ("m" (mk/set-font 'mono) nil)
  ("w" (mk/set-font 'write) nil)
  ("x" nil nil :exit t))

Download font if neccesary

My preferred monospace font is Ubuntu Mono and Futura PT for writing. Install them manually.

Load fonts

(defun mk/set-font (type)
  (if (not (eq type 'mono))
      (mk/set-mono-faces))
  (mk/set-font-on-face 'default type))

(defun mk/set-mono-faces ()
  (mk/set-font-on-face 'org-table 'mono))

(defun mk/set-font-on-face (face type)
  (cond ((eq type 'mono)
         (cond ((member "Ubuntu Mono" (font-family-list))
                (set-face-attribute face nil :font "Ubuntu Mono-13"))
               ((member "Consolas" (font-family-list))
                (set-face-attribute face nil :font "Consolas"))))
        ((eq type 'write)
         (cond ((member "Futura PT Demi" (font-family-list))
                (set-face-attribute face nil :font "Futura PT Demi-13"))
               ((member "Arial" (font-family-list))
                (set-face-attribute face nil :font "Arial"))))))

(mk/set-font 'mono)

Removed "ding"

Thanks to Arjen Wiersma for showing how to remove the ever annoying ding.

(defun mk/ring-bell-function ())
(setq ring-bell-function 'mk/ring-bell-function)
(setq visible-bell nil)

Quality of life

Google Translate

(use-package google-translate)

Engine mode

(use-package engine-mode
  :config (engine-mode t))

(defengine google
  "https://www.google.com/search?q=%s"
  :keybinding "g")

(defengine github
  "https://github.com/search?q=%s"
  :keybinding "h")

(defengine ordbok
  "http://ordbok.uib.no/perl/ordbok.cgi?OPP=+%s"
  :keybinding "o")

Hydras for QoL

(defhydra mk/hydra-qol (:hint nil) "
  Google translate^^         ^^                  Search engines
  ----------------^^         ^^                  -----------------
  _e_: English to Norwegian (_E_: @ point)       _g_: Google
  _n_: Norwegian to English (_N_: @ point)       _h_: GitHub
  _p_: Prompt for languages  ^^                  _o_: Ordbok
"
  ("e" (let ((google-translate-default-source-language "en")
             (google-translate-default-target-language "no"))
         (progn (google-translate-query-translate)
                (select-window (get-buffer-window "*Google Translate*")))) :exit t)
  ("E" (let ((google-translate-default-source-language "en")
             (google-translate-default-target-language "no"))
         (progn (google-translate-at-point)
                (select-window (get-buffer-window "*Google Translate*")))) :exit t)
  ("n" (let ((google-translate-default-source-language "no")
             (google-translate-default-target-language "en"))
         (progn (google-translate-query-translate)
                (select-window (get-buffer-window "*Google Translate*")))) :exit t)
  ("N" (let ((google-translate-default-source-language "no")
             (google-translate-default-target-language "en"))
         (progn (google-translate-at-point)
                (select-window (get-buffer-window "*Google Translate*")))) :exit t)
  ("p" (let ((google-translate-default-source-language nil)
             (google-translate-default-target-language nil))
         (progn (google-translate-query-translate)
                (select-window (get-buffer-window "*Google Translate*")))) :exit t)
  ("g" engine/search-google nil :exit t)
  ("h" engine/search-github nil :exit t)
  ("o" engine/search-ordbok nil :exit t))

Org-mode

(with-eval-after-load 'org
  (diminish 'org-indent-mode)
  (diminish 'visual-line-mode))

Visual & highligting

Activate clean indentation

(setq org-startup-indented t)
(setq org-startup-truncated nil)

Activate visual-line-mode

(add-hook 'org-mode-hook (lambda () (visual-line-mode t)))

Syntax highlighting in source blocks

(setq org-src-fontify-natively t)

Modify faces for states

(setq org-todo-keyword-faces
      '(("PRCT" . (:weight bold))
        ("GROUP" . (:weight bold))
        ("TODO" . (:weight bold))
        ("WAIT" . (:weight bold))
        ("MATR" . (:weight bold))
        ("NEXT" . (:weight bold))
        ("DONE" . (:weight bold))))

Auto completion

(use-package org-ac
  :init
  (require 'org-ac)
  (org-ac/config-default))

Key bindings

(with-eval-after-load 'org
  (bind-key "<f2>" 'org-refile org-mode-map)
  (bind-key "C-c a" 'org-agenda org-mode-map))

GTD Setup

Set agenda files

(setq org-agenda-files
      '("~/Dropbox/org/Privat.org"
        "~/Dropbox/org/NG.org"
        "~/Dropbox/org/HV.org"
        "~/Dropbox/org/UiO.org"
        "~/Dropbox/org/Nellon.org"
        "~/Dropbox/org/Habits.org"
        "~/Dropbox/org/Inbox.org"))

Set refile targets

(setq org-refile-targets
      '((nil :todo . "PRCT")
        (nil :todo . "GROUP")
        ("Privat.org" :tag . "REFILE")
        ("UiO.org" :tag . "REFILE")
        ("NG.org" :tag . "REFILE")
        ("HV.org" :tag . "REFILE")
        ("Inbox.org" :level . 1)
        ("Nellon.org" :tag . "REFILE")
        ("Habits.org" :tag . "REFILE")))

Activate logbook-drawer

(setq org-log-into-drawer "LOGBOOK")

Capture templates

A custom capture function for capturing tasks from my meeting minutes document

(defun mk/org-capture-mom ()
  (with-current-buffer (org-capture-get :original-buffer)
    (org-element-property :raw-value (org-element-at-point))))

I have a lot of capture templates. These are just a few of them. To see the complete list, check out my Github repo.

(setq org-capture-templates
      '(("t" "Todo" entry
         (file+headline "~/Dropbox/org/Inbox.org" "Inbox")
         (file "~/Dropbox/org/templates/capture-generic.org"))
        ("b" "Buy" entry
         (file+headline "~/Dropbox/org/Privat.org" "Handel")
         (file "~/Dropbox/org/templates/capture-nextaction.org") :immediate-finish t)
        ("d" "Getting Things Done")
        ("dw" "Weekly review" entry
         (file+weektree "~/Dropbox/org/archive/weekly-review.org")
         (file "~/Dropbox/org/templates/weekly-review-no.org") :immediate-finish t)
        ("di" "Empty all inboxes             (C-0 <F3> to insert at point)" entry
         (file+headline "~/Dropbox/org/Inbox.org" "Inbox")
         (file "~/Dropbox/org/templates/empty-inboxes.org") :immediate-finish t)
        ("n" "MOM Task -> Inbox" entry
         (file+headline "~/Dropbox/org/Inbox.org" "Inbox")
         (file "~/Dropbox/org/templates/momtoinbox.org") :immediate-finish t))

Habits module

(add-to-list 'org-modules 'org-habit)
(setq org-habit-preceding-days 7
      org-habit-following-days 1
      org-habit-graph-column 70
      org-habit-show-habits-only-for-today t
      org-habit-show-all-today t)

Custom Agenda views

  • Todo-items
    (defun mk/org-custom-todo (key header type files tags)
      (list key header 'todo type
            (list (list 'org-agenda-files files)
                  (list 'org-agenda-tag-filter-preset (cons 'quote (list tags)))
                  (list 'org-agenda-overriding-header header))))
    
  • Agenda list
    (defun mk/org-custom-agenda (key name tag)
      (list (concat "g" key) name 'tags-todo (concat "+" tag)
            (list (list 'org-agenda-tag-filter-preset (quote '("-SOMEDAY" "-ON_HOLD")))
                  (list 'org-agenda-overriding-header (concat "Agenda for " name)))))
    
  • Contexts
    (defun mk/org-custom-context (key name tag)
      (list (concat "c" key) name 'tags-todo (concat "+" tag)
            (list (list 'org-agenda-tag-filter-preset (quote '("-SOMEDAY" "-ON_HOLD")))
                  (list 'org-agenda-overriding-header (concat "Context: " name)))))
    
  • Maintenance
    (defvar mk/org-custom-refile
      (list "or" "Refile list" 'tags-todo "+REFILE"
            (list(list 'org-agenda-overriding-header "Refile list"))))
    
  • File lists
    (defvar mk/org-files-private
      (quote '("~/Dropbox/org/Privat.org"
               "~/Dropbox/org/UiO.org"
               "~/Dropbox/org/HV.org"
               "~/Dropbox/org/Nellon.org"
               "~/Dropbox/org/Habits.org")))
    
    (defvar mk/org-files-ng
      (quote '("~/Dropbox/org/NG.org")))
    
    (defvar mk/org-files-all
      (cons 'quote (list (append (cadr mk/org-files-ng)
                                 (cadr mk/org-files-private)))))
    
    (defvar mk/org-files-km
      (quote '("~/Dropbox/org/km.org")))
    
    (defvar mk/org-files-mom
      (quote '("~/ONEDRI~1/mom.org")))
    
  • Setup
    (setq org-agenda-custom-commands
          (list '("w" . "Work")
                (mk/org-custom-todo "wn" "Next Actions"     "NEXT" mk/org-files-ng  '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "wp" "Projects"         "PRCT" mk/org-files-ng  '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "ws" "Someday/Maybe"    "PRCT" mk/org-files-ng  '("+SOMEDAY"))
                (mk/org-custom-todo "wh" "Projects On Hold" "PRCT" mk/org-files-ng  '("+ON_HOLD"))
                (mk/org-custom-todo "ww" "Waiting For"      "WAIT" mk/org-files-ng  '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "wk" "Kms to expence"   "TODO" mk/org-files-km  '())
                (mk/org-custom-todo "wm" "TODO @ MoM"       "TODO" mk/org-files-mom '())
                '("p" . "Private")
                (mk/org-custom-todo "pn" "Next Actions"     "NEXT" mk/org-files-private '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "pp" "Projects"         "PRCT" mk/org-files-private '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "ps" "Someday/Maybe"    "PRCT" mk/org-files-private '("+SOMEDAY"))
                (mk/org-custom-todo "ph" "Projects On Hold" "PRCT" mk/org-files-private '("+ON_HOLD"))
                (mk/org-custom-todo "pw" "Waiting For"      "WAIT" mk/org-files-private '("-SOMEDAY" "-ON_HOLD"))
                '("l" . "All")
                (mk/org-custom-todo "ln" "Next Actions"     "NEXT" mk/org-files-all '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "lp" "Projects"         "PRCT" mk/org-files-all '("-SOMEDAY" "-ON_HOLD"))
                (mk/org-custom-todo "ls" "Someday/Maybe"    "PRCT" mk/org-files-all '("+SOMEDAY"))
                (mk/org-custom-todo "lh" "Projects On Hold" "PRCT" mk/org-files-all '("+ON_HOLD"))
                (mk/org-custom-todo "lw" "Waiting For"      "WAIT" mk/org-files-all '("-SOMEDAY" "-ON_HOLD"))
                '("g" . "Agenda lists")
                (mk/org-custom-agenda "p" "Per Olav" "PESPOR")
                (mk/org-custom-agenda "m" "Maria" "MACRIS")
                (mk/org-custom-agenda "j" "Jon Arne" "JOBJER")
                (mk/org-custom-agenda "a" "Marie" "MAHELL")
                (mk/org-custom-agenda "e" "Paal" "PAAL")
                (mk/org-custom-agenda "h" "Haakon" "HAHAAR")
                (mk/org-custom-agenda "o" "Johan H" "JOHANS")
                (mk/org-custom-agenda "r" "Rune S" "RUSKOG")
                (mk/org-custom-agenda "h" "Rune H" "RUHAAG")
                (mk/org-custom-agenda "l" "John" "JLO")
                '("c" . "Contexts")
                (mk/org-custom-context "s" "Shopping list" "BUY")
                (mk/org-custom-context "h" "Home" "LV34")
                (mk/org-custom-context "b" "BV9" "BV9")
                '("o" . "GTD Maintenance")
                mk/org-custom-refile))
    

Define stuck projects

(setq org-stuck-projects
      (quote ("-ON_HOLD-SOMEDAY/+PRCT"
              ("NEXT" "WAIT") nil "")))

Org export

Setting UTF-8 for exports

(setq org-export-coding-system 'utf-8)

htmlize ensures syntax highligting for org exports

(use-package htmlize)

Jira

(use-package ox-jira)

Twitter bootstrap

(use-package ox-twbs)

Github flavored markdown

(use-package ox-gfm)

Org babel settings

(org-babel-do-load-languages 'org-babel-load-languages '((python . t)
                                                         (emacs-lisp . t)
                                                         (shell . t)))

(setq org-babel-python-command "python3")

Publishing

Boilerplate for bootstrap

(defvar mk/org-twbs-pre-nav
  "<nav class=\"navbar navbar-inverse navbar-fixed-top\">
        <div class=\"container\">
          <div class=\"navbar-header\">
            <button type=\"button\" class=\"navbar-toggle collapsed\" data-toggle=\"collapse\" data-target=\"#navbar\" aria-expanded=\"false\" aria-controls=\"navbar\">
              <span class=\"sr-only\">Toggle navigation</span>
              <span class=\"icon-bar\"></span>
              <span class=\"icon-bar\"></span>
            </button>
            <a class=\"navbar-brand\" href=\"index.html\">Mats Kjesrud</a>
          </div>
          <div id=\"navbar\" class=\"collapse navbar-collapse\">
            <ul class=\"nav navbar-nav\">")

(defvar mk/org-twbs-post-nav
  "</ul>\n</div><!--/.nav-collapse -->
</div></nav>")

(defun mk/org-twbs-nav (filename)
  (concat (if (equal (file-name-base filename) "emacs" )
              "<li class=\"active\"><a href=\"#\">Emacs</a></li>"
            "<li><a href=\"emacs.html\">Emacs</a></li>")
          (if (equal (file-name-base filename) "contact")
              "<li class=\"active\"><a href=\"#\">Contact</a></li>"
            "<li><a href=\"contact.html\">Contact</a></li>")))

(defun mk/org-twbs-preamble (filename)
  (concat mk/org-twbs-pre-nav
          (mk/org-twbs-nav filename)
          mk/org-twbs-post-nav))

(defvar mk/org-twbs-postamble
  "<p class=\"creator\">Mats Kjesrud</p>
<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\"></script>
<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js\" integrity=\"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa\" crossorigin=\"anonymous\"></script>")
(setq org-export-with-section-numbers nil)
(setq org-html-include-timestamps nil)
(setq org-export-with-sub-superscripts nil)

(defun ask-user-about-lock (file opponent) "Always steal lock." t)

(setq org-publish-project-alist
      '(("Website"
         :components ("Website components"
                      "Emacs config"))
        ("Website components"
         :base-directory "~/Dropbox/org/web"
         :publishing-directory "~/Dropbox/pub"
         :publishing-function mk/org-publish-trustingly)
        ("Emacs config"
         :base-directory "~/.emacs.d"
         :publishing-directory "~/Dropbox/pub"
         :publishing-function mk/org-publish-trustingly)))

Publishing function

Just as Sasha Chua, I also want to publish without having to say yes to code blocks all the time. Here I also add the bootstrap boilerplate, and make sure the correct theme is active.

(defun mk/org-publish-trustingly (plist filename pub-dir)
  (let ((org-confirm-babel-evaluate nil)
        (org-twbs-preamble-format (list (list "en" (mk/org-twbs-preamble filename))))
        (org-twbs-postamble t)
        (org-twbs-postamble-format (list (list "en" mk/org-twbs-postamble))))
    (progn (mk/load-theme 'flatui)
           (org-twbs-publish-to-html plist filename pub-dir)
           (mk/org-publish-ftp-put filename pub-dir))))

When the file is published locally, ftp-put it to the webserver

(defun mk/org-publish-ftp-put (filename pub-dir)
  (let ((name (concat (file-name-sans-extension(file-name-nondirectory filename)) ".html")))
    (copy-file (concat pub-dir name)
               mk/srv-matskjesrud-pth t)))

Development

Common tools

Flycheck

(use-package flycheck
  :diminish flycheck-mode
  :init
  (global-flycheck-mode t)
  (setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc)))

Autocomplete

(use-package auto-complete
  :diminish auto-complete-mode
  :init
  (setq ac-modes (remove 'org-mode ac-modes))
  (ac-config-default))

I use org-mode for writing, and auto-complete breaks my workflow. This advice will prevent auto-complete to load in org-mode.

(defadvice auto-complete-mode (around disable-auto-complete-for-org-mode)
  (unless (eq major-mode 'org-mode) ad-do-it))

(ad-activate 'auto-complete-mode)

Magit

(use-package magit)

Snippets

(use-package yasnippet
  :diminish yas-minor-mode
  :config
  (yas/global-mode 1)
  (add-to-list 'yas-snippet-dirs "~/Dropbox/snippets"))

Lisp

Paredit

(use-package paredit
  :diminish paredit-mode
  :config
  (add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode)
  (add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode))

Use paredit everywhere

(use-package paredit-everywhere
  :diminish paredit-everywhere-mode
  :config
  (add-hook 'prog-mode-hook #'paredit-everywhere-mode))

Python

You can find the Elpy documentation here.

(use-package elpy
  :init (elpy-enable))

; (add-hook 'python-mode-hook (setenv "LANG" "en_US.UTF8"))

Run (elpy-config) after install. Then, install Jedi by running (jedi:install-server)

Hydra for Python

YAML

(use-package yaml-mode
  :mode "\\.yml\\'" "\\.yaml\\'"
  :bind (:map yaml-mode-map ("C-c p" . mk/hydra-yaml-tomato/body)))

(use-package yaml-tomato)

(defhydra mk/hydra-yaml-tomato ()
  "Yaml path"
  ("p" yaml-tomato-show-current-path "Show Path" :exit t)
  ("c" yaml-tomato-copy "Copy Path" :exit t))

Standard ML

(use-package sml-mode
  :init
  (if (eq system-type 'windows-nt)
      (setq sml-program-name "c:/a/tools/SMLNJ/bin/sml.bat")))

(with-eval-after-load 'sml
  (aggressive-indent-mode nil))