Christopher James Hayward
4 years ago
6 changed files with 313 additions and 321 deletions
-
2elisp/options.el
-
52modules/dired.org
-
320modules/editor.org
-
62modules/evil.org
-
136modules/keys.org
-
62modules/magit.org
@ -0,0 +1,52 @@ |
|||||
|
#+TITLE: Dired |
||||
|
#+AUTHOR: Christopher James Hayward |
||||
|
#+EMAIL: chris@chrishayward.xyz |
||||
|
|
||||
|
#+PROPERTY: header-args:emacs-lisp :tangle dired.el :comments org |
||||
|
#+PROPERTY: header-args :results silent :eval no-export :comments org |
||||
|
|
||||
|
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
||||
|
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
||||
|
|
||||
|
Emacs has a built-in directory editor. |
||||
|
|
||||
|
* Config |
||||
|
|
||||
|
Emacs has some really amazing built-in packages, and ~dired~[fn:1] is one of them. It completly coveres everything you would expect from a file manager, but it's not perfect out of the box. |
||||
|
|
||||
|
** Current directory |
||||
|
|
||||
|
I don't want to press =RET= twice to navigate to the current directory. There's a way to get around this problem with ~jump~, included in the ~dired-x~ package, included with Emacs. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(require 'dired-x) |
||||
|
#+end_src |
||||
|
|
||||
|
** Reusing the same buffer |
||||
|
|
||||
|
By default, ~dired~[fn:1] will create a new buffer each time you press =RET= over a directory. This leads to unwanted buffers all over the place. Avoid this behaviour with ~dired-single~[fn:2], reusing the same ~dired~ buffer. |
||||
|
|
||||
|
+ Move up a directory with =h= |
||||
|
+ Open a single buffer with =l= |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package dired-single |
||||
|
:config (evil-collection-define-key 'normal 'dired-mode-map |
||||
|
"h" 'dired-single-up-directory |
||||
|
"l" 'dired-single-buffer)) |
||||
|
#+end_src |
||||
|
|
||||
|
* Shortcuts |
||||
|
|
||||
|
Open a new dired buffer using the ~jump~ command with =SPC d=. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/leader |
||||
|
"d" '(dired-jump :which-key "Dired")) |
||||
|
#+end_src |
||||
|
|
||||
|
* Footnotes |
||||
|
|
||||
|
[fn:1] https://en.wikipedia.org/wiki/Dired |
||||
|
|
||||
|
[fn:2] https://github.com/crocket/dired-single |
@ -1,320 +0,0 @@ |
|||||
#+TITLE: Editor |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle editor.el :comments org |
|
||||
#+PROPERTY: header-args :results silent :eval no-export :comments org |
|
||||
|
|
||||
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
|
||||
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
|
||||
|
|
||||
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! |
|
||||
|
|
||||
* Keybindings |
|
||||
|
|
||||
Offer =ESC= as an alternative to quit (most) prompts, instead of the default =C-g=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(global-set-key (kbd "<escape>") 'keyboard-escape-quit) |
|
||||
#+end_src |
|
||||
|
|
||||
** Completions |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package which-key |
|
||||
:diminish which-key-mode |
|
||||
:custom (which-key-idle-delay dotfiles/idle) |
|
||||
:config (which-key-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Turn Emacs into Vim |
|
||||
|
|
||||
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]. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package evil |
|
||||
:custom (evil-want-integration t) ;; Required for `evil-collection'. |
|
||||
(evil-want-keybinding nil) ;; Same as above |
|
||||
:config (evil-mode +1)) |
|
||||
#+end_src |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package evil-collection |
|
||||
:after evil |
|
||||
:config (evil-collection-init)) |
|
||||
#+end_src |
|
||||
|
|
||||
*** Surround text |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package evil-surround |
|
||||
:after evil |
|
||||
:config (global-evil-surround-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
*** Toggle comments |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package evil-nerd-commenter |
|
||||
:after evil |
|
||||
:bind ("M-;" . evilnc-comment-or-uncomment-lines)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Implementing the leader key |
|
||||
|
|
||||
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]. |
|
||||
|
|
||||
+ =SPC= in most situations as a prefix key |
|
||||
+ =C-SPC= when using the [[file:desktop.org][Desktop]] module within an =X= buffer |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package general |
|
||||
:after evil |
|
||||
:config |
|
||||
(general-create-definer dotfiles/leader |
|
||||
:states '(normal motion) |
|
||||
:keymaps 'override |
|
||||
:prefix dotfiles/leader-key |
|
||||
:global-prefix dotfiles/leader-key-global)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Transient bindings |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
+ Defer loading for performance |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package hydra |
|
||||
:defer t) |
|
||||
#+end_src |
|
||||
|
|
||||
Place runtime tweaks behind =SPC t= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"t" '(:ignore t :which-key "Tweaks")) |
|
||||
#+end_src |
|
||||
|
|
||||
** Cherry picked shortcuts |
|
||||
|
|
||||
Implement shortcut bindings, cherry picked from *Doom*[fn:3]. |
|
||||
|
|
||||
+ Close buffers with =SPC c= |
|
||||
+ Find files with =SPC , (comma)= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"." '(find-file :which-key "Files") |
|
||||
"c" '(kill-buffer-and-window :which-key "Close")) |
|
||||
#+end_src |
|
||||
|
|
||||
*** Managing windows |
|
||||
|
|
||||
Window management with =SPC w= |
|
||||
|
|
||||
+ Swap with =w= |
|
||||
+ Close with =c= |
|
||||
+ Move with =h,j,k,l= |
|
||||
+ Split with =s - <motion>= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"w" '(:ignore t :which-key "Window") |
|
||||
"ww" '(window-swap-states :which-key "Swap") |
|
||||
"wc" '(delete-window :which-key "Close") |
|
||||
"wh" '(windmove-left :which-key "Left") |
|
||||
"wj" '(windmove-down :which-key "Down") |
|
||||
"wk" '(windmove-up :which-key "Up") |
|
||||
"wl" '(windmove-right :which-key "Right") |
|
||||
"ws" '(:ignore t :which-key "Split") |
|
||||
"wsj" '(split-window-below :which-key "Down") |
|
||||
"wsl" '(split-window-right :which-key "Right")) |
|
||||
#+end_src |
|
||||
|
|
||||
*** Quitting Emacs |
|
||||
|
|
||||
Quit Emacs with =SPC q= |
|
||||
|
|
||||
+ Save and quit =q= |
|
||||
+ Quit without saving =w= |
|
||||
+ Exit the Frame (daemon) =f= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"q" '(:ignore t :which-key "Quit") |
|
||||
"qq" '(save-buffers-kill-emacs :which-key "Save") |
|
||||
"qw" '(kill-emacs :which-key "Now") |
|
||||
"qf" '(delete-frame :which-key "Frame")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Helper functions |
|
||||
|
|
||||
Use the built-in ~describe-*~ functionality of Emacs to quickly access documentation for packages, variables, and functions. |
|
||||
|
|
||||
+ Run helper functions with =SPC h= |
|
||||
* Packages =p= |
|
||||
* Variables =v= |
|
||||
* Functions =f= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"h" '(:ignore t :which-key "Help") |
|
||||
"hp" '(describe-package :which-key "Package") |
|
||||
"hv" '(describe-variable :which-key "Variable") |
|
||||
"hf" '(describe-function :which-key "Function")) |
|
||||
#+end_src |
|
||||
|
|
||||
* File navigation |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
** Navigating to the current directory |
|
||||
|
|
||||
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]. |
|
||||
|
|
||||
+ Open a new dired buffer with =SPC d=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(require 'dired-x) |
|
||||
(dotfiles/leader |
|
||||
"d" '(dired-jump :which-key "Dired")) |
|
||||
#+end_src |
|
||||
|
|
||||
** Reusing the same buffer |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
+ Move up a directory with =h= |
|
||||
+ Open a single buffer with =l= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package dired-single |
|
||||
:config (evil-collection-define-key 'normal 'dired-mode-map |
|
||||
"h" 'dired-single-up-directory |
|
||||
"l" 'dired-single-buffer)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Version control |
|
||||
|
|
||||
#+ATTR_ORG: :width 420px |
|
||||
#+ATTR_HTML: :width 420px |
|
||||
#+ATTR_LATEX: :width 420px |
|
||||
[[../docs/images/2021-02-13-example-magit.gif]] |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package magit |
|
||||
:commands magit-status |
|
||||
:custom (magit-display-buffer-function |
|
||||
#'magit-display-buffer-same-window-except-diff-v1)) |
|
||||
#+end_src |
|
||||
|
|
||||
Place keybindings for *magit*[fn:13] behind =SPC g=. |
|
||||
|
|
||||
+ Clone with =c= |
|
||||
+ Status with =g= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"g" '(:ignore t :which-key "Magit") |
|
||||
"gc" '(magit-clone :which-key "Clone") |
|
||||
"gg" '(magit-status :which-key "Status")) |
|
||||
#+end_src |
|
||||
|
|
||||
** GitHub integration |
|
||||
|
|
||||
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! |
|
||||
|
|
||||
+ Requires a valid ~$GITHUB_TOKEN~ |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package forge |
|
||||
:after magit) |
|
||||
#+end_src |
|
||||
|
|
||||
** Deploying the global config |
|
||||
|
|
||||
*Git*[fn:14] reads its global config from ~$HOME/.gitconfig~, create a link to the custom configuration. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/git" |
|
||||
"~/.gitconfig") |
|
||||
#+end_src |
|
||||
|
|
||||
|
|
||||
** Interactive terminal |
|
||||
|
|
||||
Sometimes *Eshell*[fn:17] just isn't enough. Going through [[https://chrishayward.xyz/notes/thinking-in-cpp/][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. |
|
||||
|
|
||||
+ Always compile the module |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package vterm |
|
||||
:commands (vterm-other-window) |
|
||||
:custom (vterm-always-compile-module t)) |
|
||||
#+end_src |
|
||||
|
|
||||
+ Open =vterm= buffer with =SPC v= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"v" '(vterm-other-window :which-key "Terminal")) |
|
||||
#+end_src |
|
||||
|
|
||||
*** Installing dependencies |
|
||||
|
|
||||
Install dependencies on Debian/Ubuntu: |
|
||||
|
|
||||
#+begin_src shell |
|
||||
sudo apt install -y cmake \ |
|
||||
libtool \ |
|
||||
libtool-bin |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://vim.org |
|
||||
|
|
||||
[fn:2] https://evil.readthedocs.io/en/latest/index.html |
|
||||
|
|
||||
[fn:3] https://github.com/hlissner/doom-emacs/ |
|
||||
|
|
||||
[fn:4] https://spacemacs.org |
|
||||
|
|
||||
[fn:5] https://github.com/justbur/emacs-which-key/ |
|
||||
|
|
||||
[fn:6] https://github.com/emacs-evil/evil-collection |
|
||||
|
|
||||
[fn:7] https://github.com/emacs-evil/evil-surround |
|
||||
|
|
||||
[fn:8] https://github.com/redguardtoo/evil-nerd-commenter |
|
||||
|
|
||||
[fn:9] https://github.com/noctuid/general.el |
|
||||
|
|
||||
[fn:10] https://github.com/abo-abo/hydra |
|
||||
|
|
||||
[fn:11] https://en.wikipedia.org/wiki/Dired |
|
||||
|
|
||||
[fn:12] https://github.com/crocket/dired-single |
|
||||
|
|
||||
[fn:13] https://github.com/magit/magit |
|
||||
|
|
||||
[fn:14] https://git-scm.com |
|
||||
|
|
||||
[fn:15] https://github.com/magit/forge |
|
||||
|
|
||||
[fn:16] https://github.com |
|
||||
|
|
||||
[fn:17] https://gnu.org/software/emacs/manual/html_mono/eshell.html |
|
||||
|
|
||||
[fn:18] https://github.com/akermu/emacs-libvterm |
|
@ -0,0 +1,62 @@ |
|||||
|
#+TITLE: Evil |
||||
|
#+AUTHOR: Christopher James Hayward |
||||
|
#+EMAIL: chris@chrishayward.xyz |
||||
|
|
||||
|
#+PROPERTY: header-args:emacs-lisp :tangle evil.el :comments org |
||||
|
#+PROPERTY: header-args :results silent :eval no-export :comments org |
||||
|
|
||||
|
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
||||
|
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
||||
|
|
||||
|
Transform Emacs into Vim. |
||||
|
|
||||
|
* Config |
||||
|
|
||||
|
Emacs has some strange default keybindings, which given the age of the project, is not surprising. To overcome this nearly show-stopping hurdle, we transform Emacs into Vim with ~evil~[fn:1], the Extensible VI Layer for Emacs. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package evil |
||||
|
:custom (evil-want-integration t) ;; Required for `evil-collection'. |
||||
|
(evil-want-keybinding nil) ;; Same as above |
||||
|
:config (evil-mode +1)) |
||||
|
#+end_src |
||||
|
|
||||
|
** Improvements |
||||
|
|
||||
|
While covering substantial ground towards the goal, the default keybindings implemented in ~evil~[fn:1] alone are lacking compared to what you would expect from Vim. There's a community curated package ~evil-collection~[fn:2] that does a much better job implementing the proper keybindings. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package evil-collection |
||||
|
:after evil |
||||
|
:config (evil-collection-init)) |
||||
|
#+end_src |
||||
|
|
||||
|
** Surround text |
||||
|
|
||||
|
Quickly and efficiently surround text with ~evil-surround~[fn:3]. Highlight blocks of text with function definitions, quotations, or any symbol you can input from your keyboard. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package evil-surround |
||||
|
:after evil |
||||
|
:config (global-evil-surround-mode 1)) |
||||
|
#+end_src |
||||
|
|
||||
|
** Toggle comments |
||||
|
|
||||
|
Toggle comments in a language agnostic manner with ~evil-nerd-commenter~[fn:4]. Add a custom binding to =M-;= to mimmic the behaviour in other popular Emacs configuration frameworks. What is =M-?= Called the *Meta* key in Emacs, it typically refers to =Alt=. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package evil-nerd-commenter |
||||
|
:after evil |
||||
|
:bind ("M-;" . evilnc-comment-or-uncomment-lines)) |
||||
|
#+end_src |
||||
|
|
||||
|
* Footnotes |
||||
|
|
||||
|
[fn:1] https://github.com/emacs-evil/evil-mode |
||||
|
|
||||
|
[fn:2] https://github.com/emacs-evil/evil-collection |
||||
|
|
||||
|
[fn:3] https://github.com/emacs-evil/evil-surround |
||||
|
|
||||
|
[fn:4] https://github.com/redguardtoo/evil-nerd-commenter |
@ -0,0 +1,136 @@ |
|||||
|
#+TITLE: Keys |
||||
|
#+AUTHOR: Christopher James Hayward |
||||
|
#+EMAIL: chris@chrishayward.xyz |
||||
|
|
||||
|
#+PROPERTY: header-args:emacs-lisp :tangle keys.el :comments org |
||||
|
#+PROPERTY: header-args :results silent :eval no-export :comments org |
||||
|
|
||||
|
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
||||
|
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
||||
|
|
||||
|
Improve the keyboard experience within Emacs. |
||||
|
|
||||
|
* Config |
||||
|
|
||||
|
Some of the default keybindings in Emacs really do leave you wondering, for example, when you want to exit a prompt you have to use =C-g=. Offer =ESC= as an alternative to quit (most) prompts, which I have muscle memory for already from literally every program created since 1990. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(global-set-key (kbd "<escape>") 'keyboard-escape-quit) |
||||
|
#+end_src |
||||
|
|
||||
|
** Hints |
||||
|
|
||||
|
Since Emacs is keyboard driven software, there are a lot of keybindings. Sometimes it's useful to start pressing well-known key combinations, and view the available completions. This behaviour is implemented in the third-party package ~which-key~[fn:1]. It displays the current incomplete keybinding input in a mini-buffer. It also works in the other direction, showing the corresponding keybindings for each command when you run =M-x=. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package which-key |
||||
|
:diminish which-key-mode |
||||
|
:custom (which-key-idle-delay dotfiles/idle) |
||||
|
:config (which-key-mode)) |
||||
|
#+end_src |
||||
|
|
||||
|
** Leader |
||||
|
|
||||
|
If like myself, you started using Emacs using a framework such as ~doom~[fn:2] or ~spacemacs~[fn:3], you probably have a considerable amount of muscle memory developed for using =SPC= as a leader key. In both of the previously mentioned frameworks, the package ~general.el~[fn:4] is used to implement this behaviour. It's a major improvement to the default way of creating custom keybindings in Emacs. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package general |
||||
|
:config |
||||
|
(general-create-definer dotfiles/leader |
||||
|
:states '(normal motion) |
||||
|
:keymaps 'override |
||||
|
:prefix dotfiles/leader-key |
||||
|
:global-prefix dotfiles/leader-key-global)) |
||||
|
#+end_src |
||||
|
|
||||
|
** Transient |
||||
|
|
||||
|
Create transient keybindings with a shared prefix through ~hydra~[fn:5]. This is also used by a number of third-party packages as a completion system. An implementation example is used to scale the font size. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package hydra |
||||
|
:defer t) |
||||
|
#+end_src |
||||
|
|
||||
|
* Shortcuts |
||||
|
|
||||
|
Implement some shortcut bindings, with a significant portion of them cherry picked from ~doom~[fn:2]: |
||||
|
|
||||
|
+ Close buffers with =SPC c= |
||||
|
+ Find files with =SPC . (period)= |
||||
|
+ Switch buffers with =SPC , (comma)= |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/leader |
||||
|
"." '(find-file :which-key "Files") |
||||
|
"," '(switch-buffer :which-key "Buffers") |
||||
|
"c" '(kill-buffer-and-window :which-key "Close")) |
||||
|
#+end_src |
||||
|
|
||||
|
** Managing windows |
||||
|
|
||||
|
Screen space is divided into Frames inside of Emacs, manage them behind =SPC w=: |
||||
|
|
||||
|
+ Swap with =w= |
||||
|
+ Close with =c= |
||||
|
+ Move with =h,j,k,l= |
||||
|
+ Split with =s - <motion>= |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/leader |
||||
|
"w" '(:ignore t :which-key "Window") |
||||
|
"ww" '(window-swap-states :which-key "Swap") |
||||
|
"wc" '(delete-window :which-key "Close") |
||||
|
"wh" '(windmove-left :which-key "Left") |
||||
|
"wj" '(windmove-down :which-key "Down") |
||||
|
"wk" '(windmove-up :which-key "Up") |
||||
|
"wl" '(windmove-right :which-key "Right") |
||||
|
"ws" '(:ignore t :which-key "Split") |
||||
|
"wsj" '(split-window-below :which-key "Down") |
||||
|
"wsl" '(split-window-right :which-key "Right")) |
||||
|
#+end_src |
||||
|
|
||||
|
|
||||
|
** Quitting Emacs |
||||
|
|
||||
|
Customize the behaviour of exiting emacs, with keybindings behind =SPC q=: |
||||
|
|
||||
|
+ Save and quit =q= |
||||
|
+ Quit without saving =w= |
||||
|
+ Exit the Frame (daemon) =f= |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/leader |
||||
|
"q" '(:ignore t :which-key "Quit") |
||||
|
"qq" '(save-buffers-kill-emacs :which-key "Save") |
||||
|
"qw" '(kill-emacs :which-key "Now") |
||||
|
"qf" '(delete-frame :which-key "Frame")) |
||||
|
#+end_src |
||||
|
|
||||
|
** Helper Functions |
||||
|
|
||||
|
Use the built-in ~describe-*~ functionality of Emacs to quickly access documentation for packages, variables, and functions. Run helper functions with =SPC h=: |
||||
|
|
||||
|
+ Packages =p= |
||||
|
+ Variables =v= |
||||
|
+ Functions =f= |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/leader |
||||
|
"h" '(:ignore t :which-key "Help") |
||||
|
"hp" '(describe-package :which-key "Package") |
||||
|
"hv" '(describe-variable :which-key "Variable") |
||||
|
"hf" '(describe-function :which-key "Function")) |
||||
|
#+end_src |
||||
|
|
||||
|
* Footnotes |
||||
|
|
||||
|
[fn:1] https://github.com/justbur/emacs-which-key/ |
||||
|
|
||||
|
[fn:2] https://github.com/hlissner/doom-emacs/ |
||||
|
|
||||
|
[fn:3] https://spacemacs.org |
||||
|
|
||||
|
[fn:4] https://github.com/noctuid/general.el |
||||
|
|
||||
|
[fn:5] https://github.com/abo-abo/hydra |
@ -0,0 +1,62 @@ |
|||||
|
#+TITLE: Magit |
||||
|
#+AUTHOR: Christopher James Hayward |
||||
|
#+EMAIL: chris@chrishayward.xyz |
||||
|
|
||||
|
#+PROPERTY: header-args:emacs-lisp :tangle magit.el :comments org |
||||
|
#+PROPERTY: header-args :results silent :eval no-export :comments org |
||||
|
|
||||
|
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
||||
|
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
||||
|
|
||||
|
Handle all of the git interactions inside of Emacs. |
||||
|
|
||||
|
* Setup |
||||
|
|
||||
|
Deploy the global configuration file for ~git~[fn:1], by default it reads from =$HOME/.gitconfig=. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/symlink "~/.emacs.d/config/git" |
||||
|
"~/.gitconfig") |
||||
|
#+end_src |
||||
|
|
||||
|
* Config |
||||
|
|
||||
|
Another hallmark feature of Emacs is ~magit~[fn:2]. It's a complete git porcelain inside of Emacs. The developer has stressed that it's most unfortunate name was meant to be pronounced like *magic* but with *git*. Despire his best efforts a lot of people have taken to pronouncing it *maggot*, which keeps him awake at night (probably). |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package magit |
||||
|
:commands magit-status |
||||
|
:custom (magit-display-buffer-function |
||||
|
#'magit-display-buffer-same-window-except-diff-v1)) |
||||
|
#+end_src |
||||
|
|
||||
|
** Forge integration |
||||
|
|
||||
|
It's possible to interact with forges from Github / Gitlab using ~forge~[fn:3]. It requires the respective =$TOKEN= to be configured, or an alternative form of authentication. This enables working with pull-requests, code-reviews, and issues from inside of Emacs. |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(use-package forge |
||||
|
:after magit) |
||||
|
#+end_src |
||||
|
|
||||
|
* Shortcuts |
||||
|
|
||||
|
Interact with ~magit~[fn:2] behind =SPC g=: |
||||
|
|
||||
|
+ Clone with =c= |
||||
|
+ Status with =g= |
||||
|
|
||||
|
#+begin_src emacs-lisp |
||||
|
(dotfiles/leader |
||||
|
"g" '(:ignore t :which-key "Magit") |
||||
|
"gc" '(magit-clone :which-key "Clone") |
||||
|
"gg" '(magit-status :which-key "Status")) |
||||
|
#+end_src |
||||
|
|
||||
|
* Footnotes |
||||
|
|
||||
|
[fn:1] https://git-scm.com |
||||
|
|
||||
|
[fn:2] https://github.com/magit/magit |
||||
|
|
||||
|
[fn:3] https://github.com/magit/forge |
Write
Preview
Loading…
Cancel
Save
Reference in new issue