I showed you my source code, pls respond
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.

660 lines
18 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #+TITLE: Dotfiles
  2. #+AUTHOR: Christopher James Hayward
  3. #+EMAIL: chris@chrishayward.xyz
  4. Immutable GNU Emacs dotfiles, inspired by Doom, built for Liberty.
  5. + 100% Literate
  6. + 100% Immutable
  7. + 100% Reproducible
  8. * Configuration
  9. :PROPERTIES:
  10. :header-args: :tangle init.el :results silent
  11. :END:
  12. Define a function to build literate programming projects.
  13. #+begin_src emacs-lisp
  14. (defun dotfiles/tangle (dir)
  15. "Recursively tangle the Org files within a directory."
  16. (let ((org-files (directory-files-recursively dir "org")))
  17. (dolist (f org-files)
  18. (org-babel-tangle-file f))))
  19. #+end_src
  20. Configure the system font with a single ~font-family~ and define the size, of which variations to the font size are relative to this value.
  21. #+begin_src emacs-lisp
  22. (defvar dotfiles/font "Fira Code")
  23. (defvar dotfiles/font-size 96)
  24. #+end_src
  25. Functionality like =completion= and =hints= can be delayed to avoid popups for common manuevers. Adjust this value to your personal taste.
  26. #+begin_src emacs-lisp
  27. (defvar dotfiles/idle 0.0)
  28. #+end_src
  29. Avoid the infamous *Emacs pinky* by binding =SPC= as a leader key, utilizing the thumb instead of the weaker pinky finger. You may change this value if you want to use something else.
  30. #+begin_src emacs-lisp
  31. (defvar dotfiles/leader-key "SPC")
  32. #+end_src
  33. Stored source projects are in ~~/.local/source/~.
  34. #+begin_src emacs-lisp
  35. (defvar dotfiles/src "~/.local/source/")
  36. (defvar dotfiles/brain (concat dotfiles/src "brain"))
  37. #+end_src
  38. Emacs creates a lot of files relative to ~user-emacs-directory~, these files are not part of this immutable configuration and do not belong in the emacs directory. To solve this issue, and to retain hermetic evaluation of the Emacs directory, we it to ~~/.cache/emacs~ shortly after initialization, before most packages are loaded.
  39. #+begin_src emacs-lisp
  40. (defvar dotfiles/home user-emacs-directory)
  41. (defvar dotfiles/cache "~/.cache/emacs")
  42. (setq create-lockfiles nil
  43. make-backup-files nil
  44. user-emacs-directory dotfiles/cache)
  45. #+end_src
  46. ** Packages
  47. https://github.com/raxod502/straight.el
  48. + Use the development branch
  49. + Integrate with ~use-package~
  50. Apply the configurations prior to bootstrapping the package manager, by setting (writing) to the variables that =straight= will ultimately read from.
  51. #+begin_src emacs-lisp
  52. (setq straight-repository-branch "develop"
  53. straight-use-package-by-default t)
  54. #+end_src
  55. Bootstrap the package manager, downloading, installing, or configuring depending on the state of the configuration. All packages are downloaded and built from source, and can be pinned to specific git commit hashes.
  56. #+begin_src emacs-lisp
  57. (defvar bootstrap-version)
  58. (let ((bootstrap-file
  59. (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
  60. (bootstrap-version 5))
  61. (unless (file-exists-p bootstrap-file)
  62. (with-current-buffer
  63. (url-retrieve-synchronously
  64. "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
  65. 'silent 'inhibit-cookies)
  66. (goto-char (point-max))
  67. (eval-print-last-sexp)))
  68. (load bootstrap-file nil 'nomessage))
  69. #+end_src
  70. Complete the integration with ~use-package~ by installing it with =straight=.
  71. #+begin_src emacs-lisp
  72. (straight-use-package 'use-package)
  73. #+end_src
  74. ** Cleanup
  75. Despite having our *stateful* and *immutable* configurations seperate, it's good practice to make efforts to reduce the trash created by Emacs.
  76. https://github.com/emacscollective/no-littering
  77. + Reduce the files created by Emacs
  78. #+begin_src emacs-lisp
  79. (use-package no-littering)
  80. #+end_src
  81. Emacs' default user interface is horrendous, but with less than 10 lines of code we can change that.
  82. #+begin_src emacs-lisp
  83. (setq inhibit-startup-message t)
  84. (global-prettify-symbols-mode)
  85. (scroll-bar-mode -1)
  86. (menu-bar-mode -1)
  87. (tool-bar-mode -1)
  88. (tooltip-mode -1)
  89. #+end_src
  90. Write out to all *3* of Emacs' default font faces.
  91. #+begin_src emacs-lisp
  92. (set-face-attribute 'default nil :font dotfiles/font :height dotfiles/font-size)
  93. (set-face-attribute 'fixed-pitch nil :font dotfiles/font :height dotfiles/font-size)
  94. (set-face-attribute 'variable-pitch nil :font dotfiles/font :height dotfiles/font-size)
  95. #+end_src
  96. ** Keybindings
  97. Make the =ESC= key quit prompts, instead of the default =C-g=.
  98. #+begin_src emacs-lisp
  99. (global-set-key (kbd "<escape>") 'keyboard-escape-quit)
  100. #+end_src
  101. https://github.com/justbur/emacs-which-key
  102. + Display the currently incomplete keybinding in a mini-buffer.
  103. #+begin_src emacs-lisp
  104. (use-package which-key
  105. :diminish which-key-mode
  106. :init (which-key-mode)
  107. :config (setq which-key-idle-delay dotfiles/idle))
  108. #+end_src
  109. https://github.com/noctuid/general.el
  110. + Easily configure prefixed keybindings
  111. + Cleaner than default binding methods
  112. #+begin_src emacs-lisp
  113. (use-package general
  114. :config
  115. (general-create-definer dotfiles/leader
  116. :states '(normal motion)
  117. :keymaps 'override
  118. :prefix dotfiles/leader-key))
  119. #+end_src
  120. https://github.com/abo-abo/hydra
  121. + Transient keybindings sharing a common prefix
  122. #+begin_src emacs-lisp
  123. (use-package hydra)
  124. #+end_src
  125. *** Evil
  126. After a few hour with =vim= I knew it was game over, I cannot even think of another way I would feel comfortable editing text. Luckily, there exist packages to emulate this within Emacs.
  127. https://evil.readthedocs.io/en/latest/index.html
  128. + Extendable VI layer for Emacs
  129. + Disable default keybindings
  130. #+begin_src emacs-lisp
  131. (use-package evil
  132. :init (setq evil-want-integration t
  133. evil-want-keybinding nil)
  134. :config (evil-mode 1))
  135. #+end_src
  136. https://github.com/emacs-evil/evil-collection
  137. + Community keybindings for =evil-mode=
  138. #+begin_src emacs-lisp
  139. (use-package evil-collection
  140. :after evil
  141. :config (evil-collection-init))
  142. #+end_src
  143. https://github.com/redguardtoo/evil-nerd-commenter
  144. + Toggle comments with =M-;=
  145. #+begin_src emacs-lisp
  146. (use-package evil-nerd-commenter
  147. :bind ("M-;" . evilnc-comment-or-uncomment-lines))
  148. #+end_src
  149. *** Font
  150. Increase the font size in buffers with =SPC f=.
  151. + Increase =j=
  152. + Decrease =k=
  153. + Finish =f=
  154. #+begin_src emacs-lisp
  155. (defhydra hydra-text-scale (:timeout 4)
  156. "Scale"
  157. ("j" text-scale-increase "Increase")
  158. ("k" text-scale-decrease "Decrease")
  159. ("f" nil "Finished" :exit t))
  160. #+end_src
  161. #+begin_src emacs-lisp
  162. (dotfiles/leader
  163. "f" '(hydra-text-scale/body :which-key "Font"))
  164. #+end_src
  165. *** Shortcuts
  166. Again cherry picked from =Doom=, I want to continue utilizing the muscle memory I have developed from a year of mainlining the framework.
  167. + Find files =SPC . (period)=
  168. + Switch buffers with =SPC , (comma)=
  169. #+begin_src emacs-lisp
  170. (dotfiles/leader
  171. "," '(switch-to-buffer :which-key "Buffer")
  172. "." '(find-file :which-key "File"))
  173. #+end_src
  174. Quit emacs with =SPC q=.
  175. + Saving =q=
  176. + Without =w=
  177. #+begin_src emacs-lisp
  178. (dotfiles/leader
  179. "q" '(:ignore t :which-key "Quit")
  180. "qq" '(save-buffers-kill-emacs :which-key "Save")
  181. "qw" '(kill-emacs :which-key "Now"))
  182. #+end_src
  183. Window management with =SPC w=.
  184. + Swap with =w=
  185. + Close with =c=
  186. + Delete with =d=
  187. + Motions with =h,j,k,l=
  188. + Split with =s + <MOTION>=
  189. #+begin_src emacs-lisp
  190. (dotfiles/leader
  191. "w" '(:ignore t :which-key "Window")
  192. "ww" '(window-swap-states :which-key "Swap")
  193. "wd" '(kill-buffer-and-window :which-key "Delete")
  194. "wc" '(delete-window :which-key "Close")
  195. "wh" '(windmove-left :which-key "Left")
  196. "wj" '(windmove-down :which-key "Down")
  197. "wk" '(windmove-up :which-key "Up")
  198. "wl" '(windmove-right :which-key "Right")
  199. "ws" '(:ignore t :which-key "Split")
  200. "wsj" '(split-window-below :which-key "Down")
  201. "wsl" '(split-window-right :which-key "Right"))
  202. #+end_src
  203. ** Editor
  204. Relative line numbers are important when using =VI= emulation keys. You can prefix most commands with a *number*, allowing you to jump up / down by a line count.
  205. #+begin_example
  206. 5:
  207. 4:
  208. 3:
  209. 2:
  210. 1:
  211. 156: << CURRENT LINE >>
  212. 1:
  213. 2:
  214. 3:
  215. 4:
  216. 5:
  217. #+end_example
  218. https://github.com/emacsmirror/linum-relative
  219. + Integrate with ~display-line-numbers-mode~ for performance
  220. #+begin_src emacs-lisp
  221. (use-package linum-relative
  222. :init (setq linum-relative-backend
  223. 'display-line-numbers-mode)
  224. :config (linum-relative-global-mode))
  225. #+end_src
  226. https://github.com/Fanael/rainbow-delimiters
  227. + Colourize nested parenthesis
  228. #+begin_src emacs-lisp
  229. (use-package rainbow-delimiters
  230. :hook (prog-mode . rainbow-delimiters-mode))
  231. #+end_src
  232. ** VCS
  233. Another flagship feature of Emacs is =magit=, a complete git porcelain within Emacs.
  234. https://github.com/magit/magit
  235. #+begin_src emacs-lisp
  236. (use-package magit
  237. :custom (magit-display-buffer-function
  238. #'magit-display-buffer-same-window-except-diff-v1))
  239. #+end_src
  240. https://github.com/magit/forge
  241. + Requires ~$GITHUB_TOKEN~
  242. #+begin_src emacs-lisp
  243. (use-package forge)
  244. #+end_src
  245. Open the *status* page for the current repository with =SPC g=.
  246. #+begin_src emacs-lisp
  247. (dotfiles/leader
  248. "g" '(magit-status :which-key "Magit"))
  249. #+end_src
  250. ** Files
  251. Emacs' can feel more modern when icon-fonts are installed and prioritized. I feel that this makes navigation of folders much faster, given that file types may be quickly identified by their corresponding icons.
  252. https://github.com/domtronn/all-the-icons.el
  253. + Collects various icon fonts
  254. #+begin_src emacs-lisp
  255. (use-package all-the-icons)
  256. #+end_src
  257. https://github.com/jtbm37/all-the-icons-dired
  258. + Integration with dired
  259. #+begin_src emacs-lisp
  260. (use-package all-the-icons-dired
  261. :hook (dired-mode . all-the-icons-dired-mode))
  262. #+end_src
  263. When opening =dired=, I don't want to have to press =RET= twice to navigate to the current directory. This can be avoided with ~dired-jump~, included in the =dired-x= package shipped with =dired=.
  264. #+begin_src emacs-lisp
  265. (require 'dired-x)
  266. #+end_src
  267. Open a dired buffer with =SPC d=.
  268. #+begin_src emacs-lisp
  269. (dotfiles/leader
  270. "d" '(dired-jump :which-key "Dired"))
  271. #+end_src
  272. ** Shell
  273. While not a traditional terminal emulator, =eshell= provides me with all of the functionality I expect and require from one. Some users may be left wanting more, I would recommend they look into =vterm=.
  274. https://github.com/zwild/eshell-prompt-extras
  275. + Enable lambda shell prompt
  276. #+begin_src emacs-lisp
  277. (use-package eshell-prompt-extras
  278. :config (setq eshell-highlight-prompt nil
  279. eshell-prompt-function 'epe-theme-lambda))
  280. #+end_src
  281. Open an =eshell= buffer with =SPC e=.
  282. #+begin_src emacs-lisp
  283. (dotfiles/leader
  284. "e" '(eshell :which-key "Shell"))
  285. #+end_src
  286. ** Themes
  287. Bring Emacs' out of the eighties by cherry picking a few modules from =Doom=.
  288. https://github.com/hlissner/emacs-doom-themes
  289. + Modern colour themes
  290. #+begin_src emacs-lisp
  291. (use-package doom-themes
  292. :init (load-theme 'doom-moonlight t))
  293. #+end_src
  294. Load a theme with =SPC t=.
  295. #+begin_src emacs-lisp
  296. (dotfiles/leader
  297. "t" '(load-theme t nil :which-key "Theme"))
  298. #+end_src
  299. https://github.com/seagle0128/doom-modeline
  300. + Elegant status bar / modeline
  301. #+begin_src emacs-lisp
  302. (use-package doom-modeline
  303. :init (doom-modeline-mode 1)
  304. :custom ((doom-modeline-height 16)))
  305. #+end_src
  306. ** Writing
  307. *Organize your plain life in plain text*
  308. =Org-mode= is one of the hallmark features of Emacs, and provides the basis for my Literate Programming platform. It's essentially a markdown language with rich features for project management, scheduling, development, and writing. It's hard to convey everything within its capabilities.
  309. + https://orgmode.org
  310. + https://orgmode.org/worg/org-contrib/babel/languages/index.html
  311. + https://orgmode.org/manual/Structure-Templates.html
  312. #+begin_src emacs-lisp
  313. (use-package org
  314. :hook
  315. (org-mode . (lambda ()
  316. (org-indent-mode)
  317. (visual-line-mode 1)
  318. (variable-pitch-mode 1)))
  319. :config
  320. (setq org-ellipsis " ▾"
  321. org-log-done 'time
  322. org-log-into-drawer t
  323. org-src-preserve-indentation t)
  324. (org-babel-do-load-languages
  325. 'org-babel-load-languages
  326. '((shell . t)
  327. (python . t)
  328. (emacs-lisp . t)))
  329. (require 'org-tempo)
  330. (add-to-list 'org-structure-template-alist '("s" . "src"))
  331. (add-to-list 'org-structure-template-alist '("q" . "quote"))
  332. (add-to-list 'org-structure-template-alist '("e" . "example"))
  333. (add-to-list 'org-structure-template-alist '("sh" . "src shell"))
  334. (add-to-list 'org-structure-template-alist '("py" . "src python"))
  335. (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")))
  336. #+end_src
  337. https://github.com/integral-dw/org-superstar-mode
  338. + Make the headline stars more *super*
  339. #+begin_src emacs-lisp
  340. (use-package org-superstar
  341. :hook (org-mode . org-superstar-mode))
  342. #+end_src
  343. * Development
  344. :PROPERTIES:
  345. :header-args: :tangle init.el :results silent
  346. :END:
  347. An IDE like experience (or better) can be achieved in Emacs using two *Microsoft* open source initiatives.
  348. + https://microsoft.github.io/language-server-protocol/
  349. + https://microsoft.github.io/debug-adapter-protocol/
  350. https://emacs-lsp.github.io/lsp-mode/
  351. + Language servers for Emacs
  352. #+begin_src emacs-lisp
  353. (use-package lsp-mode
  354. :commands lsp
  355. :config
  356. (setq gc-cons-threshold 100000000
  357. lsp-completion-provider 'company-capf
  358. lsp-idle-delay dotfiles/idle))
  359. #+end_src
  360. https://emacs-lsp.github.io/lsp-ui/
  361. + UI improvements for =lsp-mode=
  362. #+begin_src emacs-lisp
  363. (use-package lsp-ui
  364. :commands lsp-ui-mode
  365. :custom (lsp-ui-doc-position 'at-point))
  366. #+end_src
  367. https://emacs-lsp.github.io/dap-mode/
  368. + Debug adapters for Emacs
  369. #+begin_src emacs-lisp
  370. (use-package dap-mode)
  371. #+end_src
  372. Text completion framework via =company= aka *Complete Anything*.
  373. http://company-mode.github.io/
  374. + Integrate with =lsp-mode=
  375. #+begin_src emacs-lisp
  376. (use-package company-lsp
  377. :commands company-lsp
  378. :custom (company-minimum-prefix-length 1))
  379. #+end_src
  380. ** Python
  381. Full *IDE* experience for Python within Emacs.
  382. + Completion, jumps via =lsp-mode=
  383. + Debugging via =dap-mode=
  384. Install the =pyls= language server.
  385. #+begin_src shell :tangle no
  386. pip install --user "python-language-server[all]"
  387. #+end_src
  388. https://www.emacswiki.org/emacs/PythonProgrammingInEmacs
  389. + Built in mode
  390. #+begin_src emacs-lisp
  391. (use-package python-mode
  392. :hook (python-mode . lsp)
  393. :config (require 'dap-python)
  394. :custom (python-shell-interpreter "python3") ;; Required if "python" is not python 3.
  395. (dap-python-executable "python3") ;; Same as above.
  396. (dap-python-debugger 'debugpy))
  397. #+end_src
  398. ** Rust
  399. Full *IDE* experience for Rust within Emacs.
  400. + Completion via =lsp-mode=
  401. + Debugging via =dap-mode=
  402. https://github.com/brotzeit/rustic
  403. + Install via ~lsp-install-server~
  404. #+begin_src emacs-lisp
  405. (use-package rustic)
  406. #+end_src
  407. * Writing
  408. :PROPERTIES:
  409. :header-args: :tangle init.el :results silent
  410. :END:
  411. https://github.com/org-roam/org-roam
  412. + Rudimentary roam replica with =org-mode=
  413. #+begin_src emacs-lisp
  414. (use-package org-roam
  415. :hook (after-init . org-roam-mode)
  416. :custom (org-roam-directory dotfiles/brain))
  417. #+end_src
  418. https://github.com/org-roam/org-roam
  419. + Visualizes the =org-roam= database
  420. + Available on http://localhost:8080
  421. #+begin_src emacs-lisp
  422. (use-package org-roam-server
  423. :hook (org-roam-mode . org-roam-server-mode))
  424. #+end_src
  425. Configure keybindings behind =SPC r=.
  426. + Find with =f=
  427. + Buffer with =b=
  428. + Capture with =c=
  429. + Dailies with =d=
  430. #+begin_src emacs-lisp
  431. (dotfiles/leader
  432. "r" '(:ignore t :which-key "Roam")
  433. "rf" '(org-roam-find-file :which-key "Find")
  434. "rb" '(org-roam-buffer-toggle-display :which-key "Buffer")
  435. "rc" '(org-roam-capture :which-key "Capture")
  436. "rd" '(:ignore t :which-key "Dailies")
  437. "rdd" '(org-roam-dailies-find-date :which-key "Date")
  438. "rdt" '(org-roam-dailies-find-today :which-key "Today")
  439. "rdm" '(org-roam-dailies-find-tomorrow :which-key "Tomorrow")
  440. "rdy" '(org-roam-dailies-find-yesterday :which-key "Yesterday"))
  441. #+end_src
  442. Configure the default capture template for new topics.
  443. #+begin_src emacs-lisp
  444. (setq org-roam-capture-templates
  445. '(("d" "Default" plain (function org-roam-capture--get-point)
  446. "%?"
  447. :file-name "${slug}"
  448. :head "#+TITLE: ${title}\n"
  449. :unnarrowed t)))
  450. #+end_src
  451. Configure the default capture template for daily entries.
  452. #+begin_src emacs-lisp
  453. (setq org-roam-dailies-capture-templates
  454. '(("d" "Default" entry (function org-roam-capture--get-point)
  455. "* %?"
  456. :file-name "daily/%<%Y-%m-%d>"
  457. :head "#+TITLE: %<%Y-%m-%d>\n")))
  458. #+end_src
  459. ** Agenda
  460. Configure agenda sources.
  461. + Dailies ~~/.local/source/brain/daily/~
  462. + Secrets ~~/.local/source/secrets/~
  463. #+begin_src emacs-lisp
  464. (setq org-agenda-files '("~/.local/source/secrets/"
  465. "~/.local/source/brain/daily/"))
  466. #+end_src
  467. Open an agenda buffer with =SPC a=.
  468. #+begin_src emacs-lisp
  469. (dotfiles/leader
  470. "a" '(org-agenda :which-key "Agenda"))
  471. #+end_src
  472. ** Blogging
  473. https://github.com/kaushalmodi/ox-hugo
  474. + Configure for =one-post-per-file=
  475. #+begin_src emacs-lisp
  476. (use-package ox-hugo
  477. :after ox)
  478. #+end_src
  479. Creaate a capture template for blog posts in the =posts= sub directory.
  480. #+begin_src emacs-lisp
  481. (add-to-list 'org-roam-capture-templates
  482. '("b" "Blogging" plain (function org-roam-capture--get-point)
  483. "%?"
  484. :file-name "posts/${slug}"
  485. :head "#+TITLE: ${title}\n#+HUGO_BASE_DIR: ../\n#+HUGO_SECTION: ./\n"))
  486. #+end_src
  487. ** Presentations
  488. Produce high quality presentations that work anywhere with =HTML/JS= via the =reveal.js= package.
  489. https://github.com/hexmode/ox-reveal
  490. + Configure to use =cdn=
  491. #+begin_src emacs-lisp
  492. (use-package ox-reveal
  493. :after ox
  494. :custom (org-reveal-root "https://cdn.jsdelivr.net/reveal.js/3.9.2/"))
  495. #+end_src
  496. Create a capture template for presentations stored in the =slides= sub directory.
  497. #+begin_src emacs-lisp
  498. (add-to-list 'org-roam-capture-templates
  499. '("p" "Presentation" plain (function org-roam-capture--get-point)
  500. "%?"
  501. :file-name "slides/${slug}"
  502. :head "#+TITLE: ${title}\n"))
  503. #+end_src