(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)
(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))
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))
(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)))
(iqbal-install-package 'el-get)
(unless (file-exists-p (locate-user-emacs-file "el-get"))
(make-directory (locate-user-emacs-file "el-get")))
(setq el-get-git-shallow-clone t)
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))
(iqbal-install-package 'async)
(setq async-bytecomp-allowed-packages '(all))
(async-bytecomp-package-mode)
(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))
(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)))
(iqbal-install-package 'f)
(require 'f)
(defalias 'iqbal-read-file 'f-read)
Copied from
(defun iqbal-write-to-file (path data &optional coding)
(f-write data (or coding 'utf-8) path))
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"))))
(defun iqbal-justify-paragraph-text (text)
(with-temp-buffer
(insert text)
(mark-whole-buffer)
(fill-paragraph nil t)
(buffer-string)))
(defun iqbal-indent-text (text &optional indent)
(with-temp-buffer
(insert text)
(indent-region (point-min) (point-max) indent)
(buffer-string)))
(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)))
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))
(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))))
(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))
(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)
(setq load-prefer-newer t)
(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)))))
(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))
(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))
This is needed if emacs not started from a shell
(setq exec-path-from-shell-variables (list "PATH" "MANPATH" "PKG_CONFIG_PATH" "LD_LIBRARY_PATH" "ACLOCAL_PATH"))
(iqbal-install-package 'exec-path-from-shell)
(when (and (display-graphic-p)
(not (equal system-type 'windows-nt)))
(exec-path-from-shell-initialize))
(iqbal-install-package 'restart-emacs)
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.
(defvar iqbal-jump-to-definition (kbd "M-."))
(defvar iqbal-pop-jump-to-definition-marker (kbd "M-,"))
(defvar iqbal-find-references (kbd "C-c <"))
(defvar iqbal-show-doc (kbd "C-c d"))
(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"))
(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"))
(defvar iqbal-expand-macro (kbd "C-c x"))
(defvar iqbal-expand-snippet (kbd "<C-return>"))
(defvar iqbal-hide-app (kbd "C-c q"))
(defun iqbal-default-hide-app ()
(interactive)
(if (one-window-p)
(bury-buffer)
(delete-window)))
(global-set-key iqbal-hide-app #'iqbal-default-hide-app)
(defvar iqbal-open-link (kbd "C-c RET"))
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)
(global-set-key iqbal-run-shell #'ielm)
(define-key iqbal-launcher-map "R" #'ielm)
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"))
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/"))
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))))
(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)
(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 'shen-mode "shen-mode")
(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))
(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))
(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")