Human Readable Emacs Configuration using Org mode
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1595 lines
65 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. #+TITLE: Emacs Configuration
  2. #+AUTHOR: Levi Olson
  3. #+EMAIL: olson.levi@gmail.com
  4. #+DATE: <2019-01-30 Wed>
  5. #+LANGUAGE: en
  6. #+BABEL: :cache yes
  7. #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="public/style.css" />
  8. #+EXPORT_FILE_NAME: index.html
  9. #+PROPERTY: header-args :tangle yes
  10. #+OPTIONS: num:10 whn:nil toc:10 H:10
  11. #+STARTUP: content
  12. * Summary
  13. I've really been wanting to have a nicely formatted emacs config file and this is my attempt at it.
  14. * Required Magic
  15. ** Lexical Binding
  16. #+BEGIN_SRC emacs-lisp :results silent
  17. ;;; -*- lexical-binding: t -*-
  18. ;;; DO NOT EDIT THIS FILE DIRECTLY
  19. ;;; EDIT ~init.org~ instead
  20. #+END_SRC
  21. ** The Magical Glue
  22. The following auto compiles the emacs-lisp within the =init.org= file.
  23. Simply run `org-babel-tangle` to make it RAIN!
  24. #+BEGIN_SRC emacs-lisp :results silent
  25. ;; (setq byte-compile-warnings nil)
  26. (defun tangle-init ()
  27. "If the current buffer is 'init.org' the code-blocks are tangled, and the tangled file is compiled."
  28. (when (equal (buffer-file-name)
  29. (expand-file-name (concat user-emacs-directory "init.org")))
  30. ;; Avoid running hooks when tangling.
  31. (let ((prog-mode-hook nil))
  32. (org-babel-tangle)
  33. (byte-compile-file (concat user-emacs-directory "init.el")))))
  34. (add-hook 'after-save-hook 'tangle-init)
  35. #+END_SRC
  36. * Config
  37. ** Packages
  38. #+BEGIN_SRC emacs-lisp :results silent
  39. (require 'package)
  40. (defvar my-packages
  41. '(all-the-icons
  42. anzu
  43. base16-theme
  44. bbdb
  45. better-defaults
  46. company
  47. company-go
  48. counsel
  49. counsel-projectile
  50. dash-at-point
  51. diminish
  52. dockerfile-mode
  53. doom-modeline
  54. doom-themes
  55. ein
  56. eldoc-eval
  57. elfeed
  58. elfeed-org
  59. elpy
  60. expand-region
  61. fic-mode
  62. flycheck
  63. gitignore-mode
  64. go-mode
  65. go-playground
  66. gorepl-mode
  67. iedit
  68. ivy
  69. ivy-hydra
  70. jabber
  71. json-mode
  72. magit
  73. material-theme
  74. multiple-cursors
  75. projectile
  76. rainbow-delimiters
  77. shrink-path
  78. tide
  79. typescript-mode
  80. ;; use-package
  81. web-mode
  82. which-key))
  83. (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
  84. (add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/"))
  85. (when (not package-archive-contents)
  86. (package-refresh-contents))
  87. (package-initialize)
  88. (dolist (p my-packages)
  89. (when (not (package-installed-p p))
  90. (package-install p)))
  91. #+END_SRC
  92. ** Server
  93. #+BEGIN_SRC emacs-lisp :results silent
  94. (require 'edit-server)
  95. (edit-server-start)
  96. #+END_SRC
  97. ** Better Defaults
  98. #+BEGIN_SRC emacs-lisp :results silent
  99. (require 'better-defaults)
  100. ;; Instead of the annoying giant warning icon, just flash the modeline.
  101. ;; (this happens when you do something like C-g)
  102. (setq ring-bell-function
  103. (lambda ()
  104. (let ((orig-fg (face-foreground 'mode-line)))
  105. (set-face-foreground 'mode-line "#F2804F")
  106. (run-with-idle-timer 0.1 nil
  107. (lambda (fg) (set-face-foreground 'mode-line fg))
  108. orig-fg))))
  109. (defun set-frame-size-according-to-resolution ()
  110. "Set the Emacs window size on startup."
  111. (interactive)
  112. (if window-system
  113. (progn
  114. ;; WIDTH
  115. (if (> (x-display-pixel-width) 1280)
  116. ;; Large Screen (only show 120 cols)
  117. (add-to-list 'default-frame-alist (cons 'width 240))
  118. ;; Small Screen (fill window)
  119. (add-to-list 'default-frame-alist (cons 'width (/ (x-display-pixel-width) (frame-char-width)))))
  120. ;; HEIGHT
  121. (if (> (x-display-pixel-height) 1080)
  122. ;; Large Screen (only fill half screen)
  123. (add-to-list 'default-frame-alist (cons 'height (/ (/ (x-display-pixel-height) 2)
  124. (frame-char-height))))
  125. ;; Small Screen (fill window)
  126. (add-to-list 'default-frame-alist (cons 'height (/ (x-display-pixel-height) (frame-char-height)))))
  127. )))
  128. (set-frame-size-according-to-resolution)
  129. (defun window-px-width ()
  130. "Get the width of the Emacs window in pixels."
  131. (interactive)
  132. (* (* (window-total-width) 2.874) (frame-char-width)))
  133. (defun window-px-left-pos ()
  134. "Calculate the left position of the Emacs window."
  135. (interactive)
  136. (/ (- (x-display-pixel-width) (window-px-width)) 2))
  137. (add-to-list 'default-frame-alist (cons 'top 0))
  138. (add-to-list 'default-frame-alist (cons 'left 1000))
  139. #+END_SRC
  140. ** Enable Disabled Commands
  141. #+BEGIN_SRC emacs-lisp :results silent
  142. (put 'narrow-to-region 'disabled nil)
  143. (put 'upcase-region 'disabled nil)
  144. (put 'downcase-region 'disabled nil)
  145. #+END_SRC
  146. ** Splash Screen
  147. #+BEGIN_SRC emacs-lisp :results silent
  148. (setq inhibit-splash-screen t
  149. fancy-splash-image "~/.emacs.d/public/emacs-logo.png"
  150. fancy-splash-image-file "~/.emacs.d/public/emacs-logo.png")
  151. #+END_SRC
  152. ** Basic Customization
  153. #+BEGIN_SRC emacs-lisp :results silent
  154. (defvar backup-dir (expand-file-name "~/.emacs.d/backup/"))
  155. (defvar autosave-dir (expand-file-name "~/.emacs.d/autosave/"))
  156. (setq initial-scratch-message nil
  157. backup-directory-alist (list (cons ".*" backup-dir))
  158. auto-save-list-file-prefix autosave-dir
  159. auto-save-file-name-transforms `((".*" ,autosave-dir t)))
  160. (menu-bar-mode 0)
  161. (scroll-bar-mode 0)
  162. (tool-bar-mode 0)
  163. (setq auth-sources '("~/.authinfo.gpg"))
  164. (set-default 'truncate-lines t)
  165. ;; (load-theme 'doom-city-lights t)
  166. ;; (load-theme 'doom-dracula t)
  167. ;; (load-theme 'doom-nord t)
  168. (load-theme 'doom-one t)
  169. ;; (load-theme 'doom-spacegrey t)
  170. ;; (load-theme 'base16-ocean t)
  171. (load-theme 'base16-onedark t)
  172. (global-linum-mode t)
  173. (global-auto-revert-mode t)
  174. (defalias 'yes-or-no-p 'y-or-n-p)
  175. #+END_SRC
  176. ** Custom Modes
  177. #+BEGIN_SRC emacs-lisp :results silent
  178. (require 'font-lock)
  179. (defvar openhab-mode-hook nil)
  180. (defvar openhab-mode-map
  181. (let ((map (make-keymap)))
  182. (define-key map "\C-j" 'newline-and-indent)
  183. map)
  184. "Keymap for OPENHAB major mode.")
  185. (add-to-list 'auto-mode-alist '("\\.sitemap\\'" . openhab-mode))
  186. (add-to-list 'auto-mode-alist '("\\.items\\'" . openhab-mode))
  187. (add-to-list 'auto-mode-alist '("\\.rules\\'" . openhab-mode))
  188. (add-to-list 'auto-mode-alist '("\\.things\\'" . openhab-mode))
  189. (defconst openhab-font-lock-keywords
  190. `(
  191. ("\<.*\>" . font-lock-constant-face)
  192. (,(regexp-opt
  193. '(
  194. ;; KEYWORDS
  195. "Selection" "Slider" "List" "Setpoint" "Video" "Chart" "Webview" "Colorpicker"
  196. "Timer" "Number" "String"
  197. "Switch" "Rollershutter" "Number" "String" "Dimmer" "Contact" "DateTime" "Color"
  198. "Text" "Group" "Image" "Frame"
  199. "Thing" "Bridge"
  200. "Time" "System"
  201. "sitemap"
  202. "rule" "when" "then" "end"
  203. "if" "val"
  204. "import" "var" "say" "postUpdate" "switch" "println" "case" "or" "sendCommand"
  205. )
  206. 'words)
  207. (1 font-lock-keyword-face))
  208. (,(regexp-opt
  209. '(
  210. "ON" "OFF" "on" "off"
  211. "AND" "OR" "NAND" "NOR" "AVG" "SUM" "MAX" "MIN"
  212. "true" "false"
  213. )
  214. 'words)
  215. (1 font-lock-constant-face))
  216. (,(regexp-opt
  217. '(
  218. "name" "label" "item" "period" "refresh" "icon" "mappings" "minValue" "maxValue" "step" "switchsupport" "url" "height" "refresh" "visibility" "valuecolor"
  219. )
  220. 'words)
  221. (1 font-lock-type-face))
  222. ("\(.*\)" . font-lock-variable-name-face)
  223. ("[^a-zA-Z0-9_:]\\([0-9]*\\)[^a-zA-Z0-9_:]" . (1 font-lock-variable-name-face))
  224. ("\s@\s" . font-lock-variable-name-face)
  225. ("\s\\([a-zA-Z0-9_:]*\\)\\(\s\\|$\\)" . (1 font-lock-type-face))
  226. ("=\\([a-zA-Z_]*\\)" . (1 font-lock-string-face))
  227. ("\\([a-zA-Z]*\\)=" . (1 font-lock-type-face))
  228. )
  229. "The regexps to highlight in openHAB mode.")
  230. (defvar openhab-mode-syntax-table
  231. (let ((st (make-syntax-table)))
  232. (modify-syntax-entry ?/ ". 12b" st) ;; C-style comments // ...
  233. (modify-syntax-entry ?\n "> b" st) ;; \n ends comment
  234. ;; Block comments /*...*/
  235. (modify-syntax-entry ?\/ ". 14" st)
  236. (modify-syntax-entry ?* ". 23" st)
  237. st)
  238. "Syntax table for openhab-mode.")
  239. (defun openhab-mode ()
  240. "Major mode for editing OPENHAB config files."
  241. (interactive)
  242. (kill-all-local-variables)
  243. (set-syntax-table openhab-mode-syntax-table)
  244. (use-local-map openhab-mode-map)
  245. (set (make-local-variable 'font-lock-defaults) '(openhab-font-lock-keywords nil t))
  246. (electric-pair-mode -1)
  247. (flycheck-mode -1)
  248. (setq major-mode 'openhab-mode)
  249. (setq mode-name "OpenHAB")
  250. (run-hooks 'openhab-mode-hook))
  251. (provide 'openhab-mode)
  252. #+END_SRC
  253. ** Custom Packages
  254. *** Hyperspace
  255. #+BEGIN_SRC emacs-lisp :results silent
  256. ;;; hyperspace.el --- Get there from here -*- lexical-binding: t; -*-
  257. ;; Copyright (C) 2017-2019 Ian Eure
  258. ;; Author: Ian Eure <ian@retrospec.tv>
  259. ;; URL: https://github.com/ieure/hyperspace-el
  260. ;; Version: 0.8.4
  261. ;; Package-Requires: ((emacs "25") (s "1.12.0"))
  262. ;; Keywords: tools, convenience
  263. ;; This program is free software; you can redistribute it and/or modify
  264. ;; it under the terms of the GNU General Public License as published by
  265. ;; the Free Software Foundation, either version 3 of the License, or
  266. ;; (at your option) any later version.
  267. ;; This program is distributed in the hope that it will be useful,
  268. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  269. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  270. ;; GNU General Public License for more details.
  271. ;; You should have received a copy of the GNU General Public License
  272. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  273. ;;; Commentary:
  274. ;; Hyperspace is a way to get nearly anywhere from wherever you are,
  275. ;; whether that's within Emacs or on the web. It's somewhere in
  276. ;; between Quicksilver and keyword URLs, giving you a single,
  277. ;; consistent interface to get directly where you want to go. It’s
  278. ;; for things that you use often, but not often enough to justify a
  279. ;; dedicated binding.
  280. ;;
  281. ;; When you enter Hyperspace, it prompts you where to go:
  282. ;;
  283. ;; HS:
  284. ;;
  285. ;; This prompt expects a keyword and a query. The keyword picks where
  286. ;; you want to go, and the remainder of the input is an optional
  287. ;; argument which can be used to further search or direct you within
  288. ;; that space.
  289. ;;
  290. ;; Some concrete examples:
  291. ;;
  292. ;; | *If you enter* | *then Hyperspace* |
  293. ;; |------------------+----------------------------------------------------------|
  294. ;; | "el" | opens info node "(elisp)Top" |
  295. ;; | "el eval-region" | searches for "eval-region" in the elisp Info index |
  296. ;; | "bb" | shows all BBDB entries |
  297. ;; | "bb kenneth" | shows all BBDB entries with a name matching "kenneth" |
  298. ;; | "ddg foo" | searches DuckDuckGo for "foo" using browse-url |
  299. ;; | "wp foo" | searches Wikipedia for "foo" using browse-url |
  300. ;;
  301. ;;; Code:
  302. (require 'subr-x)
  303. (require 's)
  304. ;; Action helpers
  305. (defun hyperspace-action->browse-url-pattern (pattern query)
  306. "Browse a URL former from PATTERN and QUERY."
  307. (browse-url (format pattern query)))
  308. (defun hyperspace-action->info (node &optional query)
  309. "Open an Info buffer for NODE.
  310. If QUERY is present, look it up in the index."
  311. (info node)
  312. (when query
  313. (Info-index query)))
  314. ;; Package definitions
  315. (defvar hyperspace-history nil
  316. "History of Hyperspace actions.")
  317. (defgroup hyperspace nil
  318. "Getting there from here"
  319. :prefix "hyperspace-"
  320. :group 'applications)
  321. (defcustom hyperspace-actions
  322. '(("ddg" . "https://duckduckgo.com/?q=%s")
  323. ("dis" . "https://duckduckgo.com/?q=%s&iax=images&ia=images")
  324. ("wp" . "https://en.wikipedia.org/wiki/%s")
  325. ("g" . "https://www.google.com/search?q=%s")
  326. ("gi" . "https://www.google.com/search?tbm=isch&q=%s")
  327. ("gm" . "https://www.google.com/maps/search/%s")
  328. ("yt" . "https://www.youtube.com/results?search_query=%s")
  329. ("clp" . "https://portland.craigslist.org/search/sss?query=%s")
  330. ("eb" . "https://www.ebay.com/sch/i.html?_nkw=%s")
  331. ("nf" . "https://www.netflix.com/search?q=%s")
  332. ("sh" . (lambda (query) (interactive) (shell-command query)))
  333. ("imdb" . "https://www.imdb.com/find?q=peter+jackson&s=all")
  334. ("bb" . bbdb-search-name)
  335. ("el" . (apply-partially #'hyperspace-action->info "(elisp)Top"))
  336. ("av" . apropos-variable)
  337. ("ac" . apropos-command)
  338. ("af" . (lambda (query) (apropos-command query t))))
  339. "Where Hyperspace should send you.
  340. Hyperspace actions are a cons of (KEYWORD . DISPATCHER). When
  341. Hyperspace is invoked, the keyword is extracted from the user
  342. input and looked up in this alist. The remainder of the
  343. string is passed to the dispatcher as its QUERY argument.
  344. DISPATCHER can be a function which performs the action.
  345. DISPATCHER can also be an expression which returns a function
  346. to perform the action.
  347. Finally, DISPATCHER can be a string with a URL pattern containing
  348. '%s'. The '%s' will be replaced with the query, and the URL browsed."
  349. :group 'hyperspace
  350. :type '(alist :key-type (string :tag "Keyword")
  351. :value-type (choice
  352. (function :tag "Function")
  353. (string :tag "URL Pattern")
  354. (sexp :tag "Expression"))))
  355. (defcustom hyperspace-default-action
  356. (caar hyperspace-actions)
  357. "A place to go if you don't specify one."
  358. :group 'hyperspace
  359. :type `(radio
  360. ,@(mapcar (lambda (action) (list 'const (car action))) hyperspace-actions)))
  361. (defcustom hyperspace-max-region-size 256
  362. "Maximum size of a region to consider for a Hyperspace query.
  363. If the region is active when Hyperspace is invoked, it's used
  364. as the default query, unless it's more than this number of
  365. characters."
  366. :group 'hyperspace
  367. :type 'integer)
  368. (defun hyperspace--cleanup (text)
  369. "Clean TEXT so it can be used for a Hyperspace query."
  370. (save-match-data
  371. (string-trim
  372. (replace-regexp-in-string (rx (1+ (or blank "\n"))) " " text))))
  373. (defun hyperspace--initial-text ()
  374. "Return the initial text.
  375. This is whatever's in the active region, but cleaned up."
  376. (when (use-region-p)
  377. (let* ((start (region-beginning))
  378. (end (region-end))
  379. (size (- end start)))
  380. (when (<= size hyperspace-max-region-size)
  381. (hyperspace--cleanup
  382. (buffer-substring-no-properties start end))))))
  383. (defun hyperspace--initial (initial-text)
  384. "Turn INITIAL-TEXT into INITIAL-CONTENTS for reading."
  385. (when initial-text (cons (concat " " initial-text) 1)))
  386. (defun hyperspace--process-input (text)
  387. "Process TEXT into an actionable keyword and query."
  388. (let ((kw-text (s-split-up-to "\\s-+" text 1)))
  389. (if (assoc (car kw-text) hyperspace-actions)
  390. kw-text
  391. (list hyperspace-default-action text))))
  392. (defun hyperspace--query ()
  393. "Ask the user for the Hyperspace action and query.
  394. Returns (KEYWORD . QUERY).
  395. If the region isn't active, the user is prompted for the
  396. action and query.
  397. If the region is active, its text is used as the initial value
  398. for the query, and the user enters the action.
  399. If a prefix argument is specified and the region is active,
  400. `HYPERSPACE-DEFAULT-ACTION' is chosen without prompting."
  401. (let ((initial (hyperspace--initial-text)))
  402. (if (and initial current-prefix-arg)
  403. (list hyperspace-default-action initial)
  404. (hyperspace--process-input
  405. (read-from-minibuffer "HS: " (hyperspace--initial initial) nil nil
  406. 'hyperspace-history)))))
  407. (defun hyperspace--evalable-p (form)
  408. "Can FORM be evaluated?"
  409. (and (listp form)
  410. (or (functionp (car form))
  411. (subrp (car form)))))
  412. (defun hyperspace--dispatch (action &optional query)
  413. "Execute ACTION, with optional QUERY argument."
  414. (pcase action
  415. ((pred functionp) (funcall action query))
  416. ((pred hyperspace--evalable-p) (funcall (eval action) query))
  417. ((pred stringp) (hyperspace-action->browse-url-pattern action query))
  418. (_ (error "Unknown action"))))
  419. ;;;###autoload
  420. (defun hyperspace (keyword &optional query)
  421. "Execute action for keyword KEYWORD, with optional QUERY."
  422. (interactive (hyperspace--query))
  423. (let ((action (cdr (assoc keyword hyperspace-actions))))
  424. (hyperspace--dispatch (or action hyperspace-default-action) query)))
  425. ;;;###autoload
  426. (defun hyperspace-enter (&optional query)
  427. "Enter Hyperspace, sending QUERY to the default action.
  428. If the region is active, use that as the query for
  429. ‘hyperspace-default-action’. Otherwise, prompt the user."
  430. (interactive (list (hyperspace--initial-text)))
  431. (hyperspace
  432. hyperspace-default-action
  433. (or query
  434. (read-from-minibuffer
  435. (format "HS: %s " hyperspace-default-action) nil nil
  436. 'hyperspace-history))))
  437. ;; Minor mode
  438. (defvar hyperspace-minor-mode-map
  439. (let ((kmap (make-sparse-keymap)))
  440. (define-key kmap (kbd "H-SPC") #'hyperspace)
  441. (define-key kmap (kbd "<H-return>") #'hyperspace-enter)
  442. kmap))
  443. ;;;###autoload
  444. (define-minor-mode hyperspace-minor-mode
  445. "Global (universal) minor mode to jump from here to there."
  446. nil nil hyperspace-minor-mode-map
  447. :group 'hyperspace
  448. :global t)
  449. (provide 'hyperspace)
  450. ;;; hyperspace.el ends here
  451. #+END_SRC
  452. ** Tools
  453. *** General
  454. #+BEGIN_SRC emacs-lisp :results silent
  455. (require 'which-key)
  456. (which-key-setup-minibuffer)
  457. (which-key-mode)
  458. (require 'fic-mode)
  459. (add-hook 'js-mode-hook 'fic-mode)
  460. #+END_SRC
  461. *** Company
  462. #+BEGIN_SRC emacs-lisp :results silent
  463. (require 'company)
  464. (add-hook 'after-init-hook 'global-company-mode)
  465. (setq company-dabbrev-downcase nil)
  466. (setq company-idle-delay 0.1)
  467. #+END_SRC
  468. *** Diminish
  469. #+BEGIN_SRC emacs-lisp :results silent
  470. (require 'diminish)
  471. (diminish 'auto-revert-mode)
  472. (eval-after-load "company" '(diminish 'company-mode))
  473. (eval-after-load "counsel" '(diminish 'counsel-mode))
  474. (eval-after-load "elpy" '(diminish 'elpy-mode))
  475. (eval-after-load "go-mode" '(diminish 'go-mode))
  476. (eval-after-load "go-playground" '(diminish 'go-playground-mode))
  477. (eval-after-load "gorepl-mode" '(diminish 'gorepl-mode))
  478. (eval-after-load "flycheck" '(diminish 'flycheck-mode))
  479. (eval-after-load "ivy" '(diminish 'ivy-mode))
  480. (eval-after-load "projectile" '(diminish 'projectile-mode))
  481. (eval-after-load "which-key" '(diminish 'which-key-mode))
  482. #+END_SRC
  483. *** Dired
  484. #+BEGIN_SRC emacs-lisp :results silent
  485. (defun dired-mode-setup ()
  486. "Will run as hook for `dired-mode'."
  487. (dired-hide-details-mode nil))
  488. (add-hook 'dired-mode-hook 'dired-mode-setup)
  489. #+END_SRC
  490. *** Ivy
  491. #+BEGIN_SRC emacs-lisp :results silent
  492. (require 'ivy-hydra)
  493. (require 'ivy)
  494. (require 'swiper)
  495. (ivy-mode 1)
  496. (counsel-mode)
  497. (setq ivy-use-virtual-buffers t
  498. enable-recursive-minibuffers t
  499. ivy-height 25
  500. ivy-initial-inputs-alist nil
  501. ivy-extra-directories nil)
  502. (global-set-key (kbd "C-s") 'swiper)
  503. (global-set-key (kbd "C-c C-r") 'ivy-resume)
  504. (global-set-key (kbd "M-x") 'counsel-M-x)
  505. (global-set-key (kbd "C-x C-f") 'counsel-find-file)
  506. (global-set-key (kbd "C-c g") 'counsel-git)
  507. (global-set-key (kbd "C-c j") 'counsel-git-grep)
  508. (global-set-key (kbd "C-c k") 'counsel-ag)
  509. (define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history)
  510. (defun ivy-open-current-typed-path ()
  511. (interactive)
  512. (when ivy--directory
  513. (let* ((dir ivy--directory)
  514. (text-typed ivy-text)
  515. (path (concat dir text-typed)))
  516. (delete-minibuffer-contents)
  517. (ivy--done path))))
  518. (define-key ivy-minibuffer-map (kbd "<return>") 'ivy-alt-done)
  519. (define-key ivy-minibuffer-map (kbd "C-f") 'ivy-open-current-typed-path)
  520. #+END_SRC
  521. *** Magit
  522. #+BEGIN_SRC emacs-lisp :results silent
  523. (require 'magit)
  524. (global-set-key (kbd "C-x g") 'magit-status)
  525. (global-set-key (kbd "C-c g") 'magit-status)
  526. (setq magit-completing-read-function 'ivy-completing-read)
  527. #+END_SRC
  528. *** Mu4e
  529. #+BEGIN_SRC emacs-lisp :results silent
  530. (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu/mu4e")
  531. (require 'mu4e)
  532. ;; default
  533. (setq mu4e-maildir "~/Mail"
  534. mu4e-mu-binary "/usr/local/bin/mu"
  535. mu4e-change-filenames-when-moving t ;; Rename files when moving (required by mbsync)
  536. mu4e-compose-in-new-frame t ;; New compose gets new frame
  537. mu4e-context-policy 'pick-first
  538. mu4e-get-mail-command "mbsync -a" ;; MBSYNC is the mail cmd
  539. mu4e-html2text-command "/usr/local/bin/w3m -T text/html" ;; HTML to text command
  540. mu4e-sent-messages-behavior 'delete ;; Delete sent messages
  541. mu4e-update-interval 300 ;; 5 mins
  542. mu4e-use-fancy-chars t ;; use 'fancy' chars
  543. mu4e-user-mail-address-list '("lolson@eaglecrk.com"
  544. "lolson@vlocity.com"
  545. "olson.levi@gmail.com")
  546. mu4e-view-show-images t ;; attempt to show images
  547. mu4e-view-image-max-width 400 ;; max image size
  548. message-citation-line-format "On %a %d %b %Y at %R, %f wrote:\n" ;; customize the reply-quote-string
  549. message-citation-line-function 'message-insert-formatted-citation-line ;; choose to use the formatted string
  550. message-kill-buffer-on-exit t ;; don't keep messages around
  551. send-mail-function 'smtpmail-send-it ;; Default email send function
  552. smtpmail-default-smtp-server "smtp.gmail.com"
  553. smtpmail-smtp-service 587
  554. )
  555. (defun mdmail-send-buffer ()
  556. (interactive)
  557. (shell-command-on-region (point-min) (point-max) "mdmail"))
  558. (setq mu4e-contexts
  559. `(
  560. ;; ,(make-mu4e-context
  561. ;; :name "Vlocity"
  562. ;; :enter-func (lambda () (mu4e-message "Entering Vlocity"))
  563. ;; :leave-func (lambda () (mu4e-message "Leaving Vlocity"))
  564. ;; ;; we match based on the contact-fields of the message
  565. ;; :match-func (lambda (msg)
  566. ;; (when msg
  567. ;; (string= (mu4e-message-field msg :maildir) "/Vlocity")))
  568. ;; :vars '( ( user-mail-address . "lolson@vlocity.com" )
  569. ;; ( smtpmail-mail-address . "lolson@vlocity.com" )
  570. ;; ( smtpmail-smtp-user . "lolson@vlocity.com" )
  571. ;; ( smtpmail-smtp-server . "smtp.gmail.com" )
  572. ;; ( user-full-name . "Levi Olson" )
  573. ;; ( mu4e-compose-signature .
  574. ;; (concat
  575. ;; "Levi Olson\n"
  576. ;; "Senior UI Developer"))
  577. ;; ( mu4e-sent-folder . "/Vlocity/[Gmail].Sent Mail" )
  578. ;; ( mu4e-drafts-folder . "/Vlocity/[Gmail].Drafts" )
  579. ;; ( mu4e-trash-folder . "/Vlocity/[Gmail].Trash" )
  580. ;; ( mu4e-maildir-shortcuts . (("/Vlocity/INBOX" . ?i)
  581. ;; ("/Vlocity/[Gmail].Sent Mail" . ?s)
  582. ;; ("/Vlocity/[Gmail].Trash" . ?t)
  583. ;; ("/Vlocity/[Gmail].All Mail" . ?a)))))
  584. ,(make-mu4e-context
  585. :name "EagleCreek"
  586. :enter-func (lambda () (mu4e-message "Entering EagleCreek"))
  587. :leave-func (lambda () (mu4e-message "Leaving EagleCreek"))
  588. ;; we match based on the contact-fields of the message
  589. :match-func (lambda (msg)
  590. (when msg
  591. (string= (mu4e-message-field msg :maildir) "/eaglecrk")))
  592. :vars '( ( user-mail-address . "lolson@eaglecrk.com" )
  593. ( smtpmail-mail-address . "lolson@eaglecrk.com" )
  594. ( smtpmail-smtp-user . "lolson@eaglecrk.com" )
  595. ( smtpmail-smtp-server . "smtp.office365.com" )
  596. ( user-full-name . "Levi Olson" )
  597. ;; ( mu4e-compose-signature .
  598. ;; (concat
  599. ;; "Levi Olson\n"
  600. ;; "Eagle Creek Software Services\n"
  601. ;; "Senior Application Developer Consultant\n"))
  602. ( mu4e-sent-folder . "/eaglecrk/Sent Items" )
  603. ( mu4e-drafts-folder . "/eaglecrk/Drafts" )
  604. ( mu4e-trash-folder . "/eaglecrk/Deleted Items" )
  605. ( mu4e-maildir-shortcuts . (("/eaglecrk/Inbox" . ?i)
  606. ("/eaglecrk/Sent Items" . ?s)
  607. ("/eaglecrk/Deleted Items" . ?t)
  608. ("/eaglecrk/Archive" . ?a)))))
  609. ;; ,(make-mu4e-context
  610. ;; :name "Gmail"
  611. ;; :enter-func (lambda () (mu4e-message "Entering Gmail"))
  612. ;; :leave-func (lambda () (mu4e-message "Leaving Gmail"))
  613. ;; ;; this matches maildir /Arkham and its sub-directories
  614. ;; :match-func (lambda (msg)
  615. ;; (when msg
  616. ;; (string= (mu4e-message-field msg :maildir) "/Gmail")))
  617. ;; :vars '( ( user-mail-address . "olson.levi@gmail.com" )
  618. ;; ( smtpmail-mail-address . "olson.levi@gmail.com" )
  619. ;; ( smtpmail-smtp-user . "olson.levi@gmail.com" )
  620. ;; ( smtpmail-smtp-server . "smtp.gmail.com" )
  621. ;; ( user-full-name . "Levi Olson" )
  622. ;; ( mu4e-compose-signature .
  623. ;; (concat
  624. ;; "Levi\n"))
  625. ;; ( mu4e-sent-folder . "/Gmail/[Gmail].Sent Mail" )
  626. ;; ( mu4e-drafts-folder . "/Gmail/[Gmail].Drafts" )
  627. ;; ( mu4e-trash-folder . "/Gmail/[Gmail].Trash" )
  628. ;; ( mu4e-maildir-shortcuts . (("/Gmail/INBOX" . ?i)
  629. ;; ("/Gmail/[Gmail].Sent Mail" . ?s)
  630. ;; ("/Gmail/[Gmail].Trash" . ?t)
  631. ;; ("/Gmail/[Gmail].All Mail" . ?a))
  632. ;; )))
  633. ))
  634. ;; Add option to view HTML in browser
  635. (add-to-list 'mu4e-headers-actions
  636. '("in browser" . mu4e-action-view-in-browser) t)
  637. (add-to-list 'mu4e-view-actions
  638. '("in browser" . mu4e-action-view-in-browser) t)
  639. (defun my-message-current-line-cited-p ()
  640. "Indicate whether the line at point is a cited line."
  641. (save-match-data
  642. (string-match (concat "^" message-cite-prefix-regexp)
  643. (buffer-substring (line-beginning-position) (line-end-position)))))
  644. (defun my-message-says-attachment-p ()
  645. "Return t if the message suggests there can be an attachment."
  646. (save-excursion
  647. (goto-char (point-min))
  648. (save-match-data
  649. (let (search-result)
  650. (while
  651. (and (setq search-result (re-search-forward "\\(attach\\|pdf\\|file\\)" nil t))
  652. (my-message-current-line-cited-p)))
  653. search-result))))
  654. (defun my-message-has-attachment-p ()
  655. "Return t if the message has an attachment."
  656. (save-excursion
  657. (goto-char (point-min))
  658. (save-match-data
  659. (re-search-forward "<#part" nil t))))
  660. (defun my-message-pre-send-check-attachment ()
  661. (when (and (my-message-says-attachment-p)
  662. (not (my-message-has-attachment-p)))
  663. (unless
  664. (y-or-n-p "No attachment. Send anyway?")
  665. (error "It seems that an attachment is needed, but none was found. Aborting sending."))))
  666. (add-hook 'message-send-hook 'my-message-pre-send-check-attachment)
  667. #+END_SRC
  668. *** Projectile
  669. #+BEGIN_SRC emacs-lisp :results silent
  670. (require 'projectile)
  671. (require 'counsel-projectile)
  672. (projectile-mode)
  673. (setq projectile-mode-line '(:eval (format " %s" (projectile-project-name)))
  674. projectile-remember-window-configs t
  675. projectile-completion-system 'ivy)
  676. (counsel-projectile-mode)
  677. #+END_SRC
  678. *** Notify
  679. #+BEGIN_SRC emacs-lisp :results silent
  680. ;;; notify.el --- notification front-end
  681. ;; Copyright (C) 2008 Mark A. Hershberger
  682. ;; Original Author: Mark A. Hershberger <mhersberger@intrahealth.org>
  683. ;; Modified by Andrey Kotlarski <m00naticus@gmail.com>
  684. ;; Modified by Andrew Gwozdziewycz <git@apgwoz.com>
  685. ;; Modified by Aidan Gauland <aidalgol@no8wireless.co.nz> October 2011
  686. ;; Modified by Olivier Sirven <the.slaa@gmail.com> November 2013
  687. ;; Keywords: extensions, convenience, lisp
  688. ;; This file is free software; you can redistribute it and/or modify
  689. ;; it under the terms of the GNU General Public License as published by
  690. ;; the Free Software Foundation; either version 2, or (at your option)
  691. ;; any later version.
  692. ;; This file is distributed in the hope that it will be useful,
  693. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  694. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  695. ;; GNU General Public License for more details.
  696. ;; You should have received a copy of the GNU General Public License
  697. ;; along with GNU Emacs; see the file COPYING. If not, write to
  698. ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  699. ;; Boston, MA 02111-1307, USA.
  700. ;;; Commentary:
  701. ;; This provides a single function, `notify', that will produce a notify
  702. ;; pop-up via D-Bus, libnotify, simple message or growl.
  703. ;; To use, just put (autoload 'notify "notify" "Notify TITLE, BODY.")
  704. ;; in your init file. You may override default chosen notification
  705. ;; method by assigning `notify-method' to one of 'notify-via-dbus
  706. ;; 'notify-via-libnotify or 'notify-via-message
  707. ;;; Code:
  708. (defvar notify-defaults (list :app "Emacs" :icon "emacs" :timeout 5000
  709. :urgency "low"
  710. :category "emacs.message")
  711. "Notification settings' defaults.
  712. May be overridden with key-value additional arguments to `notify'.")
  713. (defvar notify-delay '(0 5 0)
  714. "Minimum time allowed between notifications in time format.")
  715. (defvar notify-last-notification '(0 0 0) "Time of last notification.")
  716. (defvar notify-method 'notify-via-growl "Notification method among
  717. 'notify-via-dbus, 'notify-via-libnotify, 'notify-via-message or
  718. 'notify-via-growl")
  719. ;; determine notification method unless already set
  720. ;; prefer growl > D-Bus > libnotify > message
  721. (cond
  722. ((null notify-method)
  723. (setq notify-method
  724. (cond
  725. ((executable-find "growlnotify") 'notify-via-growl)
  726. ((and (require 'dbus nil t)
  727. (dbus-ping :session "org.freedesktop.Notifications"))
  728. (defvar notify-id 0 "Current D-Bus notification id.")
  729. 'notify-via-dbus)
  730. ((executable-find "notify-send") 'notify-via-libnotify)
  731. (t 'notify-via-message))))
  732. ((eq notify-method 'notify-via-dbus) ;housekeeping for pre-chosen DBus
  733. (if (and (require 'dbus nil t)
  734. (dbus-ping :session "org.freedesktop.Notifications"))
  735. (defvar notify-id 0 "Current D-Bus notification id.")
  736. (setq notify-method (if (executable-find "notify-send")
  737. 'notify-via-libnotify
  738. 'notify-via-message))))
  739. ((and (eq notify-method 'notify-via-libnotify)
  740. (not (executable-find "notify-send"))) ;housekeeping for pre-chosen libnotify
  741. (setq notify-method
  742. (if (and (require 'dbus nil t)
  743. (dbus-ping :session "org.freedesktop.Notifications"))
  744. (progn
  745. (defvar notify-id 0 "Current D-Bus notification id.")
  746. 'notify-via-dbus)
  747. 'notify-via-message)))
  748. ((and (eq notify-method 'notify-via-growl)
  749. (not (executable-find "growlnotify")))
  750. (setq notify-method 'notify-via-message)))
  751. (defun notify-via-dbus (title body)
  752. "Send notification with TITLE, BODY `D-Bus'."
  753. (dbus-call-method :session "org.freedesktop.Notifications"
  754. "/org/freedesktop/Notifications"
  755. "org.freedesktop.Notifications" "Notify"
  756. (get 'notify-defaults :app)
  757. (setq notify-id (+ notify-id 1))
  758. (get 'notify-defaults :icon) title body '(:array)
  759. '(:array :signature "{sv}") ':int32
  760. (get 'notify-defaults :timeout)))
  761. (defun notify-via-libnotify (title body)
  762. "Notify with TITLE, BODY via `libnotify'."
  763. (call-process "notify-send" nil 0 nil
  764. title body "-t"
  765. (number-to-string (get 'notify-defaults :timeout))
  766. "-i" (get 'notify-defaults :icon)
  767. "-u" (get 'notify-defaults :urgency)
  768. "-c" (get 'notify-defaults :category)))
  769. (defun notify-via-message (title body)
  770. "Notify TITLE, BODY with a simple message."
  771. (message "%s: %s" title body))
  772. (defun notify-via-growl (title body)
  773. "Notify TITLE, BODY with a growl"
  774. (call-process "growlnotify" nil 0 nil
  775. "-a" (get 'notify-defaults :app)
  776. "-n" (get 'notify-defaults :category)
  777. "-t" (notify-via-growl-stringify title)
  778. "-m" (notify-via-growl-stringify body)))
  779. (defun notify-via-growl-stringify (thing)
  780. (cond ((null thing) "")
  781. ((stringp thing) thing)
  782. (t (format "%s" thing))))
  783. (defun keywords-to-properties (symbol args &optional defaults)
  784. "Add to SYMBOL's property list key-values from ARGS and DEFAULTS."
  785. (when (consp defaults)
  786. (keywords-to-properties symbol defaults))
  787. (while args
  788. (put symbol (car args) (cadr args))
  789. (setq args (cddr args))))
  790. ;;;###autoload
  791. (defun notify (title body &rest args)
  792. "Notify TITLE, BODY via `notify-method'.
  793. ARGS may be amongst :timeout, :icon, :urgency, :app and :category."
  794. (when (time-less-p notify-delay
  795. (time-since notify-last-notification))
  796. (or (eq notify-method 'notify-via-message)
  797. (keywords-to-properties 'notify-defaults args
  798. notify-defaults))
  799. (setq notify-last-notification (current-time))
  800. (funcall notify-method title body)))
  801. (provide 'notify)
  802. ;;; notify.el ends here
  803. #+END_SRC
  804. *** Jabber
  805. #+BEGIN_SRC emacs-lisp :results silent
  806. (require 'jabber)
  807. (setq jabber-history-enabled t
  808. jabber-use-global-history nil
  809. jabber-backlog-number 40
  810. jabber-backlog-days 30
  811. jabber-alert-presence-message-function (lambda (_who _oldstatus _newstatus _statustext) nil)
  812. )
  813. (setq jabber-account-list '(
  814. ;; ("olson.levi@gmail.com"
  815. ;; (:network-server . "talk.google.com")
  816. ;; (:connection-type . ssl))
  817. ("lolson@vlocity.com"
  818. (:network-server . "talk.google.com")
  819. (:connection-type . ssl))
  820. ))
  821. (defvar my-chat-prompt "[%t] %n>\n" "Customized chat prompt")
  822. (when (featurep 'jabber)
  823. (setq
  824. jabber-chat-foreign-prompt-format my-chat-prompt
  825. jabber-chat-local-prompt-format my-chat-prompt
  826. jabber-groupchat-prompt-format my-chat-prompt
  827. jabber-muc-private-foreign-prompt-format "[%t] %g/%n>\n"
  828. )
  829. )
  830. (defun notify-jabber-notify (from buf text _proposed-alert)
  831. "(jabber.el hook) Notify of new Jabber chat messages via notify.el"
  832. (when (or jabber-message-alert-same-buffer
  833. (not (memq (selected-window) (get-buffer-window-list buf))))
  834. (if (jabber-muc-sender-p from)
  835. (notify (format "(PM) %s"
  836. (jabber-jid-displayname (jabber-jid-user from)))
  837. (format "%s: %s" (jabber-jid-resource from) text)))
  838. (notify (format "%s" (jabber-jid-displayname from))
  839. text)))
  840. ;; (add-hook 'jabber-alert-message-hooks 'notify-jabber-notify)
  841. ;; (require 'autosmiley)
  842. ;; (add-hook 'jabber-chat-mode-hook 'autosmiley-mode)
  843. (defun jabber ()
  844. (interactive)
  845. (jabber-connect-all)
  846. (switch-to-buffer "*-jabber-roster-*"))
  847. #+END_SRC
  848. *** Terminal-Notifier
  849. #+BEGIN_SRC emacs-lisp :results silent :tangle no
  850. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  851. ;; Terminal notifier
  852. ;; requires 'brew install terminal-notifier'
  853. ;; stolen from erc-notifier
  854. (defvar terminal-notifier-command (executable-find "terminal-notifier") "The path to terminal-notifier.")
  855. ; (terminal-notifier-notify "Emacs notification" "Something amusing happened")
  856. (defun terminal-notifier-notify (title message)
  857. "Show a message with
  858. terminal-notifier-command
  859. ."
  860. (start-process "terminal-notifier"
  861. "terminal-notifier"
  862. terminal-notifier-command
  863. "-title" title
  864. "-message" message
  865. "-activate" "org.gnu.Emacs"))
  866. (defun timed-notification (time msg)
  867. (interactive "sNotification when (e.g: 2 minutes, 60 seconds, 3 days): \nsMessage: ")
  868. (run-at-time time nil (lambda (msg) (terminal-notifier-notify "Emacs" msg)) msg))
  869. #+END_SRC
  870. *** Hyperspace
  871. #+BEGIN_SRC emacs-lisp :results silent
  872. (defun hyperspace-action->mu4e (&optional query)
  873. "Search mu4e with QUERY.
  874. If QUERY is unspecified, use the first bookmark in variable
  875. ‘mu4e-bookmarks’ and update mail and index."
  876. (mu4e-headers-search (or query (caar mu4e-bookmarks)))
  877. (unless query
  878. (mu4e-update-mail-and-index nil)))
  879. (add-to-list 'hyperspace-actions '("m4" . hyperspace-action->mu4e))
  880. (defun hyperspace-action->elfeed (&optional query)
  881. "Load elfeed, optionally searching for QUERY."
  882. (elfeed)
  883. (if query
  884. (elfeed-search-set-filter query)
  885. (elfeed-search-fetch nil)))
  886. (add-to-list 'hyperspace-actions '("lf" . hyperspace-action->elfeed))
  887. #+END_SRC
  888. ** Development Specific
  889. *** General
  890. #+BEGIN_SRC emacs-lisp :results silent
  891. (require 'rainbow-delimiters)
  892. (global-flycheck-mode)
  893. (add-hook 'before-save-hook 'delete-trailing-whitespace)
  894. (add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
  895. (setq-default indent-tabs-mode nil
  896. tab-width 4)
  897. (defvaralias 'c-basic-offset 'tab-width)
  898. (defvaralias 'cperl-indent-level 'tab-width)
  899. (electric-pair-mode 1)
  900. (show-paren-mode 1)
  901. (require 'dockerfile-mode)
  902. (add-to-list 'auto-mode-alist '("Dockerfile*\\'" . dockerfile-mode))
  903. (require 'gitignore-mode)
  904. (add-to-list 'auto-mode-alist '("gitignore\\'" . gitignore-mode))
  905. (require 'json-mode)
  906. (add-to-list 'auto-mode-alist '("\\.json\\'" . json-mode))
  907. (require 'web-mode)
  908. (add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode))
  909. #+END_SRC
  910. *** Python
  911. #+BEGIN_SRC emacs-lisp :results silent
  912. (elpy-enable)
  913. (setq python-shell-interpreter "jupyter"
  914. python-shell-interpreter-args "console --simple-prompt")
  915. (when (require 'flycheck nil t)
  916. (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
  917. (add-hook 'elpy-mode-hook 'flycheck-mode))
  918. (require 'py-autopep8)
  919. (setq py-autopep8-options '("--ignore=E501"))
  920. (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save)
  921. #+END_SRC
  922. *** Go
  923. #+BEGIN_SRC emacs-lisp :results silent
  924. (require 'go-mode)
  925. (require 'go-playground)
  926. (require 'gorepl-mode)
  927. (require 'company-go)
  928. (add-to-list 'auto-mode-alist '("\\.go\\'" . go-mode))
  929. (add-hook 'go-mode-hook (lambda ()
  930. (add-hook 'before-save-hook 'gofmt-before-save)
  931. (local-set-key (kbd "M-.") 'godef-jump)
  932. (local-set-key (kbd "M-,") 'pop-tag-mark)
  933. (local-set-key (kbd "C-c C-c") (lambda ()
  934. (interactive)
  935. (ansi-term)
  936. (comint-send-string "*ansi-term*" "make\n")))
  937. (set (make-local-variable 'company-backends) '(company-go))
  938. (setq company-tooltip-limit 20
  939. company-echo-delay 0
  940. company-begin-commands '(self-insert-command))
  941. (gorepl-mode)))
  942. (defun set-exec-path-from-shell-PATH ()
  943. (let ((path-from-shell (replace-regexp-in-string
  944. "[ \t\n]*$"
  945. ""
  946. (shell-command-to-string "$SHELL --login -i -c 'echo $PATH'"))))
  947. (setenv "PATH" path-from-shell)
  948. (setq eshell-path-env path-from-shell)
  949. (setq exec-path (split-string path-from-shell path-separator))))
  950. (when window-system (set-exec-path-from-shell-PATH))
  951. (setenv "GOPATH" "/Users/leviolson/go")
  952. (add-to-list 'exec-path "/Users/leviolson/go/bin")
  953. #+END_SRC
  954. *** TypeScript
  955. #+BEGIN_SRC emacs-lisp :results silent
  956. (defun setup-tide-mode ()
  957. "Tide setup function."
  958. (interactive)
  959. (tide-setup)
  960. (flycheck-mode +1)
  961. (setq flycheck-check-syntax-automatically '(save mode-enabled))
  962. (eldoc-mode +1)
  963. (tide-hl-identifier-mode +1)
  964. (company-mode +1))
  965. ;; aligns annotation to the right hand side
  966. (setq company-tooltip-align-annotations t)
  967. ;; formats the buffer before saving
  968. (add-hook 'before-save-hook 'tide-format-before-save)
  969. (add-hook 'typescript-mode-hook #'setup-tide-mode)
  970. (require 'typescript-mode)
  971. (require 'tide)
  972. (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode))
  973. (add-hook 'typescript-mode-hook
  974. '(lambda ()
  975. (set (make-local-variable 'company-backends) '(company-tide))
  976. (setq company-tooltip-limit 20
  977. company-echo-delay 0
  978. company-begin-commands '(self-insert-command)
  979. tide-format-options '(:insertSpaceAfterFunctionKeywordForAnonymousFunctions t :placeOpenBraceOnNewLineForFunctions nil))
  980. (tide-setup)))
  981. #+END_SRC
  982. **** TSX
  983. #+BEGIN_SRC emacs-lisp :results silent
  984. (require 'web-mode)
  985. (add-to-list 'auto-mode-alist '("\\.tsx\\'" . web-mode))
  986. (add-hook 'web-mode-hook
  987. (lambda ()
  988. (when (string-equal "tsx" (file-name-extension buffer-file-name))
  989. (setup-tide-mode))))
  990. ;; enable typescript-tslint checker
  991. (flycheck-add-mode 'typescript-tslint 'web-mode)
  992. #+END_SRC
  993. **** JSX
  994. #+BEGIN_SRC emacs-lisp :results silent
  995. (require 'web-mode)
  996. (add-to-list 'auto-mode-alist '("\\.jsx\\'" . web-mode))
  997. (add-hook 'web-mode-hook
  998. (lambda ()
  999. (when (string-equal "jsx" (file-name-extension buffer-file-name))
  1000. (setup-tide-mode))))
  1001. ;; configure jsx-tide checker to run after your default jsx checker
  1002. (flycheck-add-mode 'javascript-eslint 'web-mode)
  1003. (flycheck-add-next-checker 'javascript-eslint 'jsx-tide 'append)
  1004. #+END_SRC
  1005. *** Org
  1006. #+BEGIN_SRC emacs-lisp :results silent
  1007. (org-babel-do-load-languages
  1008. 'org-babel-load-languages
  1009. '((js . t)
  1010. (shell . t)
  1011. (emacs-lisp . t)))
  1012. (setq org-todo-keywords
  1013. '((sequence "TODO(t)" "|" "DONE(d)")
  1014. (sequence "BUG(b)" "|" "INPROGRESS(i)" "FIXED(f)")
  1015. (sequence "|" "CANCELED(c)")
  1016. (sequence "|" "NEEDCLARIFICATION(n)")
  1017. (sequence "|" "PROVIDEUPDATE(p)")
  1018. (sequence "|" "WAITING(w)")
  1019. ))
  1020. (setq org-agenda-files
  1021. '("~/Dropbox/Org/todo.org" "~/Dropbox/Org/archive.org"))
  1022. (setq org-refile-targets
  1023. '((nil :maxlevel . 1)
  1024. (org-agenda-files :maxlevel . 1)))
  1025. (add-hook 'focus-in-hook
  1026. (lambda () (progn
  1027. (setq org-tags-column (- 5 (frame-width)))) (org-align-all-tags)))
  1028. (add-hook 'focus-out-hook
  1029. (lambda () (progn
  1030. (setq org-tags-column (- 5 (frame-width)))) (org-align-all-tags)))
  1031. (defvar org-src-tab-acts-natively)
  1032. (setq org-src-tab-acts-natively t)
  1033. ;; (setenv "NODE_PATH"
  1034. ;; (getenv "NODE_PATH"))
  1035. (defvar org-confirm-babel-evaluate)
  1036. (defun my-org-confirm-babel-evaluate (lang _body)
  1037. "Execute certain languages without confirming.
  1038. Takes LANG to allow and BODY to execute."
  1039. (not (or (string= lang "js")
  1040. (string= lang "restclient")
  1041. (string= lang "emacs-lisp")
  1042. (string= lang "shell"))))
  1043. (setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate)
  1044. (add-to-list 'org-structure-template-alist
  1045. (list "e" (concat "#+BEGIN_SRC emacs-lisp :results silent\n"
  1046. "\n"
  1047. "#+END_SRC")))
  1048. (add-to-list 'org-structure-template-alist
  1049. (list "j" (concat "#+BEGIN_SRC js :cmd \"babel-node\"\n"
  1050. "\n"
  1051. "#+END_SRC")))
  1052. (add-to-list 'org-structure-template-alist
  1053. (list "r" (concat "#+BEGIN_SRC restclient :results raw\n"
  1054. "\n"
  1055. "#+END_SRC")))
  1056. #+END_SRC
  1057. **** Mu4e
  1058. #+BEGIN_SRC emacs-lisp :results silent
  1059. ;;store org-mode links to messages
  1060. (require 'org-mu4e)
  1061. ;;store link to message if in header view, not to header query
  1062. (setq org-mu4e-link-query-in-headers-mode nil)
  1063. (setq org-capture-templates
  1064. '(("t" "todo" entry (file+headline "~/todo.org" "Tasks")
  1065. "* TODO [#A] %?\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n%a\n")))
  1066. #+END_SRC
  1067. **** ElFeed
  1068. #+BEGIN_SRC emacs-lisp :results silent
  1069. (elfeed-org)
  1070. (setq rmh-elfeed-org-files (list "~/Dropbox/Org/elfeed.org"))
  1071. (defun leo/elfeed-search (arg)
  1072. "Search for ARG in feed."
  1073. (interactive)
  1074. (elfeed-search-set-filter arg))
  1075. (define-key elfeed-search-mode-map "a" (lambda () (interactive) (leo/elfeed-search "")))
  1076. (define-key elfeed-search-mode-map "e" (lambda () (interactive) (leo/elfeed-search "+emacs")))
  1077. (define-key elfeed-search-mode-map "d" (lambda () (interactive) (leo/elfeed-search "+daily")))
  1078. (define-key elfeed-search-mode-map "x" (lambda () (interactive) (leo/elfeed-search "xkcd")))
  1079. #+End_SRC
  1080. ** Functions
  1081. #+BEGIN_SRC emacs-lisp :results silent
  1082. (defun find-user-init-file ()
  1083. "Edit the `~/.emacs.d/init.org' file."
  1084. (interactive)
  1085. (find-file "~/.emacs.d/init.org"))
  1086. (defun find-todo-file ()
  1087. "Edit the `~/todo.org' file."
  1088. (interactive)
  1089. (find-file "~/Dropbox/Org/todo.org"))
  1090. (defun load-user-init-file ()
  1091. "LO: Reload the `~/.emacs.d/init.elc' file."
  1092. (interactive)
  1093. (load-file "~/.emacs.d/init.elc"))
  1094. (defun jump-to-symbol-internal (&optional backwardp)
  1095. "Jumps to the next symbol near the point if such a symbol exists. If BACKWARDP is non-nil it jumps backward."
  1096. (let* ((point (point))
  1097. (bounds (find-tag-default-bounds))
  1098. (beg (car bounds)) (end (cdr bounds))
  1099. (str (isearch-symbol-regexp (find-tag-default)))
  1100. (search (if backwardp 'search-backward-regexp
  1101. 'search-forward-regexp)))
  1102. (goto-char (if backwardp beg end))
  1103. (funcall search str nil t)
  1104. (cond ((<= beg (point) end) (goto-char point))
  1105. (backwardp (forward-char (- point beg)))
  1106. (t (backward-char (- end point))))))
  1107. (defun jump-to-previous-like-this ()
  1108. "Jumps to the previous occurrence of the symbol at point."
  1109. (interactive)
  1110. (jump-to-symbol-internal t))
  1111. (defun jump-to-next-like-this ()
  1112. "Jumps to the next occurrence of the symbol at point."
  1113. (interactive)
  1114. (jump-to-symbol-internal))
  1115. (defun match-paren (arg)
  1116. "Go to the matching paren if on a paren; otherwise insert ARG (a literal % sign)."
  1117. (interactive "p")
  1118. (cond ((looking-at "\\s(") (forward-list 1))
  1119. ((looking-back "\\s(" 2) (backward-char 1) (forward-list 1))
  1120. ((looking-at "\\s)") (forward-char 1) (backward-list 1))
  1121. ((looking-back "\\s)" 2) (backward-list 1))
  1122. (t (self-insert-command (or arg 1)))))
  1123. (defun kill-this-buffer-unless-scratch ()
  1124. "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."
  1125. (interactive)
  1126. (if (not (string= (buffer-name) "*scratch*"))
  1127. (kill-this-buffer)
  1128. (delete-region (point-min) (point-max))
  1129. (switch-to-buffer (other-buffer))
  1130. (bury-buffer "*scratch*")))
  1131. (defun delete-backward-sentence ()
  1132. "LO: Delete to the beginning of the sentence/line."
  1133. (interactive)
  1134. (delete-region (point) (progn (backward-sentence) (point))))
  1135. (defun delete-backward-to-boundary (arg)
  1136. "LO: Delete backward to the previous word boundary. With ARG, do this many times."
  1137. (interactive "p")
  1138. (let ((a (point))
  1139. (b (progn
  1140. (backward-word arg)
  1141. (forward-word)
  1142. (point))))
  1143. (if (< a b)
  1144. (delete-region a (progn (backward-word arg) (point)))
  1145. (if (= a b)
  1146. (delete-region a (progn (backward-word arg) (point)))
  1147. (delete-region a b)))))
  1148. (defun comment-or-uncomment-region-or-line ()
  1149. "Comments or uncomments the region or the current line if there's no active region."
  1150. (interactive)
  1151. (let (beg end)
  1152. (if (region-active-p)
  1153. (setq beg (region-beginning) end (region-end))
  1154. (setq beg (line-beginning-position) end (line-end-position)))
  1155. (comment-or-uncomment-region beg end)))
  1156. (defun fold-toggle (column)
  1157. "Code folding by COLUMN."
  1158. (interactive "P")
  1159. (set-selective-display
  1160. (or column
  1161. (unless selective-display
  1162. (1+ (current-column))))))
  1163. (defun new-line-below ()
  1164. "LO: Create a new line below current line."
  1165. (interactive)
  1166. (move-end-of-line 1)
  1167. (newline-and-indent))
  1168. (defun new-line-above ()
  1169. "LO: Create a new line above current line."
  1170. (interactive)
  1171. (move-beginning-of-line 1)
  1172. (newline)
  1173. (forward-line -1))
  1174. (defun duplicate-thing (comment)
  1175. "LO: Duplicates the current line, or the region if active. If an argument (COMMENT) is given, the duplicated region will be commented out."
  1176. (interactive "P")
  1177. (save-excursion
  1178. (let ((start (if (region-active-p) (region-beginning) (point-at-bol)))
  1179. (end (if (region-active-p) (region-end) (point-at-eol))))
  1180. (goto-char end)
  1181. (unless (region-active-p)
  1182. (newline))
  1183. (insert (buffer-substring start end))
  1184. (when comment (comment-region start end)))))
  1185. (defun tidy ()
  1186. "LO: Ident, untabify and unwhitespacify current buffer, or region if active."
  1187. (interactive)
  1188. (let ((beg (if (region-active-p) (region-beginning) (point-min)))
  1189. (end (if (region-active-p) (region-end) (point-max))))
  1190. (let ((inhibit-message t))
  1191. (indent-region beg end))
  1192. (whitespace-cleanup)
  1193. (untabify beg (if (< end (point-max)) end (point-max)))
  1194. (if (region-active-p) (message "Indenting Region...Done") (message "Indenting File...Done"))))
  1195. (defun phil-columns ()
  1196. "LO: Good 'ol Phil-Columns."
  1197. (interactive)
  1198. (message "Good 'ol fill-columns")
  1199. (with-output-to-temp-buffer "*PHIL-COLUMN*"
  1200. (shell-command "mpv --no-video 'https://www.youtube.com/watch?v=YkADj0TPrJA&t=3m16s' > /dev/null 2>&1 & sleep 8; pkill mpv"))
  1201. (other-window 1)
  1202. (delete-window))
  1203. (declare-function first "Goto FIRST shell.")
  1204. (declare-function goto-non-shell-buffer "Goto something other than a shell buffer.")
  1205. (declare-function switch-shell "Switch shell.")
  1206. (let ((last-shell ""))
  1207. (defun toggle-shell ()
  1208. (interactive)
  1209. (cond ((string-match-p "^\\*shell<[1-9][0-9]*>\\*$" (buffer-name))
  1210. (goto-non-shell-buffer))
  1211. ((get-buffer last-shell) (switch-to-buffer last-shell))
  1212. (t (shell (setq last-shell "*shell<1>*")))))
  1213. (defun switch-shell (n)
  1214. (let ((buffer-name (format "*shell<%d>*" n)))
  1215. (setq last-shell buffer-name)
  1216. (cond ((get-buffer buffer-name)
  1217. (switch-to-buffer buffer-name))
  1218. (t (shell buffer-name)
  1219. (rename-buffer buffer-name)))))
  1220. (defun goto-non-shell-buffer ()
  1221. (let* ((r "^\\*shell<[1-9][0-9]*>\\*$")
  1222. (shell-buffer-p (lambda (b) (string-match-p r (buffer-name b))))
  1223. (non-shells (cl-remove-if shell-buffer-p (buffer-list))))
  1224. (when non-shells
  1225. (switch-to-buffer (first non-shells))))))
  1226. (defadvice shell (after kill-with-no-query nil activate)
  1227. "."
  1228. (set-process-query-on-exit-flag (get-buffer-process ad-return-value) nil))
  1229. (declare-function comint-truncate-buffer ".")
  1230. (defun clear-comint ()
  1231. "Run `comint-truncate-buffer' with the `comint-buffer-maximum-size' set to zero."
  1232. (interactive)
  1233. (let ((comint-buffer-maximum-size 0))
  1234. (comint-truncate-buffer)))
  1235. (defun c-setup ()
  1236. "Compile."
  1237. (local-set-key (kbd "C-c C-c") 'compile))
  1238. #+END_SRC
  1239. ** Bindings
  1240. #+begin_src emacs-lisp :results silent
  1241. (require 'company)
  1242. (add-hook 'comint-mode-hook (lambda () (local-set-key (kbd "c-l") 'clear-comint)))
  1243. (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
  1244. (add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
  1245. (add-hook 'c-mode-common-hook 'c-setup)
  1246. (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
  1247. (defvar company-active-map (make-keymap)
  1248. "company mode keymap.")
  1249. (defvar custom-bindings (make-keymap)
  1250. "a keymap of custom bindings.")
  1251. (define-key custom-bindings (kbd "M-p") 'jump-to-previous-like-this)
  1252. (define-key custom-bindings (kbd "M-n") 'jump-to-next-like-this)
  1253. (define-key custom-bindings (kbd "M-<tab>") 'switch-to-next-buffer)
  1254. (define-key custom-bindings (kbd "M-<backspace>")'delete-backward-to-boundary)
  1255. (define-key custom-bindings (kbd "C-<backspace>")'delete-backward-to-boundary)
  1256. (define-key custom-bindings (kbd "C-}") 'mc/mark-next-like-this)
  1257. (define-key custom-bindings (kbd "C-)") 'mc/unmark-next-like-this)
  1258. (define-key custom-bindings (kbd "C-{") 'mc/mark-previous-like-this)
  1259. (define-key custom-bindings (kbd "C-(") 'mc/unmark-previous-like-this)
  1260. (define-key custom-bindings (kbd "C-'") 'mc-hide-unmatched-lines-mode)
  1261. (define-key custom-bindings (kbd "C-c 1") 'mc/insert-numbers)
  1262. (define-key custom-bindings (kbd "C-c s") 'mc/sort-regions)
  1263. (define-key custom-bindings "%" 'match-paren)
  1264. (define-key custom-bindings (kbd "C-x .") 'dash-at-point)
  1265. (define-key custom-bindings (kbd "C-x ,") 'dash-at-point-with-docset)
  1266. (define-key custom-bindings (kbd "C-s") (lambda () (interactive) (swiper (format "%s" (thing-at-point 'symbol)))))
  1267. (define-key custom-bindings (kbd "C-x C-l m") 'mu4e)
  1268. (define-key custom-bindings (kbd "C-x C-o t") 'find-todo-file)
  1269. (define-key custom-bindings (kbd "C-x C-l j") 'jabber)
  1270. (define-key custom-bindings (kbd "C-x C-l f") 'elfeed)
  1271. (define-key custom-bindings (kbd "C-x C-l a") 'org-agenda)
  1272. (define-key custom-bindings (kbd "M-SPC") #'hyperspace)
  1273. ;; (dolist (n (number-sequence 1 9))
  1274. ;; (global-set-key (kbd (concat "M-" (int-to-string n)))
  1275. ;; (lambda () (interactive) (switch-shell n))))
  1276. (define-key company-active-map (kbd "C-d") 'company-show-doc-buffer)
  1277. (define-key company-active-map (kbd "C-n") 'company-select-next)
  1278. (define-key company-active-map (kbd "C-p") 'company-select-previous)
  1279. (define-key company-active-map (kbd "<tab>") 'company-complete)
  1280. (define-key custom-bindings (kbd "C-c p") 'counsel-projectile-switch-project)
  1281. (define-key custom-bindings (kbd "C-c f") 'counsel-projectile-find-file)
  1282. (define-key custom-bindings (kbd "C-c m") 'magit-status)
  1283. (define-key custom-bindings (kbd "C-c D") 'define-word-at-point)
  1284. (define-key custom-bindings (kbd "C-@") 'er/expand-region)
  1285. (define-key custom-bindings (kbd "C-#") 'er/contract-region)
  1286. (define-key custom-bindings (kbd "C-S-c C-S-c") 'mc/edit-lines)
  1287. (define-key custom-bindings (kbd "C-c b") 'ivy-switch-buffer)
  1288. (define-key custom-bindings (kbd "C-c l") 'org-store-link)
  1289. (define-key custom-bindings (kbd "C-c t") 'org-set-tags)
  1290. (define-key custom-bindings (kbd "M-u") 'upcase-dwim)
  1291. (define-key custom-bindings (kbd "M-c") 'capitalize-dwim)
  1292. (define-key custom-bindings (kbd "M-l") 'downcase-dwim)
  1293. (define-key custom-bindings (kbd "M-o") 'other-window)
  1294. (define-key custom-bindings (kbd "C-c s") 'ispell-word)
  1295. (define-key custom-bindings (kbd "C-c C-d") 'org-capture)
  1296. (define-key custom-bindings (kbd "C-c <up>") 'windmove-up)
  1297. (define-key custom-bindings (kbd "C-c <down>") 'windmove-down)
  1298. (define-key custom-bindings (kbd "C-c <left>") 'windmove-left)
  1299. (define-key custom-bindings (kbd "C-c <right>") 'windmove-right)
  1300. (define-key custom-bindings (kbd "C-c a") (lambda () (interactive) (org-agenda nil "n")))
  1301. (define-key custom-bindings (kbd "C-c e") 'find-user-init-file)
  1302. (define-key custom-bindings (kbd "C-x f") 'phil-columns)
  1303. (define-key custom-bindings (kbd "C-x k") 'kill-this-buffer-unless-scratch)
  1304. (define-key custom-bindings (kbd "C-c d") 'duplicate-thing)
  1305. (define-key custom-bindings (kbd "C-c c") 'comment-or-uncomment-region-or-line)
  1306. (define-key custom-bindings (kbd "C-;") 'comment-or-uncomment-region-or-line)
  1307. (define-key custom-bindings (kbd "C-o") 'new-line-below)
  1308. (define-key custom-bindings (kbd "C-S-o") 'new-line-above)
  1309. (define-key custom-bindings (kbd "<C-tab>") 'tidy)
  1310. (define-key custom-bindings (kbd "M-q") 'kill-this-buffer)
  1311. (define-key custom-bindings (kbd "M-RET") '(lambda () (interactive) (term (getenv "SHELL"))))
  1312. (define-minor-mode custom-bindings-mode
  1313. "A mode that activates custom-bindings."
  1314. t nil custom-bindings)
  1315. #+END_SRC
  1316. ** UI
  1317. #+BEGIN_SRC emacs-lisp :results silent
  1318. (cond ((member "PragmataPro" (font-family-list))
  1319. (set-face-attribute 'default nil :font "PragmataPro-14")))
  1320. #+END_SRC
  1321. *** Doom Modeline
  1322. #+BEGIN_SRC emacs-lisp :results silent
  1323. (require 'doom-modeline)
  1324. (doom-modeline-mode 1)
  1325. ;; How tall the mode-line should be (only respected in GUI Emacs).
  1326. (setq doom-modeline-height 30)
  1327. ;; How wide the mode-line bar should be (only respected in GUI Emacs).
  1328. (setq doom-modeline-bar-width 4)
  1329. ;; Determines the style used by `doom-modeline-buffer-file-name'.
  1330. ;;
  1331. ;; Given ~/Projects/FOSS/emacs/lisp/comint.el
  1332. ;; truncate-upto-project => ~/P/F/emacs/lisp/comint.el
  1333. ;; truncate-from-project => ~/Projects/FOSS/emacs/l/comint.el
  1334. ;; truncate-with-project => emacs/l/comint.el
  1335. ;; truncate-except-project => ~/P/F/emacs/l/comint.el
  1336. ;; truncate-upto-root => ~/P/F/e/lisp/comint.el
  1337. ;; truncate-all => ~/P/F/e/l/comint.el
  1338. ;; relative-from-project => emacs/lisp/comint.el
  1339. ;; relative-to-project => lisp/comint.el
  1340. ;; file-name => comint.el
  1341. ;; buffer-name => comint.el<2> (uniquify buffer name)
  1342. ;;
  1343. ;; If you are expereicing the laggy issue, especially while editing remote files
  1344. ;; with tramp, please try `file-name' style.
  1345. ;; Please refer to https://github.com/bbatsov/projectile/issues/657.
  1346. (setq doom-modeline-buffer-file-name-style 'truncate-upto-project)
  1347. ;; What executable of Python will be used (if nil nothing will be showed).
  1348. (setq doom-modeline-python-executable "python")
  1349. ;; Whether show `all-the-icons' or not (if nil nothing will be showed).
  1350. (setq doom-modeline-icon t)
  1351. ;; Whether show the icon for major mode. It respects `doom-modeline-icon'.
  1352. (setq doom-modeline-major-mode-icon t)
  1353. ;; Display color icons for `major-mode'. It respects `all-the-icons-color-icons'.
  1354. (setq doom-modeline-major-mode-color-icon nil)
  1355. ;; Whether display minor modes or not. Non-nil to display in mode-line.
  1356. (setq doom-modeline-minor-modes nil)
  1357. ;; If non-nil, a word count will be added to the selection-info modeline segment.
  1358. (setq doom-modeline-enable-word-count nil)
  1359. ;; If non-nil, only display one number for checker information if applicable.
  1360. (setq doom-modeline-checker-simple-format t)
  1361. ;; Whether display perspective name or not. Non-nil to display in mode-line.
  1362. (setq doom-modeline-persp-name t)
  1363. ;; Whether display `lsp' state or not. Non-nil to display in mode-line.
  1364. (setq doom-modeline-lsp t)
  1365. ;; Whether display github notifications or not. Requires `ghub` package.
  1366. (setq doom-modeline-github nil)
  1367. ;; The interval of checking github.
  1368. (setq doom-modeline-github-interval (* 30 60))
  1369. ;; Whether display environment version or not.
  1370. (setq doom-modeline-env-version t)
  1371. ;; Whether display mu4e notifications or not. Requires `mu4e-alert' package.
  1372. (setq doom-modeline-mu4e t)
  1373. #+END_SRC