Skip to content

Latest commit

 

History

History
741 lines (620 loc) · 28.5 KB

emacs-init.org

File metadata and controls

741 lines (620 loc) · 28.5 KB

Initialize package management

Add some more repositories

(setq package-archives (delete '("gnu" . "http://elpa.gnu.org/packages/") package-archives))
(add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-initialize)

Refresh package contents if needed

(require 'cl-lib)
(defvar iqbal-package-refresh-needed (cl-reduce (lambda (need-refresh repo)
                                                  (or (not (file-exists-p (concat package-user-dir "/archives/"
                                                                                  (car repo)
                                                                                  "/archive-contents")))
                                                      need-refresh))
                                                package-archives :initial-value nil))

(when iqbal-package-refresh-needed
  (package-refresh-contents))

Path to custom El-Get recipies

Use recipies from this directory

(defvar iqbal-local-recipes (locate-user-emacs-file "recipies/"))
(eval-after-load "el-get"
  '(add-to-list 'el-get-recipe-path iqbal-local-recipes))

Helper functions to install package if not already installed

(defun iqbal--install-package (package &optional after-install)
  (unless (package-installed-p package)
    (condition-case err
        (package-install package)

      ;; File error most probably means, the contents are old
      ;; refresh content and try again (emacs-version >= 24.4)
      (file-error (progn (package-refresh-contents)
                         (package-install package)))

      ;; Older emacs
      (error (if (or (string-match-p "Error during download request.*Not Found"
                                     (error-message-string err))
                     (string-match-p "Package `.*' is unavailable"
                                     (error-message-string err)))
                 (progn (package-refresh-contents)
                        (package-install package))
               (signal (car err) (cdr err)))))

    (when after-install
      (funcall after-install))))

(defun iqbal-install-package (package &optional after-install)
  "Install package if not already installed, use el-get if 'local' recipe exists
     for the package. Otherwise install it using package"
  (if (file-exists-p (concat iqbal-local-recipes
                             (symbol-name package)
                             ".rcp"))
      (el-get 'sync package)
    (iqbal--install-package package after-install)))

(defun iqbal-install-packages (packages)
  (dolist (package packages)
    (iqbal-install-package package)))

Install el-get for installing packages that have external dependencies

(iqbal-install-package 'el-get)

Create directory for el-get

(unless (file-exists-p (locate-user-emacs-file "el-get"))
  (make-directory (locate-user-emacs-file "el-get")))

Use shallow clones for git repositories

(setq el-get-git-shallow-clone t)

Path to packages not in a package manager

Packages not currently installable package manager reside in this directory

(defvar otherpackages (locate-user-emacs-file "otherpackages/"))

(let ((default-directory otherpackages))
  (normal-top-level-add-subdirs-to-load-path))

Byte compile installed packages in a clean environment

Install emacs-async

(iqbal-install-package 'async)

Enable async byte compilation for all packages

(setq async-bytecomp-allowed-packages '(all))
(async-bytecomp-package-mode)

Declaration of global variables and utility functions

Check if given file is older than any of the other given files

(require 'cl-lib)
(defun iqbal-is-file-stale (orig-file &rest files)
  (if (file-exists-p orig-file)
      (cl-reduce (lambda (is-stale-yet? file)
                   (or is-stale-yet?
                       (file-newer-than-file-p file orig-file)))
                 files
                 :initial-value nil)
    t))

Given a url, resolve any redirects and get the original url

(defun iqbal-resolve-redirects-url (url)
  (let ((url-request-method "HEAD")
        (url-show-status nil))
    (with-current-buffer (url-retrieve-synchronously url)
      (url-recreate-url url-http-target-url))))

(defun iqbal-resolve-redirects-curl (url)
  (let ((curl-command (format "curl -L -I -s -o /dev/null %s -w '%%{url_effective}'"
                              (shell-quote-argument url))))
    (with-temp-buffer
      (when (shell-command curl-command (current-buffer))
        (buffer-string)))))

(defun iqbal-resolve-redirects (url)
  (if (executable-find "curl")
      (iqbal-resolve-redirects-curl url)
    (iqbal-resolve-redirects-url url)))

Helper functions to read/write from/to file

Install f.el

(iqbal-install-package 'f)
(require 'f)

Reading from a file

(defalias 'iqbal-read-file 'f-read)

Writing to a file

Copied from

(defun iqbal-write-to-file (path data &optional coding)
  (f-write data (or coding 'utf-8) path))

Helper functions for text manipulation

Functions/commands to convert from dos to unix line-endings and vice versa

Credits: I think I copied these from emacswiki

(defun iqbal-dos-to-unix ()
  "Cut all visible ^M from the current buffer."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (search-forward "\r" nil t)
      (replace-match ""))))

(defun iqbal-unix-to-dos ()
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (search-forward "\n" nil t)
      (replace-match "\r\n"))))

Function to justify given text

(defun iqbal-justify-paragraph-text (text)
  (with-temp-buffer
    (insert text)
    (mark-whole-buffer)
    (fill-paragraph nil t)
    (buffer-string)))

Function to indent given text

(defun iqbal-indent-text (text &optional indent)
  (with-temp-buffer
    (insert text)
    (indent-region (point-min) (point-max) indent)
    (buffer-string)))

Function to cleanup the newlines in given text

(defun iqbal-fix-newlines (text)
  (with-temp-buffer
    (insert (replace-regexp-in-string "\n"
                                      "\n\n"
                                      (replace-regexp-in-string "\\(\n\\)[^\n]" " " text nil nil 1)))
    (delete-trailing-whitespace)
    (buffer-string)))

Function to declare one-shot keybindings

These bindings active only after a particular command and are deactivated as soon as some other key is pressed (as in ‘C-x e’ and ‘e’). Credits: Magnar Sveen’s .emacs.d

(defun iqbal-one-shot-keybinding (key command)
  (set-temporary-overlay-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd key) command)
     map) t))

Interacting with REPL

(defmacro iqbal-evaluate-sexp-in-repl (name send-region-func)
  `(defun ,name ()
     (interactive)
     (let ((sexp-bounds (bounds-of-thing-at-point 'sexp)))
       (if sexp-bounds
           (,send-region-func (car sexp-bounds) (cdr sexp-bounds))
         (user-error "No sexp at point")))))

(defmacro iqbal-evaluate-line-in-repl (name send-region-func)
  `(defun ,name ()
     (interactive)
     (,send-region-func (line-beginning-position)
                        (line-end-position))))

(defmacro iqbal-evaluate-file-in-repl (name send-region-func)
  `(defun ,name (file)
     (interactive (list (read-file-name "File to evaluate: ")))
     (with-temp-buffer
       (insert-file-contents file)
       (,send-region-func (point-min)
                          (point-max)))))

(defmacro iqbal-evaluate-buffer-in-repl (name send-region-func)
  `(defun ,name ()
     (interactive)
     (,send-region-func (point-min)
                        (point-max))))

(defmacro iqbal-evaluate-defun-in-repl (name send-region-func)
  `(defun ,name ()
     (interactive)
     (let ((start (save-excursion (beginning-of-defun) (point)))
           (end   (save-excursion (end-of-defun) (point))))
       (,send-region-func  start
                           end))))

Highlighting the line to reorient the user

(autoload #'pulse-momentary-highlight-one-line "pulse")

(defun iqbal-reorient (&rest ignored)
  (ignore-errors (recenter))
  (iqbal-highlight-line)
  (when (equal major-mode 'org-mode)
    (org-show-subtree)))

(defun iqbal-highlight-line ()
  (pulse-momentary-highlight-one-line (point)))


(defun iqbal-reorient-after-func (func)
  (advice-add func :after #'iqbal-reorient))

Prefer utf-8 encoding

(setq 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)

Always prefer the uncompiled file if the compiled file is older

(setq load-prefer-newer t)

Get the url from the clipboard

(defun iqbal-get-url-from-clipboard ()
  (require 'thingatpt)
  (require 'subr-x)
  (let ((current-kill (ignore-errors (current-kill 0))))
    (when current-kill
      (with-temp-buffer
        (insert (string-trim current-kill))
        (goto-char 0)
        (thing-at-point-url-at-point)))))

Location of data directory

(defvar iqbal-data-directory (expand-file-name ".personal" "~") "Directory to store personal data")

(defun iqbal-get-file-in-data-directory (filename &optional directory-p)
  (unless (file-exists-p iqbal-data-directory)
    (make-directory iqbal-data-directory))

  (unless (file-directory-p iqbal-data-directory)
    (user-error "The specified data-directory %s, is a file. Please delete it or customize `iqbal-data-directory'"))

  (let ((file (expand-file-name filename
                                (file-truename iqbal-data-directory))))
    (if directory-p
        (make-directory file t)
      (unless (file-exists-p (file-name-directory file))
        (make-directory (file-name-directory file) t))

      (unless (file-exists-p file)
        (iqbal-write-to-file file "")))

    file))

Location of notes directory

(defvar iqbal-notes-directory (expand-file-name ".notes" "~") "Directory to store notes")

(defun iqbal-get-file-in-notes-directory (filename &optional directory-p)
  (unless (file-exists-p iqbal-notes-directory)
    (make-directory iqbal-notes-directory))

  (unless (file-directory-p iqbal-notes-directory)
    (user-error "The specified notes %s, is a file. Please delete it or customize `iqbal-notes-directory'"))

  (let ((file (expand-file-name filename
                                (file-truename iqbal-notes-directory))))
    (if directory-p
        (make-directory file t)
      (unless (file-exists-p (file-name-directory file))
        (make-directory (file-name-directory file) t))

      (unless (file-exists-p file)
        (iqbal-write-to-file file "")))

    file))

Setup the PATH and exec-path from shell

This is needed if emacs not started from a shell

The variables to copy from shell

(setq exec-path-from-shell-variables (list "PATH" "MANPATH" "PKG_CONFIG_PATH" "LD_LIBRARY_PATH" "ACLOCAL_PATH"))

Initialize the environment from shell

(iqbal-install-package 'exec-path-from-shell)

(when (and (display-graphic-p)
           (not (equal system-type 'windows-nt)))
  (exec-path-from-shell-initialize))

A simple command to restart emacs for with in emacs

(iqbal-install-package 'restart-emacs)

Declare common keybindings

These don’t actually bind any command rather they define the keys that will be used for common actions across multiple modes for commands like jumping-to-definition etc. These keys will be bound to actual functions by the respective major modes.

Jumping to definitions

(defvar iqbal-jump-to-definition (kbd "M-."))
(defvar iqbal-pop-jump-to-definition-marker (kbd "M-,"))

Finding references

(defvar iqbal-find-references (kbd "C-c <"))

Displaying doc

(defvar iqbal-show-doc (kbd "C-c d"))

Refactoring

(defvar iqbal-refactor-rename (kbd "C-c r"))
(defvar iqbal-refactor-auto-import (kbd "C-c i"))
(defvar iqbal-refactor-organize-imports (kbd "C-c o"))

Interacting with REPL

(defvar iqbal-run-shell (kbd "C-c C-z"))
(defvar iqbal-send-region (kbd "C-c C-r"))
(defvar iqbal-send-buffer (kbd "C-c C-b"))
(defvar iqbal-send-line (kbd "C-c C-l"))
(defvar iqbal-send-file (kbd "C-c C-f"))
(defvar iqbal-send-function (kbd "C-M-x"))
(defvar iqbal-send-phrase/sexp/block (kbd "C-x C-e"))

Expanding macro

(defvar iqbal-expand-macro (kbd "C-c x"))

Expanding snippet

(defvar iqbal-expand-snippet (kbd "<C-return>"))

Hiding apps

(defvar iqbal-hide-app (kbd "C-c q"))

By default hide apps by closing their window or burying them

(defun iqbal-default-hide-app ()
  (interactive)
  (if (one-window-p)
      (bury-buffer)
    (delete-window)))

(global-set-key iqbal-hide-app #'iqbal-default-hide-app)

Opening links

(defvar iqbal-open-link (kbd "C-c RET"))

Launcher map

Credits: http://endlessparentheses.com/launcher-keymap-for-standalone-features.html

(define-prefix-command 'iqbal-launcher-map)
(global-set-key (kbd "C-z") 'iqbal-launcher-map)

Keybinding to launch ielm

(global-set-key iqbal-run-shell #'ielm)
(define-key iqbal-launcher-map "R" #'ielm)

Load common libraries

These are general purpose libraries that can are used by different modes

The libaries are loaded by the file ‘config/init.org’

(unless (file-exists-p (locate-user-emacs-file "config/.compiled/"))
  (make-directory (locate-user-emacs-file "config/.compiled/")))

(when (file-newer-than-file-p (locate-user-emacs-file "config/init.org")
                              (locate-user-emacs-file "config/.compiled/init.el"))
  (org-babel-tangle-file (locate-user-emacs-file "config/init.org")
                         (locate-user-emacs-file "config/.compiled/init.el")
                         "emacs-lisp"))

(load-file (locate-user-emacs-file "config/.compiled/init.el"))

Setup language configurations

Path to language specific configurations

Lang contain the configuration related to one specific type of file. They reside in the following directory

(defvar iqbal-langs-dir (locate-user-emacs-file "lang/"))

Function to load language configuration

A simple helper function to load a particular language configuration. Instead of loading the org files one by one it combines all the code in them in one compiled file and loads that file, the compiled file is regenerated if any of the org files change

(defvar iqbal-initialized-langs nil)

(defun iqbal-initialize-lang (lang)
  (let* ((lang-path (concat iqbal-langs-dir lang "/"))
         (init-file (concat lang-path "init.org"))
         (compiled-file-dest (concat lang-path ".compiled/"))
         (compiled-file (concat compiled-file-dest "init.el")))
    (when (and (file-exists-p init-file)
               (or (not (member lang iqbal-initialized-langs))
                   (iqbal-is-file-stale compiled-file init-file)))

      (unless (file-exists-p compiled-file-dest)
        (make-directory compiled-file-dest))

      (when (iqbal-is-file-stale compiled-file init-file)
        (org-babel-tangle-file init-file compiled-file "emacs-lisp"))

      (load (file-name-sans-extension compiled-file)))

    (add-to-list 'iqbal-initialized-langs lang)))

(defun iqbal-compile-lang-config (lang)
  "Compile a languages configuration file, it simply tangles all the related
org files and combines them into one elisp file"
  (interactive
   (list (completing-read "Language: "
                          (directory-files iqbal-langs-dir nil "[^.]+"))))
  (let* ((files '("install" "setup" "keybindings"))
         (lang-path (concat iqbal-langs-dir lang "/"))
         (compiled-file-dest (concat lang-path ".compiled/"))
         (compiled-file (concat compiled-file-dest ".combined.el")))

    (when (file-exists-p lang-path)
      (unless (file-exists-p compiled-file-dest)
        (make-directory compiled-file-dest))

      (iqbal-write-to-file compiled-file
                           (loop for file in files
                                 when (file-exists-p (concat lang-path file ".org"))
                                 concat (iqbal-read-file (car (org-babel-tangle-file
                                                               (concat lang-path file ".org")
                                                               (concat compiled-file-dest file ".el")
                                                               "emacs-lisp")))))
      (byte-compile-file compiled-file))))

(defun iqbal-load-lang-config (language)
  (let* ((files '("install" "setup" "keybindings"))
         (lang-path (concat iqbal-langs-dir language "/"))
         (compiled-file-dest (concat lang-path ".compiled/"))
         (compiled-file (concat compiled-file-dest ".combined.el")))

    (when (file-exists-p lang-path)
      (iqbal-initialize-lang language)

      (when (apply #'iqbal-is-file-stale compiled-file
                   (loop for file in files
                         when (file-exists-p (concat lang-path file ".org"))
                         collect (concat lang-path file ".org")))
        (iqbal-compile-lang-config language))

      (load (file-name-sans-extension compiled-file)))))

(defun iqbal-load-lang-config-for-buffer (language)
  "Load a languages configuration, it compiles the config files
     first (if needed)"
  (interactive
   (list (completing-read "Language: "
                          (directory-files iqbal-langs-dir nil "[^.]+"))))
  (unless (string-prefix-p " " (buffer-name))
    (iqbal-load-lang-config language)))

(defun iqbal-compile-all-lang-config ()
  "Compile all language configurations"
  (interactive)
  (dolist (lang (directory-files iqbal-langs-dir nil "[^.]+"))
    (iqbal-compile-lang-config lang)))

;; Taken from prelude
(defmacro iqbal-auto-install (extension package mode)
  "When file with EXTENSION is opened triggers auto-install of PACKAGE.
PACKAGE is installed only if not already present. The file is opened in MODE."
  `(add-to-list 'auto-mode-alist
                (cons ,extension (lambda ()
                                   (iqbal-install-package ',package)
                                   (,mode)))))

(defmacro iqbal-setup-lang (hook language &optional extension)
  (let ((name (intern (concat "iqbal-setup-lang-" language))))
    `(progn (defun ,name ()
              (when (or (not ,extension)
                        (bound-and-true-p org-src-mode)
                        (string-match-p ,extension (or (file-name-extension (buffer-name)) "")))
                (iqbal-load-lang-config-for-buffer ,language)))
            (add-hook ',hook ',name))))

Emacs lisp is needs to be configured specially

(defvar iqbal-elisp-packages '(elisp-slime-nav
                               macrostep
                               cl-lib-highlight
                               suggest))

(iqbal-install-packages iqbal-elisp-packages)

;; ielm replaces the current window, stop it from doing so
(defun iqbal-split-window-before-run (&rest ignored)
  (select-window (or (split-window-sensibly)
                     (when (one-window-p)
                       (split-window))
                     (next-window))))

(advice-add 'ielm :before #'iqbal-split-window-before-run)

(defun iqbal-emacs-lisp-config ()
  ;; Setup
  (elisp-slime-nav-mode +1)
  (eldoc-mode +1)

  (cl-lib-highlight-initialize)

  (setq flycheck-emacs-lisp-load-path load-path)

  (unless (string= (buffer-name) "*scratch*")
    (flycheck-mode))

  (add-hook 'ielm-mode-hook 'company-mode)
  (add-hook 'ielm-mode-hook 'turn-on-eldoc-mode)

  (push '("Tests" "(\\(\\<ert-deftest\\)\\>\\s *\\(\\(?:\\sw\\|\\s_\\)+\\)?" 2) imenu-generic-expression)

  ;; Keybindings
  (local-set-key iqbal-show-doc #'elisp-slime-nav-describe-elisp-thing-at-point)
  (local-set-key iqbal-run-shell #'ielm)
  (local-set-key iqbal-send-buffer #'eval-buffer)
  (local-set-key iqbal-send-file #'load-file)
  (local-set-key iqbal-send-region #'eval-region)
  (local-set-key iqbal-expand-macro 'macrostep-expand))

(add-hook 'emacs-lisp-mode-hook #'iqbal-emacs-lisp-config)

Setup installation of external language modes

(iqbal-auto-install (rx ".js" string-end) js2-mode js2-mode)
(iqbal-auto-install (rx ".php" string-end) php-mode php-mode)
(iqbal-auto-install (rx ".lua" string-end) lua-mode lua-mode)
(iqbal-auto-install (rx "." (or "scala" "sbt") string-end) scala-mode2 scala-mode)
(iqbal-auto-install (rx ".ml" (zero-or-one ?i ?y ?l ?p) string-end) tuareg tuareg-mode)
(iqbal-auto-install (rx ".hs" string-end) haskell-mode haskell-mode)
(iqbal-auto-install (rx "." (or (seq "clj" (zero-or-one ?s ?x)) "dtm" "edn") string-end) clojure-mode clojure-mode)
(iqbal-auto-install (rx ".erl" string-end) erlang erlang-mode)
(iqbal-auto-install (rx "." (or "ex" "exs") string-end) elixir-mode elixir-mode)
(iqbal-auto-install (rx "." (or "sml" "sig") string-end) sml-mode sml-mode)
(iqbal-auto-install (rx "." (or "html" "ejs" "twig") string-end) web-mode web-mode)
(iqbal-auto-install (rx ".go" string-end) go-mode go-mode)
(iqbal-auto-install (rx ".rs" string-end) rust-mode rust-mode)
(iqbal-auto-install (rx ".jade" string-end) jade-mode jade-mode)
(iqbal-auto-install (rx ".factor" string-end) fuel factor-mode)
(iqbal-auto-install (rx ".json" string-end) json-mode json-mode)
(iqbal-auto-install (rx ".csv" string-end) csv-mode csv-mode)
(iqbal-auto-install (rx (or (seq "." (or "md" "markdown" "mkdn")) "README") string-end) markdown-mode markdown-mode)
(iqbal-auto-install (rx (or (regexp ".y[a]?ml") (regexp ".y[a]?ml.dist")) string-end) yaml-mode yaml-mode)
(iqbal-auto-install (rx ".toml" string-end) toml-mode toml-mode)
(iqbal-auto-install (rx (or "http.conf" "srm.conf" "access.conf" (seq "sites-" (or "available" "enabled")) ".htaccess") string-end)
                      apache-mode
                      apache-mode)
(iqbal-auto-install (rx (or ".pip" (seq "requirements" (zero-or-more nonl)  ".txt")) string-end) pip-requirements pip-requirements-mode)
(iqbal-auto-install (rx ".dot" string-end) graphviz-dot-mode graphviz-dot-mode)
(iqbal-auto-install (rx ".ps1" string-end) powershell powershell-mode)
(iqbal-auto-install (rx "rfc" (one-or-more digit) ".txt" string-end) irfc irfc-mode)
(iqbal-auto-install (rx "CMakeLists.txt" string-end) cmake-mode cmake-mode)
(iqbal-auto-install (rx ".cmake" string-end) cmake-mode cmake-mode)
(iqbal-auto-install (rx word-start "ledger" string-end) ledger-mode ledger-mode)
(iqbal-auto-install (rx ".ledger" string-end) ledger-mode ledger-mode)
(iqbal-auto-install (rx "Dockerfile" string-end) dockerfile-mode dockerfile-mode)
(iqbal-auto-install (rx "shen" string-end) shen-mode shen-mode)
(iqbal-auto-install (rx "rb" string-end) enh-ruby-mode enh-ruby-mode)

Autoload entries for languages

(autoload 'shen-mode "shen-mode")

Some extra auto-mode-alist entries

(add-to-list 'auto-mode-alist (cons (rx ".rkt" string-end) 'scheme-mode))
(add-to-list 'auto-mode-alist (cons (rx (or ".irbrc" ".pryrc" "Gemfile") string-end) 'ruby-mode))
(add-to-list 'auto-mode-alist (cons (rx word-start "composer.lock" string-end) 'json-mode))
(add-to-list 'auto-mode-alist (cons (rx ".tern-project" string-end) 'json-mode))
(add-to-list 'auto-mode-alist (cons (rx word-start "diary" string-end) 'diary-mode))
(add-to-list 'auto-mode-alist (cons (rx ".zsh" string-end) 'sh-mode))

Distinguishing between objc-headers and c-headers

(defun iqbal-file-objective-c-header-p ()
  (and buffer-file-name
       (string= (file-name-extension buffer-file-name) "h")
       (or (> (length (file-expand-wildcards "*.m"))
              (length (file-expand-wildcards "*.c")))
           (re-search-forward "@\\<interface\\>" 
                              magic-mode-regexp-match-limit t))))

(add-to-list 'magic-mode-alist
             (cons #'iqbal-file-objective-c-header-p #'objc-mode))

Setup loading of language configuration when the language mode loads

(iqbal-setup-lang python-mode-hook "python")
(iqbal-setup-lang enh-ruby-mode-hook "ruby")
(iqbal-setup-lang js2-mode-hook "javascript")
(iqbal-setup-lang php-mode-hook "php")
(iqbal-setup-lang lua-mode-hook "lua")
(iqbal-setup-lang lisp-mode-hook "common-lisp")
(iqbal-setup-lang scheme-mode-hook "scheme")
(iqbal-setup-lang c-mode-hook "c" "[ch]$")
(iqbal-setup-lang css-mode-hook "css")
(iqbal-setup-lang scala-mode-hook "scala" "scala")
(iqbal-setup-lang tuareg-mode-hook "ocaml")
(iqbal-setup-lang go-mode-hook "go")
(iqbal-setup-lang rust-mode-hook "rust")
(iqbal-setup-lang erlang-mode-hook "erlang")
(iqbal-setup-lang elixir-mode-hook "elixir")
(iqbal-setup-lang factor-mode-hook "factor")
(iqbal-setup-lang json-mode-hook "json")
(iqbal-setup-lang markdown-mode-hook "markdown")
(iqbal-setup-lang sml-mode-hook "sml")
(iqbal-setup-lang clojure-mode-hook "clojure")
(iqbal-setup-lang web-mode-hook "html" "html")
(iqbal-setup-lang haskell-mode-hook "haskell")
(iqbal-setup-lang ruby-mode-hook "ruby" "rb")
(iqbal-setup-lang ledger-mode-hook "ledger")
(iqbal-setup-lang yaml-mode-hook "yaml")
(iqbal-setup-lang cmake-mode-hook "cmake")
(iqbal-setup-lang sql-mode-hook "sql")
(iqbal-setup-lang shen-mode-hook "shen")