#+TITLE: Emacs Configuration #+AUTHOR: Levi Olson #+EMAIL: olson.levi@gmail.com #+DATE: <2019-01-30 Wed> #+LANGUAGE: en #+BABEL: :cache yes #+HTML_HEAD: #+EXPORT_FILE_NAME: index.html #+PROPERTY: header-args :tangle yes #+OPTIONS: num:10 whn:nil toc:10 H:10 #+STARTUP: content * Summary I've really been wanting to have a nicely formatted emacs config file and this is my attempt at it. * Required Magic ** Lexical Binding #+BEGIN_SRC emacs-lisp :results silent ;;; -*- lexical-binding: t -*- ;;; DO NOT EDIT THIS FILE DIRECTLY ;;; EDIT ~init.org~ instead #+END_SRC ** The Magical Glue The following auto compiles the emacs-lisp within the =init.org= file. Simply run `org-babel-tangle` to make it RAIN! #+BEGIN_SRC emacs-lisp :results silent ;; (setq byte-compile-warnings nil) (defun tangle-init () "If the current buffer is 'init.org' the code-blocks are tangled, and the tangled file is compiled." (when (equal (buffer-file-name) (expand-file-name (concat user-emacs-directory "init.org"))) ;; Avoid running hooks when tangling. (let ((prog-mode-hook nil)) (org-babel-tangle) (byte-compile-file (concat user-emacs-directory "init.el"))))) (add-hook 'after-save-hook 'tangle-init) #+END_SRC * Config ** Packages #+BEGIN_SRC emacs-lisp :results silent (require 'package) (defvar my-packages '(all-the-icons anzu base16-theme bbdb better-defaults company company-go counsel counsel-projectile dash-at-point diminish dockerfile-mode doom-modeline doom-themes ein eldoc-eval elpy expand-region fic-mode gitignore-mode go-mode go-playground gorepl-mode flycheck iedit ivy ivy-hydra json-mode magit material-theme multiple-cursors nnir-est projectile py-autopep8 rainbow-delimiters shrink-path tide typescript-mode use-package web-mode which-key)) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/")) (when (not package-archive-contents) (package-refresh-contents)) (package-initialize) (dolist (p my-packages) (when (not (package-installed-p p)) (package-install p))) #+END_SRC ** Server #+BEGIN_SRC emacs-lisp :results silent (require 'edit-server) (edit-server-start) #+END_SRC ** Better Defaults #+BEGIN_SRC emacs-lisp :results silent (require 'better-defaults) ;; Instead of the annoying giant warning icon, just flash the modeline. ;; (this happens when you do something like C-g) (setq ring-bell-function (lambda () (let ((orig-fg (face-foreground 'mode-line))) (set-face-foreground 'mode-line "#F2804F") (run-with-idle-timer 0.1 nil (lambda (fg) (set-face-foreground 'mode-line fg)) orig-fg)))) (defun set-frame-size-according-to-resolution () "Set the Emacs window size on startup." (interactive) (if window-system (progn ;; WIDTH (if (> (x-display-pixel-width) 1280) ;; Large Screen (only show 120 cols) (add-to-list 'default-frame-alist (cons 'width 240)) ;; Small Screen (fill window) (add-to-list 'default-frame-alist (cons 'width (/ (x-display-pixel-width) (frame-char-width))))) ;; HEIGHT (if (> (x-display-pixel-height) 1080) ;; Large Screen (only fill half screen) (add-to-list 'default-frame-alist (cons 'height (/ (/ (x-display-pixel-height) 2) (frame-char-height)))) ;; Small Screen (fill window) (add-to-list 'default-frame-alist (cons 'height (/ (x-display-pixel-height) (frame-char-height))))) ))) (set-frame-size-according-to-resolution) (defun window-px-width () "Get the width of the Emacs window in pixels." (interactive) (* (* (window-total-width) 2.874) (frame-char-width))) (defun window-px-left-pos () "Calculate the left position of the Emacs window." (interactive) (/ (- (x-display-pixel-width) (window-px-width)) 2)) (add-to-list 'default-frame-alist (cons 'top 0)) (add-to-list 'default-frame-alist (cons 'left 1000)) #+END_SRC ** Enable Disabled Commands #+BEGIN_SRC emacs-lisp :results silent (put 'narrow-to-region 'disabled nil) (put 'upcase-region 'disabled nil) (put 'downcase-region 'disabled nil) #+END_SRC ** Splash Screen #+BEGIN_SRC emacs-lisp :results silent (setq inhibit-splash-screen nil fancy-splash-image "~/.emacs.d/public/emacs-logo.png" fancy-splash-image-file "~/.emacs.d/public/emacs-logo.png") #+END_SRC ** Basic Customization #+BEGIN_SRC emacs-lisp :results silent (defvar backup-dir (expand-file-name "~/.emacs.d/backup/")) (defvar autosave-dir (expand-file-name "~/.emacs.d/autosave/")) (setq initial-scratch-message nil backup-directory-alist (list (cons ".*" backup-dir)) auto-save-list-file-prefix autosave-dir auto-save-file-name-transforms `((".*" ,autosave-dir t))) (menu-bar-mode 0) (scroll-bar-mode 0) (tool-bar-mode 0) ;; (load-theme 'doom-city-lights t) ;; (load-theme 'doom-dracula t) ;; (load-theme 'doom-nord t) (load-theme 'doom-one t) ;; (load-theme 'doom-spacegrey t) ;; (load-theme 'base16-ocean t) (load-theme 'base16-onedark t) (global-linum-mode t) (global-auto-revert-mode t) (defalias 'yes-or-no-p 'y-or-n-p) #+END_SRC ** Custom Modes #+BEGIN_SRC emacs-lisp :results silent (require 'font-lock) (defvar openhab-mode-hook nil) (defvar openhab-mode-map (let ((map (make-keymap))) (define-key map "\C-j" 'newline-and-indent) map) "Keymap for OPENHAB major mode.") (add-to-list 'auto-mode-alist '("\\.sitemap\\'" . openhab-mode)) (add-to-list 'auto-mode-alist '("\\.items\\'" . openhab-mode)) (add-to-list 'auto-mode-alist '("\\.rules\\'" . openhab-mode)) (add-to-list 'auto-mode-alist '("\\.things\\'" . openhab-mode)) (defconst openhab-font-lock-keywords `( ("\<.*\>" . font-lock-constant-face) (,(regexp-opt '( ;; KEYWORDS "Selection" "Slider" "List" "Setpoint" "Video" "Chart" "Webview" "Colorpicker" "Timer" "Number" "String" "Switch" "Rollershutter" "Number" "String" "Dimmer" "Contact" "DateTime" "Color" "Text" "Group" "Image" "Frame" "Thing" "Bridge" "Time" "System" "sitemap" "rule" "when" "then" "end" "if" "val" "import" "var" "say" "postUpdate" "switch" "println" "case" "or" "sendCommand" ) 'words) (1 font-lock-keyword-face)) (,(regexp-opt '( "ON" "OFF" "on" "off" "AND" "OR" "NAND" "NOR" "AVG" "SUM" "MAX" "MIN" "true" "false" ) 'words) (1 font-lock-constant-face)) (,(regexp-opt '( "name" "label" "item" "period" "refresh" "icon" "mappings" "minValue" "maxValue" "step" "switchsupport" "url" "height" "refresh" "visibility" "valuecolor" ) 'words) (1 font-lock-type-face)) ("\(.*\)" . font-lock-variable-name-face) ("[^a-zA-Z0-9_:]\\([0-9]*\\)[^a-zA-Z0-9_:]" . (1 font-lock-variable-name-face)) ("\s@\s" . font-lock-variable-name-face) ("\s\\([a-zA-Z0-9_:]*\\)\\(\s\\|$\\)" . (1 font-lock-type-face)) ("=\\([a-zA-Z_]*\\)" . (1 font-lock-string-face)) ("\\([a-zA-Z]*\\)=" . (1 font-lock-type-face)) ) "The regexps to highlight in openHAB mode.") (defvar openhab-mode-syntax-table (let ((st (make-syntax-table))) (modify-syntax-entry ?/ ". 12b" st) ;; C-style comments // ... (modify-syntax-entry ?\n "> b" st) ;; \n ends comment ;; Block comments /*...*/ (modify-syntax-entry ?\/ ". 14" st) (modify-syntax-entry ?* ". 23" st) st) "Syntax table for openhab-mode.") (defun openhab-mode () "Major mode for editing OPENHAB config files." (interactive) (kill-all-local-variables) (set-syntax-table openhab-mode-syntax-table) (use-local-map openhab-mode-map) (set (make-local-variable 'font-lock-defaults) '(openhab-font-lock-keywords nil t)) (electric-pair-mode -1) (flycheck-mode -1) (setq major-mode 'openhab-mode) (setq mode-name "OpenHAB") (run-hooks 'openhab-mode-hook)) (provide 'openhab-mode) #+END_SRC ** Tools *** General #+BEGIN_SRC emacs-lisp :results silent (require 'which-key) (which-key-setup-minibuffer) (which-key-mode) (require 'fic-mode) (add-hook 'js-mode-hook 'fic-mode) #+END_SRC *** Company #+BEGIN_SRC emacs-lisp :results silent (require 'company) (add-hook 'after-init-hook 'global-company-mode) (setq company-dabbrev-downcase nil) (setq company-idle-delay 0.1) #+END_SRC *** Diminish #+BEGIN_SRC emacs-lisp :results silent (require 'diminish) (diminish 'auto-revert-mode) (eval-after-load "company" '(diminish 'company-mode)) (eval-after-load "counsel" '(diminish 'counsel-mode)) (eval-after-load "elpy" '(diminish 'elpy-mode)) (eval-after-load "go-mode" '(diminish 'go-mode)) (eval-after-load "go-playground" '(diminish 'go-playground-mode)) (eval-after-load "gorepl-mode" '(diminish 'gorepl-mode)) (eval-after-load "flycheck" '(diminish 'flycheck-mode)) (eval-after-load "ivy" '(diminish 'ivy-mode)) (eval-after-load "projectile" '(diminish 'projectile-mode)) (eval-after-load "which-key" '(diminish 'which-key-mode)) #+END_SRC *** Dired #+BEGIN_SRC emacs-lisp :results silent (defun dired-mode-setup () "Will run as hook for `dired-mode'." (dired-hide-details-mode 1)) (add-hook 'dired-mode-hook 'dired-mode-setup) #+END_SRC *** Ivy #+BEGIN_SRC emacs-lisp :results silent (require 'ivy-hydra) (require 'ivy) (require 'swiper) (ivy-mode 1) (counsel-mode) (setq ivy-use-virtual-buffers t enable-recursive-minibuffers t ivy-height 25 ivy-initial-inputs-alist nil ivy-extra-directories nil) (global-set-key (kbd "C-s") 'swiper) (global-set-key (kbd "C-c C-r") 'ivy-resume) (global-set-key (kbd "M-x") 'counsel-M-x) (global-set-key (kbd "C-x C-f") 'counsel-find-file) (global-set-key (kbd "C-c g") 'counsel-git) (global-set-key (kbd "C-c j") 'counsel-git-grep) (global-set-key (kbd "C-c k") 'counsel-ag) (define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history) (defun ivy-open-current-typed-path () (interactive) (when ivy--directory (let* ((dir ivy--directory) (text-typed ivy-text) (path (concat dir text-typed))) (delete-minibuffer-contents) (ivy--done path)))) (define-key ivy-minibuffer-map (kbd "") 'ivy-alt-done) (define-key ivy-minibuffer-map (kbd "C-f") 'ivy-open-current-typed-path) #+END_SRC *** Magit #+BEGIN_SRC emacs-lisp :results silent (require 'magit) (global-set-key (kbd "C-x g") 'magit-status) (global-set-key (kbd "C-c g") 'magit-status) (setq magit-completing-read-function 'ivy-completing-read) #+END_SRC *** Mu4e #+BEGIN_SRC emacs-lisp :results silent (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu/mu4e") (require 'mu4e) ;; default (setq mu4e-maildir "~/Mail" mu4e-mu-binary "/usr/local/bin/mu" mu4e-get-mail-command "offlineimap" ;; Allow updating with the "U" command mu4e-sent-messages-behavior 'delete ;; Delete sent messages mu4e-view-show-images t ;; attempt to show images mu4e-view-image-max-width 400 ;; max image size message-kill-buffer-on-exit t ;; don't keep messages around mu4e-use-fancy-chars t ;; use 'fancy' chars mu4e-update-interval 300 ;; 5 mins ) (setq mu4e-contexts `( ,(make-mu4e-context :name "Vlocity" :enter-func (lambda () (mu4e-message "Entering Vlocity")) :leave-func (lambda () (mu4e-message "Leaving Vlocity")) ;; we match based on the contact-fields of the message :match-func (lambda (msg) (when msg (string= (mu4e-message-field msg :maildir) "/Vlocity"))) :vars '( ( user-mail-address . "lolson@vlocity.com" ) ( smtpmail-mail-address . "lolson@vlocity.com" ) ( user-full-name . "Levi Olson" ) ( mu4e-compose-signature . (concat "--\n" "Levi Olson\n" "Senior UI Developer")) ( mu4e-sent-folder . "/Vlocity/[Gmail].Sent Mail" ) ( mu4e-drafts-folder . "/Vlocity/[Gmail].Drafts" ) ( mu4e-trash-folder . "/Vlocity/[Gmail].Trash" ) ( mu4e-maildir-shortcuts . (("/Vlocity/INBOX" . ?i) ("/Vlocity/[Gmail].Sent Mail" . ?s) ("/Vlocity/[Gmail].Trash" . ?t) ("/Vlocity/[Gmail].All Mail" . ?a))))) ,(make-mu4e-context :name "Gmail" :enter-func (lambda () (mu4e-message "Entering Gmail")) :leave-func (lambda () (mu4e-message "Leaving Gmail")) ;; this matches maildir /Arkham and its sub-directories :match-func (lambda (msg) (when msg (string= (mu4e-message-field msg :maildir) "/Gmail"))) :vars '( ( user-mail-address . "olson.levi@gmail.com" ) ( smtpmail-mail-address . "olson.levi@gmail.com" ) ( user-full-name . "Levi Olson" ) ( mu4e-compose-signature . (concat "--\n" "Levi\n")) ( mu4e-sent-folder . "/Gmail/[Gmail].Sent Mail" ) ( mu4e-drafts-folder . "/Gmail/[Gmail].Drafts" ) ( mu4e-trash-folder . "/Gmail/[Gmail].Trash" ) ( mu4e-maildir-shortcuts . (("/Gmail/INBOX" . ?i) ("/Gmail/[Gmail].Sent Mail" . ?s) ("/Gmail/[Gmail].Trash" . ?t) ("/Gmail/[Gmail].All Mail" . ?a)) ))))) ;; (defcustom smtpmail-smtp-user nil ;; "User name to use when looking up credentials in the authinfo file. ;; If non-nil, only consider credentials for the specified user." ;; :version "24.1" ;; :type '(choice (const nil) string) ;; :group 'smtpmail) ;; How to handle HTML emails ;; (setq mu4e-html2text-command "textutil -stdin -format html -convert txt -stdout") ;; Add option to view HTML in browser (add-to-list 'mu4e-headers-actions '("in browser" . mu4e-action-view-in-browser) t) (add-to-list 'mu4e-view-actions '("in browser" . mu4e-action-view-in-browser) t) #+END_SRC *** Projectile #+BEGIN_SRC emacs-lisp :results silent (require 'projectile) (require 'counsel-projectile) (projectile-mode) (setq projectile-mode-line '(:eval (format " %s" (projectile-project-name))) projectile-remember-window-configs t projectile-completion-system 'ivy) (counsel-projectile-mode) #+END_SRC ** Development Specific *** General #+BEGIN_SRC emacs-lisp :results silent (require 'rainbow-delimiters) (global-flycheck-mode) (add-hook 'before-save-hook 'delete-trailing-whitespace) (add-hook 'prog-mode-hook 'rainbow-delimiters-mode) (setq-default indent-tabs-mode nil tab-width 4) (defvaralias 'c-basic-offset 'tab-width) (defvaralias 'cperl-indent-level 'tab-width) (electric-pair-mode 1) (show-paren-mode 1) (require 'dockerfile-mode) (add-to-list 'auto-mode-alist '("Dockerfile*\\'" . dockerfile-mode)) (require 'gitignore-mode) (add-to-list 'auto-mode-alist '("gitignore\\'" . gitignore-mode)) (require 'json-mode) (add-to-list 'auto-mode-alist '("\\.json\\'" . json-mode)) (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode)) #+END_SRC *** Python #+BEGIN_SRC emacs-lisp :results silent (elpy-enable) (setq python-shell-interpreter "jupyter" python-shell-interpreter-args "console --simple-prompt") (when (require 'flycheck nil t) (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)) (add-hook 'elpy-mode-hook 'flycheck-mode)) (require 'py-autopep8) (setq py-autopep8-options '("--ignore=E501")) (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save) #+END_SRC *** Go #+BEGIN_SRC emacs-lisp :results silent (require 'go-mode) (require 'go-playground) (require 'gorepl-mode) (require 'company-go) (add-to-list 'auto-mode-alist '("\\.go\\'" . go-mode)) (add-hook 'go-mode-hook (lambda () (add-hook 'before-save-hook 'gofmt-before-save) (local-set-key (kbd "M-.") 'godef-jump) (local-set-key (kbd "M-,") 'pop-tag-mark) (local-set-key (kbd "C-c C-c") (lambda () (interactive) (ansi-term) (comint-send-string "*ansi-term*" "make\n"))) (set (make-local-variable 'company-backends) '(company-go)) (setq company-tooltip-limit 20 company-echo-delay 0 company-begin-commands '(self-insert-command)) (gorepl-mode))) (defun set-exec-path-from-shell-PATH () (let ((path-from-shell (replace-regexp-in-string "[ \t\n]*$" "" (shell-command-to-string "$SHELL --login -i -c 'echo $PATH'")))) (setenv "PATH" path-from-shell) (setq eshell-path-env path-from-shell) (setq exec-path (split-string path-from-shell path-separator)))) (when window-system (set-exec-path-from-shell-PATH)) (setenv "GOPATH" "/Users/leviolson/go") (add-to-list 'exec-path "/Users/leviolson/go/bin") #+END_SRC *** TypeScript #+BEGIN_SRC emacs-lisp :results silent (defun setup-tide-mode () "Tide setup function." (interactive) (tide-setup) (flycheck-mode +1) (setq flycheck-check-syntax-automatically '(save mode-enabled)) (eldoc-mode +1) (tide-hl-identifier-mode +1) (company-mode +1)) ;; aligns annotation to the right hand side (setq company-tooltip-align-annotations t) ;; formats the buffer before saving (add-hook 'before-save-hook 'tide-format-before-save) (add-hook 'typescript-mode-hook #'setup-tide-mode) (require 'typescript-mode) (require 'tide) (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode)) (add-hook 'typescript-mode-hook '(lambda () (set (make-local-variable 'company-backends) '(company-tide)) (setq company-tooltip-limit 20 company-echo-delay 0 company-begin-commands '(self-insert-command) tide-format-options '(:insertSpaceAfterFunctionKeywordForAnonymousFunctions t :placeOpenBraceOnNewLineForFunctions nil)) (tide-setup))) #+END_SRC **** TSX #+BEGIN_SRC emacs-lisp :results silent (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.tsx\\'" . web-mode)) (add-hook 'web-mode-hook (lambda () (when (string-equal "tsx" (file-name-extension buffer-file-name)) (setup-tide-mode)))) ;; enable typescript-tslint checker (flycheck-add-mode 'typescript-tslint 'web-mode) #+END_SRC **** JSX #+BEGIN_SRC emacs-lisp :results silent (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.jsx\\'" . web-mode)) (add-hook 'web-mode-hook (lambda () (when (string-equal "jsx" (file-name-extension buffer-file-name)) (setup-tide-mode)))) ;; configure jsx-tide checker to run after your default jsx checker (flycheck-add-mode 'javascript-eslint 'web-mode) (flycheck-add-next-checker 'javascript-eslint 'jsx-tide 'append) #+END_SRC *** Org #+BEGIN_SRC emacs-lisp :results silent (org-babel-do-load-languages 'org-babel-load-languages '((js . t) (shell . t) (emacs-lisp . t))) (defvar org-src-tab-acts-natively) (setq org-src-tab-acts-natively t) ;; (setenv "NODE_PATH" ;; (getenv "NODE_PATH")) (defvar org-confirm-babel-evaluate) (defun my-org-confirm-babel-evaluate (lang body) "Execute certain languages without confirming. Takes LANG to allow and BODY to execute." (not (or (string= lang "js") (string= lang "restclient") (string= lang "emacs-lisp") (string= lang "shell")))) (setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate) (add-to-list 'org-structure-template-alist (list "e" (concat "#+BEGIN_SRC emacs-lisp :results silent\n" "\n" "#+END_SRC"))) (add-to-list 'org-structure-template-alist (list "j" (concat "#+BEGIN_SRC js :cmd \"babel-node\"\n" "\n" "#+END_SRC"))) (add-to-list 'org-structure-template-alist (list "r" (concat "#+BEGIN_SRC restclient :results raw\n" "\n" "#+END_SRC"))) #+END_SRC ** Functions #+BEGIN_SRC emacs-lisp :results silent (defun find-user-init-file () "Edit the `~/.emacs.d/init.org' file." (interactive) (find-file "~/.emacs.d/init.org")) (defun load-user-init-file () "LO: Reload the `~/.emacs.d/init.elc' file." (interactive) (load-file "~/.emacs.d/init.elc")) (defun jump-to-symbol-internal (&optional backwardp) "Jumps to the next symbol near the point if such a symbol exists. If BACKWARDP is non-nil it jumps backward." (let* ((point (point)) (bounds (find-tag-default-bounds)) (beg (car bounds)) (end (cdr bounds)) (str (isearch-symbol-regexp (find-tag-default))) (search (if backwardp 'search-backward-regexp 'search-forward-regexp))) (goto-char (if backwardp beg end)) (funcall search str nil t) (cond ((<= beg (point) end) (goto-char point)) (backwardp (forward-char (- point beg))) (t (backward-char (- end point)))))) (defun jump-to-previous-like-this () "Jumps to the previous occurrence of the symbol at point." (interactive) (jump-to-symbol-internal t)) (defun jump-to-next-like-this () "Jumps to the next occurrence of the symbol at point." (interactive) (jump-to-symbol-internal)) (defun match-paren (arg) "Go to the matching paren if on a paren; otherwise insert ARG (a literal % sign)." (interactive "p") (cond ((looking-at "\\s(") (forward-list 1)) ((looking-back "\\s(" 2) (backward-char 1) (forward-list 1)) ((looking-at "\\s)") (forward-char 1) (backward-list 1)) ((looking-back "\\s)" 2) (backward-list 1)) (t (self-insert-command (or arg 1))))) (defun kill-this-buffer-unless-scratch () "Works like `kill-this-buffer' unless the current buffer is the *scratch* buffer. In which case the buffer content is deleted and the buffer is buried." (interactive) (if (not (string= (buffer-name) "*scratch*")) (kill-this-buffer) (delete-region (point-min) (point-max)) (switch-to-buffer (other-buffer)) (bury-buffer "*scratch*"))) (defun delete-backward-sentence () "LO: Delete to the beginning of the sentence/line." (interactive) (delete-region (point) (progn (backward-sentence) (point)))) (defun delete-backward-to-boundary (arg) "LO: Delete backward to the previous word boundary. With ARG, do this many times." (interactive "p") (let ((a (point)) (b (progn (backward-word arg) (forward-word) (point)))) (if (< a b) (delete-region a (progn (backward-word arg) (point))) (if (= a b) (delete-region a (progn (backward-word arg) (point))) (delete-region a b))))) (defun comment-or-uncomment-region-or-line () "Comments or uncomments the region or the current line if there's no active region." (interactive) (let (beg end) (if (region-active-p) (setq beg (region-beginning) end (region-end)) (setq beg (line-beginning-position) end (line-end-position))) (comment-or-uncomment-region beg end))) (defun fold-toggle (column) "Code folding by COLUMN." (interactive "P") (set-selective-display (or column (unless selective-display (1+ (current-column)))))) (defun new-line-below () "LO: Create a new line below current line." (interactive) (move-end-of-line 1) (newline-and-indent)) (defun new-line-above () "LO: Create a new line above current line." (interactive) (move-beginning-of-line 1) (newline) (forward-line -1)) (defun duplicate-thing (comment) "LO: Duplicates the current line, or the region if active. If an argument (COMMENT) is given, the duplicated region will be commented out." (interactive "P") (save-excursion (let ((start (if (region-active-p) (region-beginning) (point-at-bol))) (end (if (region-active-p) (region-end) (point-at-eol)))) (goto-char end) (unless (region-active-p) (newline)) (insert (buffer-substring start end)) (when comment (comment-region start end))))) (defun tidy () "LO: Ident, untabify and unwhitespacify current buffer, or region if active." (interactive) (let ((beg (if (region-active-p) (region-beginning) (point-min))) (end (if (region-active-p) (region-end) (point-max)))) (let ((inhibit-message t)) (indent-region beg end)) (whitespace-cleanup) (untabify beg (if (< end (point-max)) end (point-max))) (if (region-active-p) (message "Indenting Region...Done") (message "Indenting File...Done")))) (defun phil-columns () "LO: Good 'ol Phil-Columns." (interactive) (message "Good 'ol fill-columns") (with-output-to-temp-buffer "*PHIL-COLUMN*" (shell-command "mpv --no-video 'https://www.youtube.com/watch?v=YkADj0TPrJA&t=3m16s' > /dev/null 2>&1 & sleep 8; pkill mpv")) (other-window 1) (delete-window)) (declare-function first "Goto FIRST shell.") (declare-function goto-non-shell-buffer "Goto something other than a shell buffer.") (declare-function switch-shell "Switch shell.") (let ((last-shell "")) (defun toggle-shell () (interactive) (cond ((string-match-p "^\\*shell<[1-9][0-9]*>\\*$" (buffer-name)) (goto-non-shell-buffer)) ((get-buffer last-shell) (switch-to-buffer last-shell)) (t (shell (setq last-shell "*shell<1>*"))))) (defun switch-shell (n) (let ((buffer-name (format "*shell<%d>*" n))) (setq last-shell buffer-name) (cond ((get-buffer buffer-name) (switch-to-buffer buffer-name)) (t (shell buffer-name) (rename-buffer buffer-name))))) (defun goto-non-shell-buffer () (let* ((r "^\\*shell<[1-9][0-9]*>\\*$") (shell-buffer-p (lambda (b) (string-match-p r (buffer-name b)))) (non-shells (cl-remove-if shell-buffer-p (buffer-list)))) (when non-shells (switch-to-buffer (first non-shells)))))) (defadvice shell (after kill-with-no-query nil activate) "." (set-process-query-on-exit-flag (get-buffer-process ad-return-value) nil)) (declare-function comint-truncate-buffer ".") (defun clear-comint () "Run `comint-truncate-buffer' with the `comint-buffer-maximum-size' set to zero." (interactive) (let ((comint-buffer-maximum-size 0)) (comint-truncate-buffer))) (defun c-setup () "Compile." (local-set-key (kbd "C-c C-c") 'compile)) #+END_SRC ** Bindings #+BEGIN_SRC emacs-lisp :results silent (require 'company) (add-hook 'comint-mode-hook (lambda () (local-set-key (kbd "C-l") 'clear-comint))) (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode) (add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode) (add-hook 'c-mode-common-hook 'c-setup) (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode)) (defvar company-active-map (make-keymap) "Company Mode keymap.") (defvar custom-bindings (make-keymap) "A keymap of custom bindings.") (define-key global-map (kbd "M-p") 'jump-to-previous-like-this) (define-key global-map (kbd "M-n") 'jump-to-next-like-this) (define-key global-map (kbd "M-") 'switch-to-next-buffer) (define-key global-map (kbd "M-")'delete-backward-to-boundary) (define-key global-map (kbd "C-")'delete-backward-to-boundary) (global-set-key (kbd "C-S-") 'mc/mark-next-like-this) (global-set-key (kbd "C->") 'mc/mark-next-like-this-symbol) (global-set-key (kbd "C-S-") 'mc/mark-previous-like-this) (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) (global-set-key (kbd "C-c C->") 'mc/mark-all-like-this) (global-set-key "%" 'match-paren) (global-set-key (kbd "C-x .") 'dash-at-point) (global-set-key (kbd "C-x ,") 'dash-at-point-with-docset) (global-set-key (kbd "C-s") (lambda () (interactive) (swiper (format "%s" (thing-at-point 'symbol))))) (global-set-key (kbd "M-m") 'mu4e) ;; (dolist (n (number-sequence 1 9)) ;; (global-set-key (kbd (concat "M-" (int-to-string n))) ;; (lambda () (interactive) (switch-shell n)))) (define-key company-active-map (kbd "C-d") 'company-show-doc-buffer) (define-key company-active-map (kbd "C-n") 'company-select-next) (define-key company-active-map (kbd "C-p") 'company-select-previous) (define-key company-active-map (kbd "") 'company-complete) (define-key custom-bindings (kbd "C-c p") 'counsel-projectile-switch-project) (define-key custom-bindings (kbd "C-c f") 'counsel-projectile-find-file) (define-key custom-bindings (kbd "C-c m") 'magit-status) (define-key custom-bindings (kbd "C-c D") 'define-word-at-point) (define-key custom-bindings (kbd "C-@") 'er/expand-region) (define-key custom-bindings (kbd "C-#") 'er/contract-region) (define-key custom-bindings (kbd "C-S-c C-S-c") 'mc/edit-lines) (define-key custom-bindings (kbd "C-c b") 'ivy-switch-buffer) (define-key custom-bindings (kbd "C-c l") 'org-store-link) (define-key custom-bindings (kbd "C-c t") 'org-set-tags) (define-key custom-bindings (kbd "M-u") 'upcase-dwim) (define-key custom-bindings (kbd "M-c") 'capitalize-dwim) (define-key custom-bindings (kbd "M-l") 'downcase-dwim) (define-key custom-bindings (kbd "M-o") 'other-window) (define-key custom-bindings (kbd "C-c s") 'ispell-word) (define-key custom-bindings (kbd "C-c C-d") 'org-capture) (define-key custom-bindings (kbd "C-c ") 'windmove-up) (define-key custom-bindings (kbd "C-c ") 'windmove-down) (define-key custom-bindings (kbd "C-c ") 'windmove-left) (define-key custom-bindings (kbd "C-c ") 'windmove-right) (define-key custom-bindings (kbd "C-c a") (lambda () (interactive) (org-agenda nil "n"))) (define-key custom-bindings (kbd "C-c e") 'find-user-init-file) (define-key custom-bindings (kbd "C-x f") 'phil-columns) (define-key custom-bindings (kbd "C-x k") 'kill-this-buffer-unless-scratch) (define-key custom-bindings (kbd "C-c d") 'duplicate-thing) (define-key custom-bindings (kbd "C-c c") 'comment-or-uncomment-region-or-line) (define-key custom-bindings (kbd "C-;") 'comment-or-uncomment-region-or-line) (define-key custom-bindings (kbd "C-o") 'new-line-below) (define-key custom-bindings (kbd "C-S-o") 'new-line-above) (define-key custom-bindings (kbd "") 'tidy) (define-key custom-bindings (kbd "M-q") 'kill-this-buffer) (define-key custom-bindings (kbd "M-RET") '(lambda () (interactive) (term (getenv "SHELL")))) (define-minor-mode custom-bindings-mode "A mode that activates custom-bindings." t nil custom-bindings) #+END_SRC ** UI #+BEGIN_SRC emacs-lisp :results silent (cond ((member "PragmataPro" (font-family-list)) (set-face-attribute 'default nil :font "PragmataPro-14"))) #+END_SRC *** Doom Modeline #+BEGIN_SRC emacs-lisp :results silent (require 'doom-modeline) (doom-modeline-mode 1) ;; How tall the mode-line should be (only respected in GUI Emacs). (setq doom-modeline-height 35) ;; How wide the mode-line bar should be (only respected in GUI Emacs). (setq doom-modeline-bar-width 4) ;; Determines the style used by `doom-modeline-buffer-file-name'. ;; ;; Given ~/Projects/FOSS/emacs/lisp/comint.el ;; truncate-upto-project => ~/P/F/emacs/lisp/comint.el ;; truncate-from-project => ~/Projects/FOSS/emacs/l/comint.el ;; truncate-with-project => emacs/l/comint.el ;; truncate-except-project => ~/P/F/emacs/l/comint.el ;; truncate-upto-root => ~/P/F/e/lisp/comint.el ;; truncate-all => ~/P/F/e/l/comint.el ;; relative-from-project => emacs/lisp/comint.el ;; relative-to-project => lisp/comint.el ;; file-name => comint.el ;; buffer-name => comint.el<2> (uniquify buffer name) ;; ;; If you are expereicing the laggy issue, especially while editing remote files ;; with tramp, please try `file-name' style. ;; Please refer to https://github.com/bbatsov/projectile/issues/657. (setq doom-modeline-buffer-file-name-style 'truncate-upto-project) ;; What executable of Python will be used (if nil nothing will be showed). (setq doom-modeline-python-executable "python") ;; Whether show `all-the-icons' or not (if nil nothing will be showed). (setq doom-modeline-icon t) ;; Whether show the icon for major mode. It respects `doom-modeline-icon'. (setq doom-modeline-major-mode-icon t) ;; Display color icons for `major-mode'. It respects `all-the-icons-color-icons'. (setq doom-modeline-major-mode-color-icon nil) ;; Whether display minor modes or not. Non-nil to display in mode-line. (setq doom-modeline-minor-modes nil) ;; If non-nil, a word count will be added to the selection-info modeline segment. (setq doom-modeline-enable-word-count nil) ;; If non-nil, only display one number for checker information if applicable. (setq doom-modeline-checker-simple-format t) ;; Whether display perspective name or not. Non-nil to display in mode-line. (setq doom-modeline-persp-name t) ;; Whether display `lsp' state or not. Non-nil to display in mode-line. (setq doom-modeline-lsp t) ;; Whether display github notifications or not. Requires `ghub` package. (setq doom-modeline-github nil) ;; The interval of checking github. (setq doom-modeline-github-interval (* 30 60)) ;; Whether display environment version or not. (setq doom-modeline-env-version t) ;; Whether display mu4e notifications or not. Requires `mu4e-alert' package. (setq doom-modeline-mu4e t) #+END_SRC