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.

803 lines
26 KiB

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