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.

320 lines
9.8 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
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
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #+TITLE: Editor
  2. #+AUTHOR: Christopher James Hayward
  3. #+EMAIL: chris@chrishayward.xyz
  4. #+PROPERTY: header-args:emacs-lisp :tangle editor.el :comments org
  5. #+PROPERTY: header-args :results silent :eval no-export :comments org
  6. #+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil
  7. #+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
  8. Configuration and imrpovements to the editor experience within Emacs. *Vim*[fn:1] user? This module extends the keybindings by implementing *Evil*[fn:2]. *Doom*[fn:3], *Spacemacs*[fn:4]? The all powerful leader key is also implemented right here!
  9. * Keybindings
  10. Offer =ESC= as an alternative to quit (most) prompts, instead of the default =C-g=.
  11. #+begin_src emacs-lisp
  12. (global-set-key (kbd "<escape>") 'keyboard-escape-quit)
  13. #+end_src
  14. ** Completions
  15. Emacs has *a lot of keybindings*, sometimes it's useful to just start mashing keys and see what happens. This behaviour exists in a third-party package called *which-key*[fn:5]. It displays the current incomplete keybinding input in a mini-buffer, showing available completion options with their corresponding keybindings.
  16. #+begin_src emacs-lisp
  17. (use-package which-key
  18. :diminish which-key-mode
  19. :custom (which-key-idle-delay dotfiles/idle)
  20. :config (which-key-mode))
  21. #+end_src
  22. ** Turn Emacs into Vim
  23. Emacs has *some strange default keybindings*, they're not like any other editor you've likely ever used. To overcome this nearly show-stopping hurdle, we turn Emacs into Vim[fn:1] with *Evil Mode - The Extensible VI Layer for Emacs*[fn:2].
  24. #+begin_src emacs-lisp
  25. (use-package evil
  26. :custom (evil-want-integration t) ;; Required for `evil-collection'.
  27. (evil-want-keybinding nil) ;; Same as above
  28. :config (evil-mode +1))
  29. #+end_src
  30. While covering substantial ground towards our goal, the default keybindings implemented in *Evil*[fn:2] alone are *lacking* compared to what you would expect from *Vim*[fn:1]. There's, of course, a communicated curated package *evil-collection*[fn:6] that does a much better job implementing the proper keybindings.
  31. #+begin_src emacs-lisp
  32. (use-package evil-collection
  33. :after evil
  34. :config (evil-collection-init))
  35. #+end_src
  36. *** Surround text
  37. Whether it's on purpose, or more likely, you forgot an opening brace; *evil-surround*[fn:7] surrounds highlighted blocks of text with functions, quotations, and any symbol you can input.
  38. #+begin_src emacs-lisp
  39. (use-package evil-surround
  40. :after evil
  41. :config (global-evil-surround-mode 1))
  42. #+end_src
  43. *** Toggle comments
  44. When you're in deep with errors, or just trying some new code, it's useful to be able to toggle large comment sections in a language agnostic manner. In comes *evil-nerd-commentor*[fn:8], with a custom binding to =M-;=. What is =M-= ? Typically that refers to the =Alt= key, called the =Meta= key in Emacs.
  45. #+begin_src emacs-lisp
  46. (use-package evil-nerd-commenter
  47. :after evil
  48. :bind ("M-;" . evilnc-comment-or-uncomment-lines))
  49. #+end_src
  50. ** Implementing the leader key
  51. If you're like me and started with Emacs using a framework like *Doom*[fn:3] or *Spacemacs*[fn:4], you probably have a lot of muscle memory for using =SPC= as a leader key. This behaviour is actually not difficult to implement, especially when using *general.el*[fn:9].
  52. + =SPC= in most situations as a prefix key
  53. + =C-SPC= when using the [[file:desktop.org][Desktop]] module within an =X= buffer
  54. #+begin_src emacs-lisp
  55. (use-package general
  56. :after evil
  57. :config
  58. (general-create-definer dotfiles/leader
  59. :states '(normal motion)
  60. :keymaps 'override
  61. :prefix dotfiles/leader-key
  62. :global-prefix dotfiles/leader-key-global))
  63. #+end_src
  64. ** Transient bindings
  65. Create transient keybindings with a shared prefix through *Hydra*[fn:10]. This is also used by a number of third-party packages as a completion system. An implementation example is available in the *Font* section of the [[file:interface.org][Interface]] module.
  66. + Defer loading for performance
  67. #+begin_src emacs-lisp
  68. (use-package hydra
  69. :defer t)
  70. #+end_src
  71. Place runtime tweaks behind =SPC t=
  72. #+begin_src emacs-lisp
  73. (dotfiles/leader
  74. "t" '(:ignore t :which-key "Tweaks"))
  75. #+end_src
  76. ** Cherry picked shortcuts
  77. Implement shortcut bindings, cherry picked from *Doom*[fn:3].
  78. + Close buffers with =SPC c=
  79. + Find files with =SPC , (comma)=
  80. #+begin_src emacs-lisp
  81. (dotfiles/leader
  82. "." '(find-file :which-key "Files")
  83. "c" '(kill-buffer-and-window :which-key "Close"))
  84. #+end_src
  85. *** Managing windows
  86. Window management with =SPC w=
  87. + Swap with =w=
  88. + Close with =c=
  89. + Move with =h,j,k,l=
  90. + Split with =s - <motion>=
  91. #+begin_src emacs-lisp
  92. (dotfiles/leader
  93. "w" '(:ignore t :which-key "Window")
  94. "ww" '(window-swap-states :which-key "Swap")
  95. "wc" '(delete-window :which-key "Close")
  96. "wh" '(windmove-left :which-key "Left")
  97. "wj" '(windmove-down :which-key "Down")
  98. "wk" '(windmove-up :which-key "Up")
  99. "wl" '(windmove-right :which-key "Right")
  100. "ws" '(:ignore t :which-key "Split")
  101. "wsj" '(split-window-below :which-key "Down")
  102. "wsl" '(split-window-right :which-key "Right"))
  103. #+end_src
  104. *** Quitting Emacs
  105. Quit Emacs with =SPC q=
  106. + Save and quit =q=
  107. + Quit without saving =w=
  108. + Exit the Frame (daemon) =f=
  109. #+begin_src emacs-lisp
  110. (dotfiles/leader
  111. "q" '(:ignore t :which-key "Quit")
  112. "qq" '(save-buffers-kill-emacs :which-key "Save")
  113. "qw" '(kill-emacs :which-key "Now")
  114. "qf" '(delete-frame :which-key "Frame"))
  115. #+end_src
  116. * Helper functions
  117. Use the built-in ~describe-*~ functionality of Emacs to quickly access documentation for packages, variables, and functions.
  118. + Run helper functions with =SPC h=
  119. * Packages =p=
  120. * Variables =v=
  121. * Functions =f=
  122. #+begin_src emacs-lisp
  123. (dotfiles/leader
  124. "h" '(:ignore t :which-key "Help")
  125. "hp" '(describe-package :which-key "Package")
  126. "hv" '(describe-variable :which-key "Variable")
  127. "hf" '(describe-function :which-key "Function"))
  128. #+end_src
  129. * File navigation
  130. Emacs has some really cool built-in packages, *Dired*[fn:11] is one of them. It's not perfect out of the box though, there's work to do.
  131. ** Navigating to the current directory
  132. I don't want to have to press =RET= twice to navigate to the current directory. Avoid this behaviour with ~jump~, included in the =dired-x= package that ships with *Dired*[fn:11].
  133. + Open a new dired buffer with =SPC d=.
  134. #+begin_src emacs-lisp
  135. (require 'dired-x)
  136. (dotfiles/leader
  137. "d" '(dired-jump :which-key "Dired"))
  138. #+end_src
  139. ** Reusing the same buffer
  140. By default *Dired*[fn:11] will create a new buffer every time you press =RET= over a directory. This leads to unwanted buffers all over the place. Avoid this behaviour with *Dired Single*[fn:12], reusing the same dired buffer.
  141. + Move up a directory with =h=
  142. + Open a single buffer with =l=
  143. #+begin_src emacs-lisp
  144. (use-package dired-single
  145. :config (evil-collection-define-key 'normal 'dired-mode-map
  146. "h" 'dired-single-up-directory
  147. "l" 'dired-single-buffer))
  148. #+end_src
  149. * Version control
  150. #+ATTR_ORG: :width 420px
  151. #+ATTR_HTML: :width 420px
  152. #+ATTR_LATEX: :width 420px
  153. [[../docs/images/2021-02-13-example-magit.gif]]
  154. Yet another hallmark feature of Emacs: *Magit*[fn:13] with the *darling* name, the developer stresses it's supposed to be *Magic* but with *Git*[fn:14]. It's a complete *Git*[fn:14] porcelain within Emacs.
  155. #+begin_src emacs-lisp
  156. (use-package magit
  157. :commands magit-status
  158. :custom (magit-display-buffer-function
  159. #'magit-display-buffer-same-window-except-diff-v1))
  160. #+end_src
  161. Place keybindings for *magit*[fn:13] behind =SPC g=.
  162. + Clone with =c=
  163. + Status with =g=
  164. #+begin_src emacs-lisp
  165. (dotfiles/leader
  166. "g" '(:ignore t :which-key "Magit")
  167. "gc" '(magit-clone :which-key "Clone")
  168. "gg" '(magit-status :which-key "Status"))
  169. #+end_src
  170. ** GitHub integration
  171. Interact with *Git*[fn:14] forges from *Magit*[fn:13] and Emacs using *Forge*[fn:15], requiring only a *GitHub*[fn:16] token to get started. If you're not sure what *GitHub*[fn:16] is, it's to *Git*[fn:14] what *Porn* is to *PornHub*. No citations!
  172. + Requires a valid ~$GITHUB_TOKEN~
  173. #+begin_src emacs-lisp
  174. (use-package forge
  175. :after magit)
  176. #+end_src
  177. ** Deploying the global config
  178. *Git*[fn:14] reads its global config from ~$HOME/.gitconfig~, create a link to the custom configuration.
  179. #+begin_src emacs-lisp
  180. (dotfiles/symlink "~/.emacs.d/config/git"
  181. "~/.gitconfig")
  182. #+end_src
  183. ** Interactive terminal
  184. Sometimes *Eshell*[fn:17] just isn't enough. Going through [[file:../docs/notes/thinking-in-cpp.org.gpg][Thinking in C++]] for one of my courses requires lots of terminal input which *Eshell*[fn:17] just doesn't handle. Prior to this I was dropping to another *TTY* interface, but that was cumbersome. *Vterm's*[fn:18] based on an external C library which is blazing fast.
  185. + Always compile the module
  186. #+begin_src emacs-lisp
  187. (use-package vterm
  188. :commands (vterm-other-window)
  189. :custom (vterm-always-compile-module t))
  190. #+end_src
  191. + Open =vterm= buffer with =SPC v=
  192. #+begin_src emacs-lisp
  193. (dotfiles/leader
  194. "v" '(vterm-other-window :which-key "Terminal"))
  195. #+end_src
  196. *** Installing dependencies
  197. Install dependencies on Debian/Ubuntu:
  198. #+begin_src shell
  199. sudo apt install -y cmake \
  200. libtool \
  201. libtool-bin
  202. #+end_src
  203. * Footnotes
  204. [fn:1] https://vim.org
  205. [fn:2] https://evil.readthedocs.io/en/latest/index.html
  206. [fn:3] https://github.com/hlissner/doom-emacs/
  207. [fn:4] https://spacemacs.org
  208. [fn:5] https://github.com/justbur/emacs-which-key/
  209. [fn:6] https://github.com/emacs-evil/evil-collection
  210. [fn:7] https://github.com/emacs-evil/evil-surround
  211. [fn:8] https://github.com/redguardtoo/evil-nerd-commenter
  212. [fn:9] https://github.com/noctuid/general.el
  213. [fn:10] https://github.com/abo-abo/hydra
  214. [fn:11] https://en.wikipedia.org/wiki/Dired
  215. [fn:12] https://github.com/crocket/dired-single
  216. [fn:13] https://github.com/magit/magit
  217. [fn:14] https://git-scm.com
  218. [fn:15] https://github.com/magit/forge
  219. [fn:16] https://github.com
  220. [fn:17] https://gnu.org/software/emacs/manual/html_mono/eshell.html
  221. [fn:18] https://github.com/akermu/emacs-libvterm