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.

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