Personal emacs config
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.

657 lines
22 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. * Editing
  2. ** IEdit mode
  3. #+BEGIN_SRC emacs-lisp
  4. (use-package iedit
  5. :bind ("C-;" . iedit-mode))
  6. #+END_SRC
  7. ** Imenu
  8. #+BEGIN_SRC emacs-lisp
  9. (use-package imenu
  10. :bind
  11. ("C-S-s" . imenu))
  12. #+END_SRC
  13. ** Spellcheck
  14. #+BEGIN_SRC emacs-lisp
  15. (global-set-key (kbd "C-!") 'ispell-buffer)
  16. #+END_SRC
  17. ** Undo tree
  18. #+BEGIN_SRC emacs-lisp
  19. (use-package undo-tree
  20. :config
  21. (global-undo-tree-mode))
  22. #+END_SRC
  23. * Added functionality
  24. ** Multiline sexp with symbol
  25. Jump to symbol, go up list, lispy-multiline. Great for diff-friendly custom
  26. #+BEGIN_SRC emacs-lisp
  27. (require 'isearch)
  28. (require 'lispy)
  29. (defun rlbr/multiline-sexp-with-symbol (symbol-name)
  30. (save-excursion
  31. (beginning-of-buffer)
  32. (search-forward-regexp (isearch-symbol-regexp symbol-name))
  33. (backward-up-list)
  34. (lispy-alt-multiline)))
  35. #+END_SRC
  36. ** Output matches
  37. Run command for each matching exe and see if output-p is true when fed the command output
  38. #+BEGIN_SRC emacs-lisp
  39. (defun rlbr/output-matches (output-matches-p exe args)
  40. "locate the executable whose output satisfies output-matches-p when fed args and return the full-path"
  41. (let ((exec-path exec-path)
  42. (output)
  43. (bad)
  44. (command-output)
  45. (current-exe)
  46. (failed))
  47. (while (not (or output failed))
  48. (setq current-exe
  49. (executable-find exe))
  50. (if current-exe
  51. (progn
  52. (setq command-output
  53. (shell-command-to-string (format "%s %s" (rlbr/quote-exe current-exe)
  54. args)))
  55. (if (funcall output-matches-p command-output)
  56. (setq output current-exe)
  57. (progn
  58. (setq bad
  59. (replace-regexp-in-string "/$" "" (file-name-directory current-exe)))
  60. (setq exec-path
  61. (seq-filter (lambda (item)
  62. (not (rlbr/case-insensitive-match item bad)))
  63. exec-path)))))
  64. (setq failed t)))
  65. output))
  66. #+END_SRC
  67. ** Save buffer-output to file
  68. This handy function is a customized ripoff of custom-save-all
  69. #+BEGIN_SRC emacs-lisp
  70. (defun rlbr/save-buffer-func-to-file (visit-file func args)
  71. "Rip off of custom-save-all"
  72. (let* ((filename visit-file)
  73. (recentf-exclude (if recentf-mode (append `(,(concat "\\`" (regexp-quote (recentf-expand-file-name visit-file))
  74. "\\'")
  75. ,(concat "\\`" (regexp-quote (file-truename (recentf-expand-file-name visit-file)))
  76. "\\'"))
  77. recentf-exclude)))
  78. (old-buffer (find-buffer-visiting filename))
  79. old-buffer-name)
  80. (with-current-buffer (let ((find-file-visit-truename t))
  81. (or old-buffer (let ((delay-mode-hooks t))
  82. (find-file-noselect filename))))
  83. (when old-buffer (setq old-buffer-name (buffer-file-name))
  84. (set-visited-file-name (file-chase-links filename)))
  85. (unless (eq major-mode 'emacs-lisp-mode)
  86. (delay-mode-hooks (emacs-lisp-mode)))
  87. (let ((inhibit-read-only t)
  88. (print-length nil)
  89. (print-level nil))
  90. (apply func args))
  91. (let ((file-precious-flag t))
  92. (save-buffer))
  93. (if old-buffer (progn (set-visited-file-name old-buffer-name)
  94. (set-buffer-modified-p nil))
  95. (kill-buffer (current-buffer))))))
  96. #+END_SRC
  97. ** Low memeory check
  98. #+BEGIN_SRC emacs-lisp
  99. (defun rlbr/high-mem (&optional threshold)
  100. (let ((threshold (or threshold (expt 1024 2)))))
  101. (>= (nth 1 (memory-info))
  102. threshold))
  103. #+END_SRC
  104. ** Kill this buffer
  105. #+BEGIN_SRC emacs-lisp
  106. (defun rlbr/kill-this-buffer ()
  107. (interactive)
  108. (kill-buffer (current-buffer)))
  109. #+END_SRC
  110. * Save/load
  111. ** Backup/auto-save
  112. #+BEGIN_SRC emacs-lisp
  113. (let ((backup-dir "~/.emacs.d/backup")
  114. (auto-save-dir "~/.emacs.d/autosave"))
  115. (if (not (file-directory-p backup-dir))
  116. (make-directory backup-dir))
  117. (if (not (file-directory-p
  118. auto-save-dir))
  119. (make-directory auto-save-dir)))
  120. #+END_SRC
  121. ** On save
  122. #+BEGIN_SRC emacs-lisp
  123. (add-hook 'before-save-hook 'delete-trailing-whitespace)
  124. #+END_SRC
  125. ** Recent files mode
  126. #+BEGIN_SRC emacs-lisp
  127. (use-package recentf
  128. :config
  129. (recentf-mode 1))
  130. #+END_SRC
  131. * Platform dependent
  132. ** Windows
  133. #+BEGIN_SRC emacs-lisp
  134. (when (string-equal system-type "windows-nt")
  135. (progn (defun rlbr/quote-exe (path)
  136. (w32-short-file-name path))
  137. (defun rlbr/high-mem (&optional threshold) t)
  138. (defun rlbr/start-external-shell ()
  139. (interactive)
  140. (start-process-shell-command (format "cmd(%s)" default-directory)
  141. nil "start default.bat"))
  142. (global-set-key (kbd "C-S-C")
  143. 'rlbr/start-external-shell)
  144. (defun rlbr/start-windows-explorer-here ()
  145. (interactive)
  146. (start-process-shell-command "explorer" nil (format "explorer %s" (replace-regexp-in-string "/" (regexp-quote "\\")
  147. (expand-file-name default-directory)))))
  148. (global-set-key (kbd "C-S-E")
  149. 'rlbr/start-windows-explorer-here)
  150. (defun rlbr/case-insensitive-match (string1 string2)
  151. (apply 'string-equal (mapcar 'downcase (list string1 string2))))
  152. (let ((find)
  153. (grep)
  154. (ls))
  155. (progn (setq find (rlbr/output-matches (lambda (output)
  156. (string-equal ".\n" output))
  157. "find" "-maxdepth 0"))
  158. (if find (setq find-program (rlbr/quote-exe find)))
  159. (setq grep (rlbr/output-matches (lambda (output)
  160. (string-match "grep (\\w+ grep)" output))
  161. "grep" "-V"))
  162. (if grep (setq grep-program (rlbr/quote-exe grep)))
  163. (setq ls (rlbr/output-matches (lambda (output)
  164. (string-match "ls: .*'\\?/': No such file or directory" output))
  165. "ls" "?/"))
  166. (if ls (setq insert-directory-program (rlbr/quote-exe ls)))))))
  167. #+END_SRC
  168. * Tramp configuration
  169. ** Tramp append plist to connection properties
  170. #+BEGIN_SRC emacs-lisp
  171. (use-package kv
  172. :config
  173. (defun rlbr/add-config-to-tramp (matches-regexp config-plist)
  174. (let ((config-alist (kvplist->alist config-plist)))
  175. (dolist (pair config-alist)
  176. (let ((config (list matches-regexp (car pair)
  177. (cdr pair))))
  178. (add-to-list 'tramp-connection-properties config))))))
  179. #+END_SRC
  180. ** Android
  181. #+BEGIN_SRC emacs-lisp
  182. (use-package tramp
  183. :config
  184. (let ((android-config (let ((default-directory "/data/data/com.termux/files"))
  185. (list "tmpdir" (expand-file-name "home/temp/")
  186. "remote-shell" (expand-file-name "usr/bin/sh")
  187. "remote-process-environment" (append (list (concat "PREFIX=" default-directory "usr")) tramp-remote-process-environment)
  188. "remote-path" (append (mapcar 'expand-file-name '("home/.local/bin" "usr/bin" "usr/bin/applets")) '("/sbin" "/vendor/bin" "/system/sbin" "/system/bin" "/system/xbin"))))))
  189. (rlbr/add-config-to-tramp (rx "/" (or "scp" "ssh") (zero-or-one "x") ":" "termux" (zero-or-more any) ":") android-config)))
  190. #+END_SRC
  191. * Major modes
  192. ** C
  193. #+BEGIN_SRC emacs-lisp
  194. (use-package format-all
  195. :if (executable-find "clang-format")
  196. :hook (c-mode . format-all-mode))
  197. #+END_SRC
  198. ** Docker
  199. *** Docker
  200. *** Dockerfile
  201. *** Docker-compose
  202. #+BEGIN_SRC emacs-lisp
  203. (use-package docker-compose-mode
  204. :mode (rx "docker-compose.yml" eos)
  205. :hook
  206. (docker-compose-mode . company-mode))
  207. #+END_SRC
  208. ** Java
  209. *** Meghanada
  210. #+BEGIN_SRC emacs-lisp
  211. (use-package autodisass-java-bytecode
  212. :defer t)
  213. (use-package meghanada
  214. :if (rlbr/high-mem (* 512 1024))
  215. :defer t
  216. :init
  217. (add-hook 'java-mode-hook
  218. (lambda ()
  219. (meghanada-mode t)
  220. (flycheck-mode +1)
  221. (add-hook 'before-save-hook 'meghanada-code-beautify-before-save)))
  222. :config
  223. (setq indent-tabs-mode nil)
  224. (setq meghanada-server-remote-debug t)
  225. (setq meghanada-javac-xlint "-Xlint:all,-processing")
  226. (advice-add 'meghanada-code-beautify :around (lambda (old)
  227. (interactive)
  228. (let ((p (line-number-at-pos)))
  229. (apply old nil)
  230. (goto-line p)
  231. (reposition-window))))
  232. (defhydra hydra-meghanada (:hint nil :exit t)
  233. "
  234. ^Edit^ ^Tast or Task^
  235. ^^^^^^-------------------------------------------------------
  236. _f_: meghanada-compile-file _m_: meghanada-restart
  237. _c_: meghanada-compile-project _t_: meghanada-run-task
  238. _o_: meghanada-optimize-import _j_: meghanada-run-junit-test-case
  239. _s_: meghanada-switch-test-case _J_: meghanada-run-junit-class
  240. _v_: meghanada-local-variable _R_: meghanada-run-junit-recent
  241. _i_: meghanada-import-all _r_: meghanada-reference
  242. _g_: magit-status _T_: meghanada-typeinfo
  243. _q_: exit
  244. "
  245. ("f" meghanada-compile-file)
  246. ("m" meghanada-restart)
  247. ("c" meghanada-compile-project)
  248. ("o" meghanada-optimize-import)
  249. ("s" meghanada-switch-test-case)
  250. ("v" meghanada-local-variable)
  251. ("i" meghanada-import-all)
  252. ("g" magit-status)
  253. ("t" meghanada-run-task)
  254. ("T" meghanada-typeinfo)
  255. ("j" meghanada-run-junit-test-case)
  256. ("J" meghanada-run-junit-class)
  257. ("R" meghanada-run-junit-recent)
  258. ("r" meghanada-reference)
  259. ("q" exit)
  260. ("z" nil "leave"))
  261. :bind
  262. (:map meghanada-mode-map
  263. ("C-S-t" . meghanada-switch-testcase)
  264. ("M-RET" . meghanada-local-variable)
  265. ("M-r" . meghanada-reference)
  266. ("M-t" . meghanada-typeinfo)
  267. ("C-z" . hydra-meghanada/body))
  268. :commands
  269. (meghanada-mode))
  270. #+END_SRC
  271. ** JavaScript
  272. #+BEGIN_SRC emacs-lisp
  273. (use-package js2-mode
  274. :mode "\\.js\\'"
  275. :hook ((js2-mode . js2-imenu-extras-mode)
  276. (js2-mode . (lambda () (add-hook 'xref-backend-functions #'xref-js2-xref-backend nil t))))
  277. :config
  278. (use-package js2-refactor
  279. :hook (js2-mode . js2-refactor-mode)
  280. :bind
  281. (:map js2-mode-map
  282. ("C-k" . js2r-kill))
  283. :config
  284. (js2r-add-keybindings-with-prefix "C-c C-r"))
  285. (use-package xref-js2
  286. :demand t)
  287. (define-key js-mode-map (kbd "M-.") nil)
  288. (defun rlbr/jump-to-definition ()
  289. "Jump to a definition."
  290. (interactive)
  291. (condition-case-unless-debug nil
  292. (js2-jump-to-definition)
  293. (error
  294. (progn
  295. (ignore-errors
  296. (xref-pop-marker-stack))
  297. (xref-find-definitions (xref-backend-identifier-at-point (xref-find-backend)))))))
  298. (define-key js-mode-map (kbd "M-.") #'rlbr/jump-to-definition))
  299. #+END_SRC
  300. ** Lisp
  301. *** Emacs lisp
  302. #+BEGIN_SRC emacs-lisp
  303. (use-package elisp-mode
  304. :hook (emacs-lisp-mode . company-mode))
  305. #+END_SRC
  306. ** Magit
  307. #+BEGIN_SRC emacs-lisp
  308. (use-package magit
  309. :bind (("C-x g" . magit-status))
  310. :config
  311. (use-package git-commit
  312. :hook (git-commit-setup . git-commit-turn-on-flyspell)))
  313. #+END_SRC
  314. ** Python
  315. *** Platform specific
  316. Set python command
  317. #+BEGIN_SRC emacs-lisp
  318. (setq elpy-rpc-python-command
  319. (cond
  320. ((string-equal system-type "gnu/linux")
  321. "python3")
  322. ((string-equal system-type "windows-nt")
  323. "pythonw.exe")))
  324. #+END_SRC
  325. put executables in elpy-rpc-venv in path
  326. #+BEGIN_SRC emacs-lisp
  327. (defun rlbr/elpy-append-to-path ()
  328. (setenv "PATH" (string-join (list (getenv "PATH")
  329. (let ((default-directory (elpy-rpc-get-or-create-virtualenv))
  330. (path-entry)
  331. (elpy-binpath))
  332. (if (string-equal system-type "windows-nt")
  333. (progn (setq elpy-binpath (expand-file-name "Scripts"))
  334. (setq path-entry (replace-regexp-in-string (regexp-quote "/")
  335. (regexp-quote "\\")
  336. elpy-binpath)))
  337. (setq elpy-binpath (expand-file-name "bin"))
  338. (setq path-entry elpy-binpath))
  339. (nconc exec-path (list elpy-binpath))
  340. elpy-binpath))
  341. path-separator)))
  342. #+END_SRC
  343. #+BEGIN_SRC emacs-lisp
  344. (defun rlbr/fix-for-android ()
  345. (unless (= 0 (call-process elpy-rpc-python-command nil nil nil "-c" "import multiprocessing;multiprocessing.Pool()"))
  346. (setq python-check-command
  347. (string-join `(,python-check-command "--jobs=1") " "))))
  348. #+END_SRC
  349. *** Custom feature
  350. #+BEGIN_SRC emacs-lisp
  351. (defun rlbr/join-venv-with-number (number-name)
  352. "Join a list with a name and a number"
  353. (let
  354. ((number (car number-name))
  355. (name (cdr number-name)))
  356. (if (= number 0)
  357. name
  358. (string-join (list name (number-to-string number))
  359. "~"))))
  360. (defun rlbr/split-venv-with-number (name-number)
  361. "Split a virtualenv name with either a ~ seperating the name and the number, or nothing"
  362. (let ((split-result (split-string name-number (regexp-quote "~")))
  363. (ret))
  364. (if (= 1 (length split-result))
  365. (progn
  366. (setq ret (car split-result))
  367. (push 0 ret))
  368. (progn
  369. (setq ret
  370. (string-join
  371. (butlast split-result)
  372. "~"))
  373. (push
  374. (string-to-number
  375. (car (last split-result)))
  376. ret)))
  377. ret))
  378. (defun rlbr/get-venv-name (&optional library-root)
  379. "Generate venv name based off of the base-name of the library root"
  380. (file-name-base
  381. (directory-file-name
  382. (if library-root
  383. library-root
  384. (elpy-library-root)))))
  385. (defun rlbr/handle-name-conflicts (venv-name)
  386. "Deal with potential name conflicts in venv"
  387. (let ((venv-conflicts)
  388. (venv-partition-name))
  389. (setq venv-partition-name (rlbr/split-venv-with-number venv-name))
  390. (setq venv-conflicts
  391. (seq-filter
  392. (lambda (item)
  393. (string-equal (cdr item)
  394. venv-name))
  395. (mapcar #'rlbr/split-venv-with-number (pyvenv-virtualenv-list))))
  396. (when venv-conflicts
  397. (setcar venv-partition-name (1+ (apply 'max (mapcar #'car venv-conflicts)))))
  398. (rlbr/join-venv-with-number venv-partition-name)))
  399. (require 'vc)
  400. (defun rlbr/setup-python-venv-dirlocals (&optional library-root venv-name)
  401. "Setup .dir-locals file in library root and tell vc system to ignore .dir-locals file"
  402. (let* ((library-root (if library-root
  403. library-root
  404. (elpy-library-root)))
  405. (venv-name (if venv-name venv-name (rlbr/get-venv-name library-root)))
  406. (default-directory library-root)
  407. (dir-locals-path (expand-file-name
  408. ".dir-locals.el")))
  409. (rlbr/save-buffer-func-to-file dir-locals-path 'add-dir-local-variable
  410. `(python-mode pyvenv-workon ,venv-name))
  411. (let ((vc-root (vc-find-root dir-locals-path ".git")))
  412. (when vc-root
  413. ;; If the directory is under version control
  414. (let ((vc-ignore-file (vc-call-backend 'Git 'find-ignore-file vc-root)))
  415. (if (apply 'string-equal (mapcar 'directory-file-name (mapcar 'file-truename (list vc-root library-root))))
  416. ;; If the vc-root is the same as the library root, don't ask any questions
  417. (vc-ignore ".dir-locals.el")
  418. ;; Otherwise prompt to ignore
  419. (when (y-or-n-p (format "Ignore .dir-locals.el in repo '%s' ?" vc-root))
  420. (vc-ignore ".dir-locals.el"))))))))
  421. (defun rlbr/get-python-executable ()
  422. (read-file-name "Python interpreter to use: " (file-name-directory (executable-find "python"))
  423. nil nil "python"))
  424. (defun emacs-default-venv ()
  425. (unless (member "emacs-default-venv" (pyvenv-virtualenv-list))
  426. (pyvenv-create "emacs-default-venv" (rlbr/get-python-executable)))
  427. "emacs-default-venv")
  428. (defun rlbr/init-python-venv-in-library-root (&optional library-root)
  429. "Prompt to either create one or use default" (let ((venv-name (rlbr/get-venv-name))
  430. (library-root (if library-root library-root (elpy-library-root))))
  431. (setq venv-name (rlbr/handle-name-conflicts venv-name))
  432. (if (y-or-n-p (format "Create venv '%s'?" venv-name))
  433. (pyvenv-create venv-name (rlbr/get-python-executable))
  434. (progn
  435. (setq venv-name (emacs-default-venv))))
  436. (rlbr/setup-python-venv-dirlocals library-root venv-name)
  437. venv-name))
  438. (require 'dash)
  439. (defun rlbr/init-venv ()
  440. (when (eq major-mode 'python-mode)
  441. (cond ((file-remote-p buffer-file-name)
  442. ;; If the file is remote, don't try and do anything fancy
  443. (setq-local pyvenv-workon (emacs-default-venv)))
  444. ((let ((buffer-file-name (file-truename buffer-file-name)))
  445. ;; Don't change anything if entering a file in a python install's lib (ie for a file located with xref)
  446. (string-match-p (rx bos (or
  447. ;; Windows
  448. (and letter ":/" (one-or-more not-newline)
  449. "/Lib")
  450. ;; Rest of the sane world
  451. (and (or
  452. ;; In the home directory
  453. (and (zero-or-more not-newline)
  454. "/home/" (zero-or-more not-newline)
  455. (or
  456. ;; System python user installed package
  457. "/.local"
  458. ;; In a virtualenv
  459. (and "/.virtualenvs/" (one-or-more (not (any "/"))))
  460. ;; Elpy-rpc venv
  461. (and "/.emacs.d/elpy/rpc-venv")
  462. ;; Using Pyenv
  463. (and "/.pyenv/versions/"
  464. (one-or-more (not (any "/"))))))
  465. ;; System python
  466. (and (zero-or-more not-newline)
  467. "/usr"
  468. (opt "/local")))
  469. ;; Standard */lib/python3.7/ etc
  470. (or
  471. ;; Standard python
  472. (and "/lib/python" (one-or-more (any digit ".")))
  473. ;; PyPy
  474. (and (or "/lib-python" "/lib_pypy")))))
  475. (zero-or-more not-newline))
  476. buffer-file-name))
  477. nil)
  478. (t
  479. ;; Upon failing all conditions, prompt to create virtual environment if it doesn't exist
  480. (cond ((and pyvenv-workon (not (member pyvenv-workon (pyvenv-virtualenv-list))))
  481. ;; If there is a virtualenv specified and it doesn't exist, prompt to create it or set to default virtual environment
  482. (if (y-or-n-p (format "Venv '%s' is specified but does not exist. Create it?" pyvenv-workon))
  483. (progn (pyvenv-create pyvenv-workon (rlbr/get-python-executable))
  484. (pyvenv-workon pyvenv-workon))
  485. (rlbr/save-buffer-func-to-file (let ((default-directory (elpy-library-root)))
  486. (expand-file-name ".dir-locals.el"))
  487. 'add-dir-local-variable '(python-mode pyvenv-workon (emacs-default-venv)))
  488. (setq-local pyvenv-workon (emacs-default-venv))))
  489. ((not pyvenv-workon)
  490. ;; If nothing has already set pyvenv-workon, create venv
  491. (setq-local pyvenv-workon (rlbr/init-python-venv-in-library-root))))))
  492. (pyvenv-workon pyvenv-workon)))
  493. #+END_SRC
  494. *** Bindings/settings
  495. #+BEGIN_SRC emacs-lisp
  496. (use-package python
  497. :hook
  498. ((python-mode . pyvenv-mode)
  499. (python-mode . flycheck-mode)
  500. (python-mode . (lambda () (add-hook 'before-save-hook 'elpy-black-fix-code nil 'local))))
  501. :bind
  502. (:map python-mode-map
  503. (("C-<" . flycheck-previous-error)
  504. ("C->" . flycheck-next-error)))
  505. :config
  506. (use-package elpy
  507. :hook (hack-local-variables . rlbr/init-venv)
  508. :bind (:map python-mode-map
  509. (("C-=" . elpy-goto-assignment)))
  510. :config
  511. (when (require 'flycheck nil t)
  512. (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)))
  513. (rlbr/elpy-append-to-path)
  514. (rlbr/fix-for-android))
  515. (use-package realgud
  516. :bind (:map python-mode-map
  517. (("C-c d b" . realgud:pdb))))
  518. (elpy-enable))
  519. #+END_SRC
  520. ** SSH config mode
  521. #+BEGIN_SRC emacs-lisp
  522. (use-package ssh-config-mode
  523. :mode "~/.ssh/config\\'")
  524. #+END_SRC
  525. ** Tramp
  526. ** Webmode
  527. #+BEGIN_SRC emacs-lisp
  528. (use-package web-mode
  529. :mode
  530. (("\\.phtml\\'" . web-mode)
  531. ("\\.tpl\\.php\\'" . web-mode)
  532. ("\\.[agj]sp\\'" . web-mode)
  533. ("\\.as[cp]x\\'" . web-mode)
  534. ("\\.erb\\'" . web-mode)
  535. ("\\.mustache\\'" . web-mode)
  536. ("\\.djhtml\\'" . web-mode)
  537. ("\\.html?\\'" . web-mode)))
  538. #+END_SRC
  539. ** YAML
  540. #+BEGIN_SRC emacs-lisp
  541. (use-package yaml-mode
  542. :mode "\\.yml\\'")
  543. #+END_SRC
  544. * Minor modes/misc
  545. ** Kill the things
  546. *** Buffer
  547. #+BEGIN_SRC emacs-lisp
  548. (global-set-key (kbd "C-x k") 'rlbr/kill-this-buffer)
  549. #+END_SRC
  550. *** Emacs
  551. #+BEGIN_SRC emacs-lisp
  552. (global-set-key (kbd "C-x C-k C-x C-k") 'save-buffers-kill-emacs)
  553. #+END_SRC
  554. ** Lispy
  555. #+BEGIN_SRC emacs-lisp
  556. (use-package lispy
  557. :hook ((emacs-lisp-mode) . lispy-mode))
  558. #+END_SRC
  559. ** Custom custom
  560. #+BEGIN_SRC emacs-lisp
  561. (advice-add 'custom-save-faces :after (lambda () (rlbr/multiline-sexp-with-symbol "custom-set-faces")))
  562. (advice-add 'custom-save-variables :after (lambda () (rlbr/multiline-sexp-with-symbol "custom-set-variables")))
  563. #+END_SRC
  564. ** Elmacro
  565. #+BEGIN_SRC emacs-lisp
  566. (use-package elmacro
  567. :demand
  568. :config
  569. (elmacro-mode +1))
  570. #+END_SRC
  571. ** Better shell
  572. #+BEGIN_SRC emacs-lisp
  573. (use-package better-shell
  574. :bind
  575. (("C-M-;" . better-shell-shell)
  576. ("C-M-:" . better-shell-remote-open)
  577. ("C-#" . better-shell-sudo-here)))
  578. #+END_SRC
  579. * Navigation/auto-completion
  580. ** Ace window
  581. #+BEGIN_SRC emacs-lisp
  582. (use-package ace-window
  583. :bind (("M-Q" . ace-window)))
  584. #+END_SRC
  585. ** Hippie expand
  586. #+BEGIN_SRC emacs-lisp
  587. (use-package hippie-exp
  588. :bind ("M-/" . hippie-expand))
  589. #+END_SRC
  590. ** IBuffer mode
  591. #+BEGIN_SRC emacs-lisp
  592. (use-package ibbufer-vc
  593. :hook
  594. ((ibuffer-mode . ibuffer-vc-set-filter-groups-by-vc-root)))
  595. ;; Use human readable Size column instead of original one
  596. (use-package ibuffer :bind (("C-x C-b" . ibuffer))
  597. :bind (:map ibuffer-mode-map
  598. (("C-c t" . ibuffer-tramp-set-filter-groups-by-tramp-connection)
  599. ("C-c g" . ibuffer-vc-set-filter-groups-by-vc-root)))
  600. :config (define-ibuffer-column size-h (:name "Size" :inline t)
  601. (cond ((> (buffer-size)
  602. 1000000)
  603. (format "%7.1fM" (/ (buffer-size)
  604. 1000000.0)))
  605. ((> (buffer-size)
  606. 100000)
  607. (format "%7.0fk" (/ (buffer-size)
  608. 1000.0)))
  609. ((> (buffer-size)
  610. 1000)
  611. (format "%7.1fk" (/ (buffer-size)
  612. 1000.0)))
  613. (t (format "%8d" (buffer-size))))))
  614. #+END_SRC
  615. ** Ivy
  616. #+BEGIN_SRC emacs-lisp
  617. (use-package ivy
  618. :config
  619. (use-package swiper
  620. :bind ("C-s" . swiper))
  621. (ivy-mode))
  622. #+END_SRC
  623. * Look and feel
  624. ** Theme
  625. #+BEGIN_SRC emacs-lisp
  626. (use-package dracula-theme
  627. :config
  628. (load-theme 'dracula t))
  629. #+END_SRC
  630. ** Line numbers
  631. #+BEGIN_SRC emacs-lisp
  632. (global-display-line-numbers-mode)
  633. #+END_SRC
  634. ** Mode line bell
  635. #+BEGIN_SRC emacs-lisp
  636. (use-package mode-line-bell
  637. :config
  638. (mode-line-bell-mode))
  639. #+END_SRC
  640. ** Spaceline
  641. #+BEGIN_SRC emacs-lisp
  642. (use-package spaceline-config
  643. :config (use-package winum
  644. :bind
  645. (:map winum-keymap
  646. (("M-0" . winum-select-window-0-or-10)
  647. ("M-1" . winum-select-window-1)
  648. ("M-2" . winum-select-window-2)
  649. ("M-3" . winum-select-window-3)
  650. ("M-4" . winum-select-window-4)
  651. ("M-5" . winum-select-window-5)
  652. ("M-6" . winum-select-window-6)
  653. ("M-7" . winum-select-window-7)
  654. ("M-8" . winum-select-window-8))))
  655. (spaceline-spacemacs-theme)
  656. (winum-mode))
  657. #+END_SRC