Christopher James Hayward
3 years ago
48 changed files with 1996 additions and 3141 deletions
-
2180README.org
-
BINconfig/authinfo.gpg
-
5config/git
-
2config/gpg-agent.conf
-
26config/mbsyncrc
-
6config/mpd.conf
-
22config/profile
-
11config/xinitrc
-
7config/xmodmap
-
31hosts/acernitro.org
-
38modules/agenda.org
-
56modules/capture.org
-
45modules/cc.org
-
55modules/conf.org
-
33modules/dap.org
-
89modules/dashboard.org
-
52modules/dired.org
-
44modules/docker.org
-
58modules/elfeed.org
-
86modules/emms.org
-
45modules/eshell.org
-
100modules/evil.org
-
72modules/exwm.org
-
123modules/fonts.org
-
75modules/go.org
-
68modules/gpg.org
-
30modules/grammar.org
-
100modules/hugo.org
-
80modules/ivy.org
-
137modules/keys.org
-
76modules/lsp.org
-
62modules/magit.org
-
19modules/modeline.org
-
150modules/mu4e.org
-
27modules/nix.org
-
160modules/org.org
-
51modules/pass.org
-
136modules/projects.org
-
67modules/python.org
-
55modules/reveal.org
-
175modules/roam.org
-
98modules/shell.org
-
36modules/spelling.org
-
48modules/themes.org
-
38modules/trash.org
-
55modules/uml.org
-
43modules/vterm.org
-
165modules/x11.org
2180
README.org
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,5 +0,0 @@ |
|||||
[user] |
|
||||
email = chris@chrishayward.xyz |
|
||||
name = Christopher James Hayward |
|
||||
[github] |
|
||||
user = chayward1 |
|
@ -1,2 +0,0 @@ |
|||||
allow-emacs-pinentry |
|
||||
allow-loopback-pinentry |
|
@ -1,26 +0,0 @@ |
|||||
# Sync |
|
||||
# :PROPERTIES: |
|
||||
# :header-args: :tangle ../config/mbsyncrc :comments org |
|
||||
# :END: |
|
||||
|
|
||||
# This is the *mbsyncrc*[fn:3] file I use to synchronize my local mail with my server. |
|
||||
|
|
||||
|
|
||||
IMAPStore xyz-remote |
|
||||
Host mail.chrishayward.xyz |
|
||||
User chris@chrishayward.xyz |
|
||||
PassCmd "pass chrishayward.xyz/chris" |
|
||||
SSLType IMAPS |
|
||||
|
|
||||
MaildirStore xyz-local |
|
||||
Path ~/.cache/mail/ |
|
||||
Inbox ~/.cache/mail/inbox |
|
||||
SubFolders Verbatim |
|
||||
|
|
||||
Channel xyz |
|
||||
Master :xyz-remote: |
|
||||
Slave :xyz-local: |
|
||||
Patterns * !Archives |
|
||||
Create Both |
|
||||
Expunge Both |
|
||||
SyncState * |
|
@ -1,6 +0,0 @@ |
|||||
music_directory "~/.local/share/media/music" |
|
||||
|
|
||||
playlist_directory "~/.local/share/media/playlists" |
|
||||
|
|
||||
bind_to_address "localhost" |
|
||||
port "6600" |
|
@ -1,22 +0,0 @@ |
|||||
# Force colours |
|
||||
|
|
||||
# Manually set the terminal type to ~xterm-256color~ for better colours on TTY Emacs. |
|
||||
|
|
||||
|
|
||||
export TERM=xterm-256color |
|
||||
|
|
||||
# Setting up the $PATH |
|
||||
|
|
||||
# Ensure ~~/.local/bin~ added to the =$PATH= environment variable. |
|
||||
|
|
||||
|
|
||||
export PATH=$PATH:~/.local/bin |
|
||||
|
|
||||
# Starting Emacs by default on TTY1 |
|
||||
|
|
||||
# When launching into a new session on ~TTY1~, if the display server is not running, run *StartX*[fn:3]. This will launch the window manager. |
|
||||
|
|
||||
|
|
||||
if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then |
|
||||
exec startx |
|
||||
fi |
|
@ -1,11 +0,0 @@ |
|||||
# Config |
|
||||
# :PROPERTIES: |
|
||||
# :header-args: :tangle ../config/xinitrc :comments org |
|
||||
# :END: |
|
||||
|
|
||||
# My workflow includes launching Emacs under X11[fn:1] without the use of a display manager, controlling everything within Emacs, while still providing the functionality of a desktop environment. |
|
||||
|
|
||||
|
|
||||
compton & |
|
||||
xss-lock -- slock & |
|
||||
exec dbus-launch --exit-with-session emacs -mm --debug-init |
|
@ -1,7 +0,0 @@ |
|||||
clear lock |
|
||||
clear control |
|
||||
|
|
||||
keycode 66 = Control_L |
|
||||
|
|
||||
add control = Control_L |
|
||||
add Lock = Control_R |
|
@ -1,31 +0,0 @@ |
|||||
#+TITLE: Acernitro |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle acernitro.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 |
|
||||
|
|
||||
The first real hardware to deploy this configuration on. It's an [[https://www.amazon.com/Acer-Nitro-AN515-Laptop-i5-8300H/dp/B07C715KNT][Acer Nitro AN-515]][fn:1] with the [[https://7thzero.com/blog/switch-hybrid-graphics-mode-nvidia-and-intel][NVIDIA / Intel Hybrid GPU]] [fn:2], which is honestly a pain in the ass to deal with. Due to the issues I encountered with this hardware setup, I opted for *easy mode* and installed [[https://ubuntu.com][Ubuntu]][fn:3], setting up the drivers, and then ripping away everything I didn't need. |
|
||||
|
|
||||
* Options |
|
||||
|
|
||||
+ Set the browser manually |
|
||||
+ Set the language to Canadian english |
|
||||
+ Increase the font size for the high DPI screen |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(setq dotfiles/browser "firefox" |
|
||||
dotfiles/language "en_CA" |
|
||||
dotfiles/font-size 112) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://www.amazon.com/Acer-Nitro-AN515-Laptop-i5-8300H/dp/B07C715KNT |
|
||||
|
|
||||
[fn:2] https://7thzero.com/blog/switch-hybrid-graphics-mode-nvidia-and-intel |
|
||||
|
|
||||
[fn:3] https://ubuntu.com |
|
@ -1,38 +0,0 @@ |
|||||
#+TITLE: Agenda |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle agenda.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 |
|
||||
|
|
||||
Agenda integrations for ~org-mode~. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Integrate the ~org-agenda~ with the ~org-roam~ database, and the rest of the ~org-mode~ contexts throughout the repository: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(setq org-agenda-files '("~/.emacs.d/" |
|
||||
"~/.emacs.d/docs/" |
|
||||
"~/.emacs.d/docs/courses/" |
|
||||
"~/.emacs.d/docs/daily/" |
|
||||
"~/.emacs.d/docs/notes/" |
|
||||
"~/.emacs.d/docs/posts/" |
|
||||
"~/.emacs.d/docs/slides/" |
|
||||
"~/.emacs.d/hosts/" |
|
||||
"~/.emacs.d/modules/")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Open an agenda buffer with =SPC a=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"a" '(org-agenda :which-key "Agenda")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
@ -1,56 +0,0 @@ |
|||||
#+TITLE: Capture |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle capture.el :comments org |
|
||||
#+PROPERTY: header-args :results silent :eval no-export |
|
||||
|
|
||||
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
|
||||
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
|
||||
|
|
||||
Capturing images, screencasts, screenshots or live-streaming. It's defined in this file. |
|
||||
|
|
||||
* Screenshots |
|
||||
|
|
||||
Download *screenshot.el*[fn:1] for taking screenshots of highlighted regions or entire buffers. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(straight-use-package |
|
||||
'(screenshot |
|
||||
:type git |
|
||||
:host github |
|
||||
:repo "tecosaur/screenshot")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Screencasts |
|
||||
|
|
||||
Create screencasts with =one-frame-per-action= GIF recording via *Emacs gif screencast*[fn:2]. |
|
||||
|
|
||||
+ Pause / Resume |
|
||||
+ High Quality |
|
||||
+ Optimized |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package gif-screencast |
|
||||
:commands (gif-screencast-start-or-stop gif-screencast-toggle-pause) |
|
||||
:custom (gif-screencast-output-directory (concat dotfiles/home "docs/images/"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Keybindings |
|
||||
|
|
||||
+ Place keybindings for capturing the screen behind =SPC s=. |
|
||||
* Screenshot with =s= |
|
||||
* Screencast with =c= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"s" '(:ignore t :which-key "Screen") |
|
||||
"ss" '(screenshot :which-key "Screenshot") |
|
||||
"sc" '(gif-screencast-start-or-stop :which-key "Screencast")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/tecosaur/screenshot |
|
||||
|
|
||||
[fn:2] https://github.com/takaxp/emacs-gif-screencast |
|
@ -1,45 +0,0 @@ |
|||||
#+TITLE: C/C++ |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle cc.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
#+begin_quote |
|
||||
The goal of C++ is productivity, this comes in many ways, but the language is designed to aid you as much as possible whiole hindering you as little as possible with arbitrary rules or requirements. |
|
||||
|
|
||||
-- Bruce Eckel, Thinking in C++[fn:1] |
|
||||
#+end_quote |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Make sure all of the required components are installed, and the ~lsp~ and ~dap~ modules have loaded before loading this module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y gcc gdb ccls libstdc++ |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Use the ~ccls~[fn:2] language server, and the respective Emacs package to interact with the server inside of Emacs. Load the ~babel~ language module and add structure templates for creating C/C++ code blocks inside ~org-mode~. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ccls |
|
||||
:hook ((c-mode c++-mode objc-mode cuda-mode) . |
|
||||
(lambda () |
|
||||
(require 'ccls) |
|
||||
(lsp-deferred))) |
|
||||
:config (add-to-list 'org-structure-template-alist '("cc" . "src C")) |
|
||||
(add-to-list 'org-structure-template-alist '("cpp" . "src C++")) |
|
||||
(org-babel-do-load-languages 'org-babel-load-languages '((C . t)))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://chrishayward.xyz/notes/thinking-in-cpp/ |
|
||||
|
|
||||
[fn:2] https://github.com/MaskRay/ccls |
|
@ -1,55 +0,0 @@ |
|||||
#+TITLE: Conf |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle conf.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Support for different configuration languages. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Add support for different configuration languages, or other modules that don't fit in their own module (yet). |
|
||||
|
|
||||
** HTTP |
|
||||
|
|
||||
Interact with ~HTTP~ endpoints using the ~ob-http~[fn:1] package. You can see how it works in my post here[fn:2]. It adds interactive ~HTTP~ blocks that can output their results in place, within an ~org-mode~ buffer. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ob-http |
|
||||
:after org |
|
||||
:config (org-babel-do-load-languages |
|
||||
'org-babel-load-languages '((http . t)))) |
|
||||
#+end_src |
|
||||
|
|
||||
** YAML |
|
||||
|
|
||||
Support for YAML[fn:3] files. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package yaml-mode) |
|
||||
#+end_src |
|
||||
|
|
||||
** gRPC |
|
||||
|
|
||||
Support for gRPC[fn:4] protocol buffer definition files. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package protobuf-mode |
|
||||
:after org |
|
||||
:config (add-to-list 'org-structure-template-alist '("pb" . "src protobuf"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/zweifisch/ob-http |
|
||||
|
|
||||
[fn:2] https://chrishayward.xyz/posts/kanye-as-a-service/ |
|
||||
|
|
||||
[fn:3] https://emacswiki.org/emacs/YamlMode |
|
||||
|
|
||||
[fn:4] https://github.com/protocolbuffers/protobuf/blob/master/editors/protobuf-mode.el |
|
@ -1,33 +0,0 @@ |
|||||
#+TITLE: Debug Adapter Protocol |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle dap.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
The Debug Adapter Protocol (DAP) defines the abstract protocol used between a development tool (Emacs) and a debugger[fn:1]. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Use the package ~dap-mode~[fn:2] to add support for the Debug Adapter Protocol[fn:1] inside of Emacs. It has been tested against the following language servers: |
|
||||
|
|
||||
+ Java |
|
||||
+ Ruby |
|
||||
+ Python |
|
||||
+ Elixir |
|
||||
+ LLDB (C/C++/Obj-C/Swift) |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package dap-mode |
|
||||
:commands (dap-debug)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://microsoft.github.io/debug-adapter-protocol/ |
|
||||
|
|
||||
[fn:2] https://github.com/emacs-lsp/dap-mode |
|
@ -1,89 +0,0 @@ |
|||||
#+TITLE: Dashboard |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle dashboard.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
#+ATTR_ORG: :width 420px |
|
||||
#+ATTR_HTML: :width 420px |
|
||||
#+ATTR_LATEX: :width 420px |
|
||||
[[../docs/images/desktop-example.png]] |
|
||||
|
|
||||
Present a *Dashboard*[fn:1] when first launching Emacs. Customize the buttons of the navigator. |
|
||||
|
|
||||
* Configuration |
|
||||
|
|
||||
Goal of this module is to provide an easily customizable dashboard buffer to display when launching Emacs. I also want it to include some custom links. These are hard coded right now but I want to move them to [[file:../README.org][Options]]. |
|
||||
|
|
||||
+ Brain @ http://localhost:8080 |
|
||||
+ Homepage @ https://chrishayward.xyz |
|
||||
+ Athabasca @ https://login.athabascau.ca/cas/login |
|
||||
+ Bookshelf @ https://online.vitalsource.com |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package dashboard |
|
||||
:custom (dashboard-center-content t) |
|
||||
(dashboard-set-init-info t) |
|
||||
(dashboard-set-file-icons t) |
|
||||
(dashboard-set-heading-icons t) |
|
||||
(dashboard-set-navigator t) |
|
||||
(dashboard-startup-banner (expand-file-name "~/.emacs.d/docs/images/emacs.png")) |
|
||||
(dashboard-projects-backend 'projectile) |
|
||||
(dashboard-items '((projects . 10) (recents . 10) (agenda . 10))) |
|
||||
(dashboard-navigator-buttons |
|
||||
`(((,(all-the-icons-fileicon "brain" :height 1.1 :v-adjust 0.0) |
|
||||
"Brain" "Knowledge base" |
|
||||
(lambda (&rest _) (browse-url "http://localhost:8080")))) |
|
||||
((,(all-the-icons-material "public" :height 1.1 :v-adjust 0.0) |
|
||||
"Homepage" "Personal website" |
|
||||
(lambda (&rest _) (browse-url "https://chrishayward.xyz")))) |
|
||||
((,(all-the-icons-faicon "university" :height 1.1 :v-adjust 0.0) |
|
||||
"Athabasca" "Univeristy login" |
|
||||
(lambda (&rest _) (browse-url "https://login.athabascau.ca/cas/login")))) |
|
||||
((,(all-the-icons-faicon "book" :height 1.1 :v-adjust 0.0) |
|
||||
"Bookshelf" "Vitalsource bookshelf" |
|
||||
(lambda (&rest _) (browse-url "https://online.vitalsource.com")))))) |
|
||||
:config (dashboard-setup-startup-hook)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Default buffer |
|
||||
|
|
||||
Ensure that the dashboard is the initial buffer. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'dashboard |
|
||||
(setq initial-buffer-choice |
|
||||
(lambda () |
|
||||
(get-buffer "*dashboard*")))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Keybinding |
|
||||
|
|
||||
Quickly navigate to the dashboard with =SPC SPC=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"SPC" '((lambda () |
|
||||
(interactive) |
|
||||
(switch-to-buffer "*dashboard*")) |
|
||||
:which-key "Dashboard")) |
|
||||
#+end_src |
|
||||
|
|
||||
Navigate to the scratch buffer with =SPC C-SPC=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"C-SPC" '((lambda () |
|
||||
(interactive) |
|
||||
(switch-to-buffer "*scratch*")) |
|
||||
:which-key "Scratch")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/emacs-dashboard/emacs-dashboard |
|
@ -1,52 +0,0 @@ |
|||||
#+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,44 +0,0 @@ |
|||||
#+TITLE: Docker |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle docker.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Interact with Docker[fn:1] inside of Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Make sure you have the required components installed on your system before loading the module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y docker docker-compose |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
It's possible to interact with Docker[fn:1] inside of Emacs through the ~docker.el~[fn:2] plugin. It provides rich support for working with containers, images, compose networks, and has bindings for using machine. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package docker |
|
||||
:commands (docker)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Open the container management screen with =SPC k=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"k" '(docker :which-key "Docker")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://docker.com |
|
||||
|
|
||||
[fn:2] https://github.com/Silex/docker.el |
|
@ -1,58 +0,0 @@ |
|||||
#+TITLE: Elfeed |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle elfeed.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+PROPERTY: header-args :results silent :eval no-export :comments org |
|
||||
|
|
||||
Setup a news feed inside of Emacs using ~elfeed~[fn:1], an Emacs web feeds client. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
+ Add the feed for my website[fn:2] to make sure the RSS feeds are updating correctly |
|
||||
+ Add some subreddits, mostly about ~linux~, ~emacs~ and ~org-mode~ |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package elfeed |
|
||||
:commands (elfeed elfeed-update) |
|
||||
:custom (elfeed-feeds (quote |
|
||||
(("https://hexdsl.co.uk/rss.xml") |
|
||||
("https://lukesmith.xyz/rss.xml") |
|
||||
("https://friendo.monster/rss.xml") |
|
||||
("https://chrishayward.xyz/index.xml") |
|
||||
("https://protesilaos.com/codelog.xml"))))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Goodies |
|
||||
|
|
||||
Extend ~elfeed~[fn:1] with the ~elfeed-goodies~[fn:3] package. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package elfeed-goodies |
|
||||
:after elfeed |
|
||||
:custom (elfeed-goodies/entry-pane-size 0.5) |
|
||||
:config (elfeed-goodies/setup)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Configure ~elfeed~[fn:1] keybindings behind =SPC l=: |
|
||||
|
|
||||
+ Open with =l= |
|
||||
+ Update with =u= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"l" '(:ignore t :which-key "Elfeed") |
|
||||
"ll" '(elfeed :which-key "Open") |
|
||||
"lu" '(elfeed-update :which-key "Update")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/skeeto/elfeed |
|
||||
|
|
||||
[fn:2] https://chrishayward.xyz/index.xml |
|
||||
|
|
||||
[fn:3] https://github.com/algernon/elfeed-goodies |
|
@ -1,86 +0,0 @@ |
|||||
#+TITLE: EMMS |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle emms.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 |
|
||||
|
|
||||
EMMS[fn:1] is Emacs as a multimedia player. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Make sure you install the required packages on your system before loading the module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y mpc mpd mpv |
|
||||
#+end_src |
|
||||
|
|
||||
** Music player daemon |
|
||||
:PROPERTIES: |
|
||||
:header-args: :tangle ../config/mpd.conf |
|
||||
:END: |
|
||||
|
|
||||
MPD[fn:2] uses a simple text configuration file. Most options only accept a string in " quotes ". The most important option to configure is the ~music_directory~. This is where all of the music ~mpd~[fn:2] will serve exists. It will read the directory recursively. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
music_directory "~/.local/share/media/music" |
|
||||
#+end_src |
|
||||
|
|
||||
You can configure where ~mpd~[fn:2] will look for playlists. You may want to configure this option if you share your playlists between devices. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
playlist_directory "~/.local/share/media/playlists" |
|
||||
#+end_src |
|
||||
|
|
||||
It's possible to serve ~mpd~[fn:2] over the network by configuring it to listen on =0.0.0.0=, or by the systems host name. For a local setup, leave it as =localhost=. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
bind_to_address "localhost" |
|
||||
port "6600" |
|
||||
#+end_src |
|
||||
|
|
||||
*** Deploy the configuration |
|
||||
|
|
||||
MPD[fn:2] will look for its configuration in =~/.config/mpd/mpd.conf=, and =/etc/mpd.conf= respectively. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(let ((mpd-dir "~/.config/mpd")) |
|
||||
(unless (file-exists-p mpd-dir) |
|
||||
(make-directory mpd-dir t)) |
|
||||
(dotfiles/symlink "~/.emacs.d/config/mpd.conf" |
|
||||
(concat mpd-dir "/mpd.conf"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Displays and play multimedia from within Emacs with ~emms~[fn:1], using a variety of external players from different sources. It can run as a minimalist player and controlled with commands, or a fully fledged interactive media browser. It can display album art, play streaming media, tag files, search lyrics, and provide ~mpd~[fn:2] connectivity. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package emms |
|
||||
:custom (emms-player-mpd-server-name "localhost") |
|
||||
(emms-player-mpd-server-port "6600") |
|
||||
:config (require 'emms-setup) |
|
||||
(require 'emms-player-mpd) |
|
||||
(emms-all) |
|
||||
(emms-default-players) |
|
||||
(add-to-list 'emms-info-functions 'emms-info-mpd) |
|
||||
(add-to-list 'emms-player-list 'emms-player-mpd)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Place bindings for ~emms~[fn:1] behind =SPC u=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"u" '(:ignore t :which-key "EMMS")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://gnu.org/software/emms/ |
|
||||
|
|
||||
[fn:2] https://musicpd.org |
|
@ -1,45 +0,0 @@ |
|||||
#+TITLE: EShell |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle eshell.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 |
|
||||
|
|
||||
EShell is a fully POSIX compliant shell written entirely in Emacs Lisp, included with Emacs. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
While not a traditional terminal emulator, it provides a native REPL for Emacs Lisp code, with everything in your configuration available in the environment. Make some slight configurations: |
|
||||
|
|
||||
+ Don't highlight the prompt |
|
||||
+ Favour use of system utilities |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(setq eshell-highlight-prompt nil |
|
||||
eshell-prefer-lisp-functions nil) |
|
||||
#+end_src |
|
||||
|
|
||||
* Extras |
|
||||
|
|
||||
Implement the lambda prompt for aesthetic purposes with the ~eshell-prompt-extras~ package. Here's an example of what that looks like: |
|
||||
|
|
||||
#+begin_example |
|
||||
~/.emacs.d/modules:main*? λ |
|
||||
#+end_example |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package eshell-prompt-extras |
|
||||
:custom (eshell-prompt-function 'epe-theme-lambda)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Open ~eshell~ in the current buffer with =SPC e=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"e" '(eshell :which-key "EShell")) |
|
||||
#+end_src |
|
@ -1,100 +0,0 @@ |
|||||
#+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 |
|
||||
|
|
||||
** Line numbering |
|
||||
|
|
||||
Relative line numbers are important when using VI emulation keys. You can prefix commands with a number, allowing you to perform that action that number of times. Useful when navigating around pages that are hundreds, or even thousands of lines long. |
|
||||
|
|
||||
#+begin_example |
|
||||
5: |
|
||||
4: |
|
||||
3: |
|
||||
2: |
|
||||
1: |
|
||||
156: << CURRENT LINE >> |
|
||||
1: |
|
||||
2: |
|
||||
3: |
|
||||
4: |
|
||||
5: |
|
||||
#+end_example |
|
||||
|
|
||||
This behaviour is implemented with ~linum-relative~[fn:4], hooking into the ~display-line-number-mode~ as the backend for good performance in the GUI or TTY. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package linum-relative |
|
||||
:commands (linum-relative-global-mode) |
|
||||
:custom (linum-delay t) |
|
||||
(linum-relative-backend 'display-line-numbers-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Toggle comments |
|
||||
|
|
||||
Toggle comments in a language agnostic manner with ~evil-nerd-commenter~[fn:5]. 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 |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Toggle relative line numbers with =SPC t l=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"tl" '(linum-relative-global-mode :which-key "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/emacsmirror/linum-relative |
|
||||
|
|
||||
[fn:5] https://github.com/redguardtoo/evil-nerd-commenter |
|
@ -1,72 +0,0 @@ |
|||||
#+TITLE: EXWM |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle exwm.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 can run as a complete tiling window manager for X11. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Load the ~x11~ module before loading this module. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
When ~exwm~[fn:1] first launches the ~init-hook~ is executed, allowing us to define some custom logic inside of a hook. Display the time and date, and the battery information, if any is available. I add this here because when I'm running Emacs without ~exwm~[fn:1], information such as the batter and time is typically already available. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/init-hook () |
|
||||
(exwm-workspace-switch-create 1) |
|
||||
(setq display-time-and-date t) |
|
||||
(display-battery-mode 1) |
|
||||
(display-time-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Display detection |
|
||||
|
|
||||
Enable hot plugging by forcing a profile change with ~autorandr~. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/update-display () |
|
||||
"Update the displays by forcing a change through autorandr." |
|
||||
(dotfiles/run-in-background "autorandr --change --force")) |
|
||||
#+end_src |
|
||||
|
|
||||
** Window manager |
|
||||
|
|
||||
Connect all of the custom hooks and configure the input keys, a custom layer for key captures when Emacs us running as a window manager. Enable ~randr~ support, to function with ~autorandr~, and apply some default bindings. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package exwm |
|
||||
:when (window-system) |
|
||||
:custom (exwm-workspace-show-all-buffers t) |
|
||||
(exwm-input-prefix-keys |
|
||||
'(?\M-x |
|
||||
?\C-g |
|
||||
?\C-\ )) |
|
||||
(exwm-input-global-keys |
|
||||
`(([?\s-r] . exwm-reset) |
|
||||
,@(mapcar (lambda (i) |
|
||||
`(,(kbd (format "s-%d" i)) . |
|
||||
(lambda () |
|
||||
(interactive) |
|
||||
(exwm-workspace-switch-create ,i)))) |
|
||||
(number-sequence 1 9)))) |
|
||||
:config (require 'exwm-randr) |
|
||||
(exwm-randr-enable) |
|
||||
(add-hook 'exwm-init-hook #'dotfiles/init-hook) |
|
||||
(add-hook 'exwm-randr-screen-change-hook #'dotfiles/update-display) |
|
||||
(add-hook 'exwm-update-class-hook (lambda () (exwm-workspace-rename-buffer exwm-class-name))) |
|
||||
(dotfiles/update-display) |
|
||||
(dotfiles/run-in-background "nitrogen --restore") ;; Update the wallpaper. |
|
||||
(dotfiles/run-in-background "xmodmap") ;; Rebind CTRL and CAPS. |
|
||||
(exwm-enable)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/ch11ng/exwm |
|
@ -1,123 +0,0 @@ |
|||||
#+TITLE: Fonts |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle fonts.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Unified system font across Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Install the required ~firacode~[fn:1] font before loading the module: |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y fonts-firacode |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Write out the value of ~dotfiles/font~ to all of the available font faces supported by Emacs. By default, this uses ~firacode~[fn:1] for its readability and ligature support. All of the heights are configured to ~dotfiles/font-size~ by default, with further configuration based on the given size possible. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(set-face-attribute 'default nil :font dotfiles/font :height dotfiles/font-size) |
|
||||
(set-face-attribute 'fixed-pitch nil :font dotfiles/font :height dotfiles/font-size) |
|
||||
(set-face-attribute 'variable-pitch nil :font dotfiles/font :height dotfiles/font-size) |
|
||||
#+end_src |
|
||||
|
|
||||
** Icons |
|
||||
|
|
||||
Emacs feels more modern with prioritized icon fonts, available in the ~all-the-icons~[fn:2] package. This makes navigation and visually parsing directories much faster, given that the file types are quickly identified by their corresponding icons. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package all-the-icons) |
|
||||
#+end_src |
|
||||
|
|
||||
Integration with the built-in ~dired~ package is available in the ~all-the-icons-dired~[fn:3] package. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package all-the-icons-dired |
|
||||
:hook (dired-mode . all-the-icons-dired-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Emojis |
|
||||
|
|
||||
It's finally here, first class support for Emojis in Emacs via the ~emacs-emojify~[fn:4] package. Have we finally gone too far? |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package emojify |
|
||||
:when (window-system) |
|
||||
:hook (after-init . global-emojify-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Scrolling |
|
||||
|
|
||||
Emacs' default scrolling behaviour is annoying. The sudden half-page jumps and the variable scroll-speed can be fixed with a few simple commands. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(setq scroll-conservatively 101 ;; Values >= 100 fix page jumping. |
|
||||
mouse-wheel-scroll-amount '(3 ((shift) . 3)) ;; Control the number of lines per jump. |
|
||||
mouse-wheel-progressive-speed t ;; Accelerate scrolling with the mouse wheel. |
|
||||
mouse-wheel-follow-mouse t) ;; Scroll the window under the mouse. |
|
||||
#+end_src |
|
||||
|
|
||||
** Ligatures |
|
||||
|
|
||||
Enable ~firacode~[fn:1] font ligatures with the ~fira-code-mode~[fn:5] package. Only perform this action when ~firacode~[fn:1] is the current font, and Emacs isn't running on the TTY. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package fira-code-mode |
|
||||
:when (and (window-system) |
|
||||
(equal dotfiles/font "Fira Code")) |
|
||||
:hook (prog-mode org-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Parenthesis |
|
||||
|
|
||||
Colourize nested parenthesis with ~rainbow-delimeters~[fn:4], a mandatory life-jacked to keep you from drowning in the sea of them in Lisp. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package rainbow-delimiters |
|
||||
:hook (prog-mode . rainbow-delimiters-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Text scaling |
|
||||
|
|
||||
Define a transient keybinding for scaling the text. One caveat to this, it only works when Emacs is running as a GUI application, and has no effect in the terminal. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defhydra hydra-text-scale (:timeout 4) |
|
||||
"Scale" |
|
||||
("j" text-scale-increase "Increase") |
|
||||
("k" text-scale-decrease "Decrease") |
|
||||
("f" nil "Finished" :exit t)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Scale the text inside of buffers using the custom transient binding, behind =SPC t f=: |
|
||||
|
|
||||
+ Increase with =j= |
|
||||
+ Decrease with =k= |
|
||||
+ Finish with =f= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"tf" '(hydra-text-scale/body :which-key "Font")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/tonsky/FiraCode |
|
||||
|
|
||||
[fn:2] [[https://github.com/domtronn/all-the-icons.el]] |
|
||||
|
|
||||
[fn:3] https://github.com/jtbm37/all-the-icons-dired |
|
||||
|
|
||||
[fn:4] https://github.com/Fanael/rainbow-delimiters |
|
||||
|
|
||||
[fn:5] https://github.com/jming422/fira-code-mode |
|
@ -1,75 +0,0 @@ |
|||||
#+TITLE: Go |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle go.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software[fn:1] |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Install ~golang~[fn:1] on your system, and configure your environment prior to loading this module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y golang |
|
||||
#+end_src |
|
||||
|
|
||||
** Language server |
|
||||
|
|
||||
Get started by installing the ~gopls~[fn:2] language server. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
GO111MODULE=on go get golang.org/x/tools/gopls@latest |
|
||||
#+end_src |
|
||||
|
|
||||
** Setup the environment |
|
||||
|
|
||||
Make some modifications to the environment. Set the =$GOPATH= variable prior to loading, allowing modification of the default value. Include the =bin= subdirectory of the =$GOPATH= in the =$PATH= variable, adding compiled golang applications to the system path. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(setenv "GOPATH" (concat (getenv "HOME") "/.go/")) |
|
||||
(setenv "PATH" (concat (getenv "GOPATH") "bin:" (getenv "PATH"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Use the ~go-mode~[fn:3] package for integration with ~lsp-mode~, manually setting the path to ~gopls~[fn:2] before loading. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package go-mode |
|
||||
:hook (go-mode . lsp) |
|
||||
:custom (lsp-go-gopls-server-path "~/.go/bin/gopls")) |
|
||||
#+end_src |
|
||||
|
|
||||
** Before save hooks |
|
||||
|
|
||||
Apply some custom behaviour when saving ~golang~[fn:1] buffers. Format and organize the imports before saving. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/go-hook () |
|
||||
(add-hook 'before-save-hook #'lsp-format-buffer t t) |
|
||||
(add-hook 'before-save-hook #'lsp-organize-imports t t)) |
|
||||
|
|
||||
(add-hook 'go-mode-hook #'dotfiles/go-hook) |
|
||||
#+end_src |
|
||||
|
|
||||
** Babel structure templates |
|
||||
|
|
||||
Configure the ~babel~ engine to support ~golang~[fn:1] source blocks. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(add-to-list 'org-structure-template-alist '("go" . "src go")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://golang.org |
|
||||
|
|
||||
[fn:2] https://pkg.go.dev/golang.org/x/tools/gopls |
|
||||
|
|
||||
[fn:3] https://emacswiki.org/emacs/GoMode |
|
@ -1,68 +0,0 @@ |
|||||
#+TITLE: GPG |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle gpg.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 GPG[fn:1] pinentry within Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
:PROPERTIES: |
|
||||
:header-args: :tangle ../config/gpg-agent.conf |
|
||||
:END: |
|
||||
|
|
||||
When the ~gpg-agent~[fn:1] loads it will read the configuration at =~/.gnupg/gpg-agent.conf=. Override the default settings to allow Emacs to function as the Pinentry application. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
allow-emacs-pinentry |
|
||||
allow-loopback-pinentry |
|
||||
#+end_src |
|
||||
|
|
||||
You may need to restart the ~gpg-agent~[fn:1] to load the configuration without rebooting. |
|
||||
|
|
||||
#+begin_src shell :tangle nil |
|
||||
gpgconf --reload gpg-agent |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Create the symbolic link to the configuration file. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/gpg-agent.conf" |
|
||||
"~/.gnupg/gpg-agent.conf") |
|
||||
#+end_src |
|
||||
|
|
||||
With the ~pinentry~[fn:2] package for Emacs prompts will now appear in the minibuffer. Increase the minimum prime bit size to increase performance during symmetric encryption. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package pinentry |
|
||||
:custom (epa-file-select-keys 2) |
|
||||
(gnutls-min-prime-bits 4096) |
|
||||
(epa-pinentry-mode 'loopback) |
|
||||
(epa-file-encrypt-to dotfiles/public-key) |
|
||||
(epa-file-cache-passphrase-for-symmetric-encryption t) |
|
||||
:config (pinentry-start)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Including agenda files |
|
||||
|
|
||||
Override ~org-agenda-file-regexp~ to include =.org.gpg= files. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(unless (string-match-p "\\.gpg" org-agenda-file-regexp) |
|
||||
(setq org-agenda-file-regexp |
|
||||
(replace-regexp-in-string "\\\\\\.org" "\\\\.org\\\\(\\\\.gpg\\\\)?" |
|
||||
org-agenda-file-regexp))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://gnupg.org |
|
||||
|
|
||||
[fn:2] https://elpa.gnu.org/packages/pinentry.html |
|
@ -1,30 +0,0 @@ |
|||||
#+TITLE: Grammar |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle grammar.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 |
|
||||
|
|
||||
Real time checking and one-shot methods to check and correct common grammatical errors. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Use ~writegood-mode~ to find common writing problems such as cliches, and poor wording. Grammarly for the peons! |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package writegood-mode |
|
||||
:after org |
|
||||
:config (writegood-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Toggle ~writegood-mode~ with =SPC t w=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"tw" '(writegood-mode :which-key "Grammar")) |
|
||||
#+end_src |
|
@ -1,100 +0,0 @@ |
|||||
#+TITLE: Hugo |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle hugo.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 |
|
||||
|
|
||||
Create entire websites with Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Download and install ~hugo~[fn:1] on your system before loading the module: |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y hugo |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
It's possible to export ~org-mode~ into ~hugo~[fn:1] specific markdown[fn:2] using the ~ox-hugo~[fn:3] package. I have my setup configured for one-post-per-file, despite it not being the suggested method. The option will appear in the default export menu inside of an ~org-mode~ buffer, accessible by pressing =C-c C-e=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ox-hugo |
|
||||
:after ox) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Create capture templates for creating new blog posts, and creating publicly shared notes on various topics, and other peoples published works. |
|
||||
|
|
||||
** Posts |
|
||||
|
|
||||
I post nonsense on my personal blog, available here[fn:4]. This template makes sure the file ends up going to the right location, with the configuration pre-applied. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(add-to-list 'org-roam-capture-templates |
|
||||
'("p" "Post" plain (function org-roam-capture--get-point) |
|
||||
"%?" |
|
||||
:file-name "docs/posts/${slug}" |
|
||||
:unnarrowed t |
|
||||
:head |
|
||||
" |
|
||||
,#+TITLE: ${title} |
|
||||
,#+AUTHOR: Christopher James Hayward |
|
||||
,#+DATE: %<%Y-%m-%d> |
|
||||
|
|
||||
,#+OPTIONS: num:nil todo:nil tasks:nil |
|
||||
|
|
||||
,#+EXPORT_FILE_NAME: ${slug} |
|
||||
,#+ROAM_KEY: https://chrishayward.xyz/posts/${slug}/ |
|
||||
|
|
||||
,#+HUGO_BASE_DIR: ../ |
|
||||
,#+HUGO_AUTO_SET_LASTMOD: t |
|
||||
,#+HUGO_SECTION: posts |
|
||||
,#+HUGO_DRAFT: true |
|
||||
"))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Notes |
|
||||
|
|
||||
Read my notes on various textbooks, artciles, and other un-categorized nonsense here[fn:5]. This template makes sure the file ends up going to the right location, with the configuration pre-applied. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(add-to-list 'org-roam-capture-templates |
|
||||
'("n" "Notes" plain (function org-roam-capture--get-point) |
|
||||
"%?" |
|
||||
:file-name "docs/notes/${slug}" |
|
||||
:unnarrowed t |
|
||||
:head |
|
||||
" |
|
||||
,#+TITLE: ${title} |
|
||||
,#+AUTHOR: Christopher James Hayward |
|
||||
|
|
||||
,#+OPTIONS: num:nil todo:nil tasks:nil |
|
||||
,#+EXPORT_FILE_NAME: ${slug} |
|
||||
,#+ROAM_KEY: https://chrishayward.xyz/notes/${slug}/ |
|
||||
|
|
||||
,#+HUGO_BASE_DIR: ../ |
|
||||
,#+HUGO_AUTO_SET_LASTMOD: t |
|
||||
,#+HUGO_SECTION: notes |
|
||||
,#+HUGO_DRAFT: true |
|
||||
"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://gohugo.io |
|
||||
|
|
||||
[fn:2] https://markdownguide.org/tools/hugo |
|
||||
|
|
||||
[fn:3] https://github.com/kaushalmodi/ox-hugo |
|
||||
|
|
||||
[fn:4] https://chrishayward.xyz/posts/ |
|
||||
|
|
||||
[fn:5] https://chrishayward.xyz/notes/ |
|
@ -1,80 +0,0 @@ |
|||||
#+TITLE: Ivy |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle ivy.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Bring Emacs out of the eighties. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
There's a lot of occasions where Emacs asks you to input text to match a file name in a directory, or of a potential buffer selection. The family of packages ~ivy/swiper~[fn:1] work together toward this common goal of improving the default completion menu system. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ivy |
|
||||
:diminish |
|
||||
:config (ivy-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Replacements |
|
||||
|
|
||||
Include ~counsel~[fn:2], a customized set of commands to replace the built-in completion buffers. This will provide an experience similar to what you've maybe experienced on ~doom~ or ~spacemacs~. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package counsel |
|
||||
:after ivy |
|
||||
:custom (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only) |
|
||||
:config (counsel-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Additional details |
|
||||
|
|
||||
Provide more information about each item in the completion menu with ~ivy-rich~[fn:3]. This will include snippets from any available documentation, or active buffers. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ivy-rich |
|
||||
:after counsel |
|
||||
:init (ivy-rich-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Popup selection frame |
|
||||
|
|
||||
Display ~ivy~[fn:1] completions in a popup buffer with the ~ivy-posframe~[fn:4] package. I prefer to use this since the menu appears in the center of my screen, stopping my from having to tilt my head to look down at the default completion menu appearing in the mini-buffer. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ivy-posframe |
|
||||
:after ivy |
|
||||
:when (window-system) |
|
||||
:custom (ivy-posframe-display-functions-alist '((t . ivy-posframe-display))) |
|
||||
(ivy-posframe-parameters '((parent-frame nil))) |
|
||||
:config (ivy-posframe-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Candidate selection sorting |
|
||||
|
|
||||
Sort completion candidates based on how recently or frequently they're selected with ~prescient.el~[fn:5]. This can be helpful when using =M-x= to run commands that aren't bound to specific key-strokes. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ivy-prescient |
|
||||
:after counsel |
|
||||
:custom (ivy-prescient-enable-filtering nil) |
|
||||
:config (prescient-persist-mode 1) |
|
||||
(ivy-prescient-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/abo-abo/swiper |
|
||||
|
|
||||
[fn:2] https://libraries.io/emacs/counsel |
|
||||
|
|
||||
[fn:3] https://github.com/Yevgnen/ivy-rich |
|
||||
|
|
||||
[fn:4] https://github.com/tumashu/ivy-posframe |
|
||||
|
|
||||
[fn:5] https://github.com/raxod502/prescient.el |
|
@ -1,137 +0,0 @@ |
|||||
#+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)= |
|
||||
+ Kill buffers with =SPC / (slash)= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"." '(find-file :which-key "Files") |
|
||||
"," '(switch-to-buffer :which-key "Buffers") |
|
||||
"c" '(kill-buffer-and-window :which-key "Close")) |
|
||||
#+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 |
|
||||
|
|
||||
** Managing windows |
|
||||
|
|
||||
Screen space is divided into Frames inside of Emacs, manage them behind =SPC w=: |
|
||||
|
|
||||
+ Swap with =w= |
|
||||
+ Close with =c= |
|
||||
+ Delete with =d= |
|
||||
+ 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 |
|
||||
|
|
||||
** 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 |
|
@ -1,76 +0,0 @@ |
|||||
#+TITLE: Language Server Protocol |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle lsp.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
The Language Server Protocol (LSP) defines the protocol used between an editor, or IDE, and a language server that provides language features like auto-complete, go-to-definition, find-all-references, etc[fn:1] |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Support for the Language Server Protocol[fn:1] is available through the ~lsp-mode~[fn:2] package. Configure an immutable delay of =.5= to ensure it doesn't attack the current language server and overload it with requests. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package lsp-mode |
|
||||
:commands (lsp lsp-deferred) |
|
||||
:custom (lsp-idle-delay 0.5) |
|
||||
(lsp-prefer-flymake t)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Code snippets |
|
||||
|
|
||||
Download ~yasnippet~[fn:4], used by a number of ~lsp-mode~[fn:2] extensions to provide smart completion functionality. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package yasnippet |
|
||||
:ensure t) |
|
||||
#+end_src |
|
||||
|
|
||||
** UI integration |
|
||||
|
|
||||
Download ~lsp-ui~[fn:3] to provide user interface improvements for ~lsp-mode~[fn:2] over the defaults. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package lsp-ui |
|
||||
:after lsp |
|
||||
:custom (lsp-ui-doc-position 'at-point) |
|
||||
(lsp-ui-doc-delay 0.500)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Code completion |
|
||||
|
|
||||
Text completion provided by ~company~[fn:5], AKA Complete Anything. Make sure it's integrated with ~lsp-mode~[fn:2] to provide completion candidates through the Language Server Protocol[fn:1]. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package company |
|
||||
:after lsp) |
|
||||
#+end_src |
|
||||
|
|
||||
Specify the repository for ~company-lsp~ using straight to make sure we're getting the most recent version from GitHub, instead of the typically outdated versions in the Emacs package repositories. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package company-lsp |
|
||||
:after (lsp company) |
|
||||
:custom (company-lsp-async t) |
|
||||
(company-backend 'company-lsp) |
|
||||
:straight (company-lsp :type git |
|
||||
:host github |
|
||||
:repo "tigersoldier/company-lsp")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://microsoft.github.io/language-server-protocol/ |
|
||||
|
|
||||
[fn:2] https://emacs-lsp.github.io/lsp-mode/ |
|
||||
|
|
||||
[fn:3] https://emacs-lsp.github.io/lsp-ui/ |
|
||||
|
|
||||
[fn:4] https://github.com/joaotavora/yasnippet |
|
||||
|
|
||||
[fn:5] https://company-mode.github.io/ |
|
@ -1,62 +0,0 @@ |
|||||
#+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 |
|
@ -1,19 +0,0 @@ |
|||||
#+TITLE: Modeline |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
Extend the usability of the Emacs modeline. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Implement and elegant and modern status bar, fully customizable and compatible with our themes with the ~doom-modeline~[fn:1] package. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package doom-modeline |
|
||||
:custom (doom-modeline-height 16) |
|
||||
:config (doom-modeline-mode 1)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/seagle0128/doom-modeline |
|
@ -1,150 +0,0 @@ |
|||||
#+TITLE: Mu4e |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle mu4e.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Plain-text email inside of Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Make sure the following dependencies are installed on your system before loading the module. I would recommend against using any distributions pre-packaged version of ~mu4e~[fn:1], and instead build it yourself which I detail in this post[fn:2]: |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y isync libgmime-3.0-dev libxapian-dev |
|
||||
#+end_src |
|
||||
|
|
||||
** Setting up mbsync |
|
||||
:PROPERTIES: |
|
||||
:header-args: :tangle ../config/mbsyncrc :comments org |
|
||||
:END: |
|
||||
|
|
||||
The program that actually synchronizes the emails with the server is ~mbsync~[fn:3]. Create the configuration file, this is for my personal mail server[fn:4], which I host myself, so make sure you write your own. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
IMAPStore xyz-remote |
|
||||
Host mail.chrishayward.xyz |
|
||||
User chris@chrishayward.xyz |
|
||||
PassCmd "pass chrishayward.xyz/chris" |
|
||||
SSLType IMAPS |
|
||||
|
|
||||
MaildirStore xyz-local |
|
||||
Path ~/.cache/mail/ |
|
||||
Inbox ~/.cache/mail/inbox |
|
||||
SubFolders Verbatim |
|
||||
|
|
||||
Channel xyz |
|
||||
Master :xyz-remote: |
|
||||
Slave :xyz-local: |
|
||||
Patterns * !Archives |
|
||||
Create Both |
|
||||
Expunge Both |
|
||||
SyncState * |
|
||||
#+end_src |
|
||||
|
|
||||
** Create symbolic links |
|
||||
|
|
||||
The system typically expects to find this file at =$HOME/.mbsyncrc=, but you may also specify a custom path if launching the command using arguments. I chose to symlink the default location to my repository. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/mbsyncrc" |
|
||||
"~/.mbsyncrc") |
|
||||
#+end_src |
|
||||
|
|
||||
This repository also contains my personal encrypted auth info, this is required by ~mbsync~[fn:3] to sign all of the outbound messages. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/authinfo.gpg" |
|
||||
"~/.authinfo.gpg") |
|
||||
#+end_src |
|
||||
|
|
||||
** First time indexing |
|
||||
|
|
||||
Before you can use ~mu4e~[fn:1] inside of Emacs, you need to synchronize the mail database, and index it using ~mu~[fn:5], the library used by ~mu4e~[fn:1] under the hood. Execute these commands in your terminal before loading the module, after that you can do everything inside of Emacs: |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN mbsync -a |
|
||||
RUN mu init --maildir="~/.cache/mail" --my-address="chris@chrishayward.xyz" |
|
||||
RUN mu index |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
After syncing and indexing, the mail is ready for Emacs. Include ~mu4e~[fn:1] in the configuration by adding the custom built version to the load path, and configure the mail account. |
|
||||
|
|
||||
+ Update every 5 minutes |
|
||||
+ Configure mail account(s) |
|
||||
+ Scale text for all devices |
|
||||
+ Sign outbound mail with GPG key |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package mu4e |
|
||||
:load-path "~/.local/source/mu/mu4e/" |
|
||||
:custom (mu4e-maildir "~/.cache/mail") |
|
||||
(mu4e-update-interval (* 5 60)) |
|
||||
(mu4e-get-mail-command "mbsync -a") |
|
||||
(mu4e-compose-format-flowed t) |
|
||||
(mu4e-change-filenames-when-moving t) |
|
||||
(message-send-mail-function 'smtpmail-send-it) |
|
||||
(mml-secure-openpgp-signers '("37AB1CB72B741E478CA026D43025DCBD46F81C0F")) |
|
||||
(mu4e-compose-signature (concat "Chris Hayward\n" |
|
||||
"https://chrishayward.xyz\n")) |
|
||||
:config |
|
||||
(add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime) |
|
||||
(setq mu4e-contexts |
|
||||
(list |
|
||||
;; Main |
|
||||
;; chris@chrishayward.xyz |
|
||||
(make-mu4e-context |
|
||||
:name "Main" |
|
||||
:match-func |
|
||||
(lambda (msg) |
|
||||
(when msg |
|
||||
(string-prefix-p "/Main" (mu4e-message-field msg :maildir)))) |
|
||||
:vars |
|
||||
'((user-full-name . "Christopher James Hayward") |
|
||||
(user-mail-address . "chris@chrishayward.xyz") |
|
||||
(smtpmail-smtp-server . "mail.chrishayward.xyz") |
|
||||
(smtpmail-smtp-service . 587) |
|
||||
(smtpmail-stream-type . starttls)))))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Desktop notifications |
|
||||
|
|
||||
Receive desktop notifications when new mail arrives with the ~mu4e-alert~[fn:6] package. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package mu4e-alert |
|
||||
:after mu4e |
|
||||
:custom (mu4e-alert-set-default-style 'libnotify) |
|
||||
:config (mu4e-alert-enable-notifications) |
|
||||
(mu4e-alert-enable-mode-line-display)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Open the ~mu4e~[fn:1] dashboard with =SPC m=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"m" '(mu4e :which-key "Mu4e")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://emacswiki.org/emacs/mu4e |
|
||||
|
|
||||
[fn:2] https://chrishayward.xyz/posts/installing-mu-mu4e-from-source/ |
|
||||
|
|
||||
[fn:3] https://isync.sourceforge.io |
|
||||
|
|
||||
[fn:4] mailto:chris@chrishayward.xyz |
|
||||
|
|
||||
[fn:5] https://codewith.mu/en/download |
|
||||
|
|
||||
[fn:6] https://github.com/iqbalansari/mu4e-alert |
|
@ -1,27 +0,0 @@ |
|||||
#+TITLE: Nix |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle nix.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 emacs:nil creator:nil timestamp:nil |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
*Nix*[fn:1] is a package manager for Linux that uses functional configuration language to build reproducible package deployments. *NixOS*[fn:2] is an extension of the Nix package manager to the entire operating system. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Download and install ~nix-mode~ for working with *Nix* language buffers. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package nix-mode) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://nixos.org |
|
||||
|
|
||||
[fn:2] https://nixos.org |
|
@ -1,160 +0,0 @@ |
|||||
#+TITLE: Org |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle org.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 |
|
||||
|
|
||||
Organize your plain-life in plain-text. The hallmark feature of Emacs, ~org-mode~[fn:1] is the king of markup languages. It has rich feature support for project management, scheduling, development, and writing. It's hard to convey everything within its capabilities. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Define a custom hook when ~org-mode~[fn:1] is enabled to customize the experience: |
|
||||
|
|
||||
+ Enable ~org-indent-mode~ to indent and align text with the parent heading |
|
||||
+ Enable ~visual-line-mode~ to allow text to overflow and wrap to the next visual line |
|
||||
+ Enable ~variable-pitch-mode~ to support multiple font-pitches and monospaced fonts |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/org-mode-hook () |
|
||||
(org-indent-mode) ;; Indent and align text. |
|
||||
(visual-line-mode 1) ;; Allow text to overflow line. |
|
||||
(variable-pitch-mode 1)) ;; Enable monospaced fonts. |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Force ~straight~ to ignore the local version of ~org-mode~[fn:1], instead downloading the most recent version available. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(straight-use-package '(org :local-repo nil)) |
|
||||
#+end_src |
|
||||
|
|
||||
Setup the default babel languages and structure templates, and apply customizations: |
|
||||
|
|
||||
+ Setup ~org-mode-hook~ with our custom hook |
|
||||
+ Setup ~org-ellipsis~ to show headlines with hidden contents |
|
||||
+ Setup ~org-log-*~ for event logging |
|
||||
+ Setup ~org-src-*~ for source blocks |
|
||||
+ Setup ~org-todo-keyword~ sequence |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package org |
|
||||
:hook (org-mode . dotfiles/org-mode-hook) |
|
||||
:custom (org-ellipsis " ▾") |
|
||||
(org-log-done 'time) |
|
||||
(org-log-into-drawer t) |
|
||||
(org-return-follows-link t) |
|
||||
(org-image-actual-width nil) |
|
||||
(org-directory dotfiles/home) |
|
||||
(org-src-fontify-natively t) |
|
||||
(org-src-tab-acts-natively t) |
|
||||
(org-src-preserve-indentation t) |
|
||||
(org-confirm-babel-evaluate nil) |
|
||||
(org-todo-keywords '((sequence "TODO" "START" "WAIT" "DONE"))) |
|
||||
:config (require 'org-tempo) ;; Required for structure templates. |
|
||||
(add-to-list 'org-structure-template-alist '("s" . "src")) |
|
||||
(add-to-list 'org-structure-template-alist '("q" . "quote")) |
|
||||
(add-to-list 'org-structure-template-alist '("e" . "example")) |
|
||||
(add-to-list 'org-structure-template-alist '("sh" . "src shell")) |
|
||||
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) |
|
||||
(org-babel-do-load-languages 'org-babel-load-languages '((shell . t) |
|
||||
(emacs-lisp . t)))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Pomodoro |
|
||||
|
|
||||
Adds support for the Pomodoro workflow in Emacs through the ~org-pomodoro~[fn:4] package. Some workflows benefit from thje option to work a few minutes of *overtime* to finish a task before taking a break. With this workflow, a break notification is sent at the end of the pomodoro timer, but the break starts when calling =M-x org-pomodoro=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package org-pomodoro |
|
||||
:after org |
|
||||
:custom (org-pomodoro-manual-break t) ;; Enable the 'overtime' workflow. |
|
||||
(org-pomodoro-keep-killed-time t)) ;; Track abandoned timers. |
|
||||
#+end_src |
|
||||
|
|
||||
** Flashcards |
|
||||
|
|
||||
Create study flashcards using ~org-drill~[fn:2], an extension for ~org-mode~. It uses a spaced repititon algorithm to conduct interactive drill sesslions using ~org-mode~ buffers as sources of facts to be memorized. Each drill can be restricted to topics in the current buffer, one of several, all agenda files, or a single topic across all buffers. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package org-drill |
|
||||
:after org) |
|
||||
#+end_src |
|
||||
|
|
||||
** Headline stars |
|
||||
|
|
||||
Make the headline stars a bit more *super* with ~org-superstar-mode~[fn:3]. Only enable this inside of a window system, as the effect can be distracting on the TTY. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package org-superstar |
|
||||
:when (window-system) |
|
||||
:after org |
|
||||
:hook (org-mode . org-superstar-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Methods |
|
||||
|
|
||||
Define some custom methods for use in the rest of the configuration. |
|
||||
|
|
||||
** Tangle directory |
|
||||
|
|
||||
Build all of the ~org~ files within a given directory, recursively. This is used in CI. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/tangle (dir) |
|
||||
"Recursively tangle the Org files within a directory." |
|
||||
(interactive) |
|
||||
(let ((org-files (directory-files-recursively dir "org"))) |
|
||||
(dolist (f org-files) |
|
||||
(org-babel-tangle-file f)))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Force symbolic links |
|
||||
|
|
||||
Function that takes in a system and configuration file path, checks to see if the system file doesn't exist, or doesn't point to the configuration file, deleting it for the latter, then creating a symbolic link to the configuration file in place. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/symlink (src tgt) |
|
||||
"Forces a symlink from `src' to `tgt'." |
|
||||
(interactive) |
|
||||
(let ((sys-file (expand-file-name tgt)) |
|
||||
(dot-file (expand-file-name src))) |
|
||||
(when (or (not (file-exists-p sys-file)) |
|
||||
(not (equal (file-symlink-p sys-file) dot-file))) |
|
||||
(delete-file sys-file) |
|
||||
(make-symbolic-link dot-file sys-file)))) |
|
||||
#+end_src |
|
||||
|
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Place ~org-mode~[fn:1] extension bindings behind =SPC o=. |
|
||||
|
|
||||
+ Drill with =d= |
|
||||
+ Drill with =d= |
|
||||
+ Resume with =r= |
|
||||
+ Pomodoro with =p= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"o" '(:ignore t :which-key "Org") |
|
||||
"od" '(:ignore t :which-key "Drill") |
|
||||
"odd" '(org-drill :which-key "Drill") |
|
||||
"odc" '(org-drill-cram :which-key "Cram") |
|
||||
"odr" '(org-drill-resume :which-key "Resume") |
|
||||
"op" '(org-pomodoro :which-key "Pomodoro")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://orgmode.org |
|
||||
|
|
||||
[fn:2] https://orgmode.org/worg/org-contrib/org-drill.html |
|
||||
|
|
||||
[fn:3] https://github.com/integral-dw/org-superstar-mode |
|
||||
|
|
||||
[fn:4] https://github.com/marcinkoziej/org-pomodoro |
|
@ -1,51 +0,0 @@ |
|||||
#+TITLE: Pass |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle pass.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Password management inside of Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Install ~pass~[fn:1] on the system before loading the module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y pass |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Encrypted passwords are stored inside files, in a file structure providing easy commands for generating, modifying, and copying passwords. ~password-store.el~[fn:2] provides a wrapper for the functionality within Emacs. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package password-store |
|
||||
:custom (password-store-dir dotfiles/passwords)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Configure keybindings behind =SPC p=: |
|
||||
|
|
||||
+ Copy with =p= |
|
||||
+ Rename with =r= |
|
||||
+ Generate with =g= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"p" '(:ignore t :which-key "Passwords") |
|
||||
"pp" '(password-store-copy :which-key "Copy") |
|
||||
"pr" '(password-store-rename :which-key "Rename") |
|
||||
"pg" '(password-store-generate :which-key "Generate")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://passwordstore.org |
|
||||
|
|
||||
[fn:2] https://github.com/NicolasPetton/pass |
|
@ -1,136 +0,0 @@ |
|||||
#+TITLE: Projects |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle projects.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
#+ATTR_ORG: :width 420px |
|
||||
#+ATTR_HTML: :width 420px |
|
||||
#+ATTR_LATEX: :width 420px |
|
||||
[[../docs/images/2021-02-13-example-ccls.gif]] |
|
||||
|
|
||||
An *IDE*[fn:1] like experience or better can be achieved within Emacs using two *Microsoft*[fn:2] open-source initiatives: |
|
||||
|
|
||||
+ *Debug Adapter Protocol*[fn:3] |
|
||||
+ *Language Server Protocol*[fn:4] |
|
||||
|
|
||||
* Code snippets |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package yasnippet |
|
||||
:ensure t) |
|
||||
#+end_src |
|
||||
|
|
||||
* Debug adapters |
|
||||
|
|
||||
*Dap mode*[fn:5] provides support for the *Debug Adapter Protocol*[fn:3] inside of Emacs. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package dap-mode |
|
||||
:commands (dap-debug)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Language servers |
|
||||
|
|
||||
Support for the *Language Server Protocol*[fn:4] is added to Emacs through the *Lsp mode*[fn:6] package. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package lsp-mode |
|
||||
:commands (lsp lsp-deferred) |
|
||||
:custom (lsp-idle-delay (* 5 dotfiles/idle)) |
|
||||
(lsp-prefer-flymake t)) |
|
||||
#+end_src |
|
||||
|
|
||||
** UI integration |
|
||||
|
|
||||
*Lsp ui*[fn:7] provides user interface improvements for *Lsp mode*[fn:6]. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package lsp-ui |
|
||||
:after lsp |
|
||||
:custom (lsp-ui-doc-position 'at-point) |
|
||||
(lsp-ui-doc-delay 0.500)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Code completion |
|
||||
|
|
||||
Text completion via *Company*[fn:8] =AKA= *Complete Anything*. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package company |
|
||||
:after lsp) |
|
||||
#+end_src |
|
||||
|
|
||||
Integrate with *Lsp mode*[fn:6] to provide completion candidates through the *Language Server Protocol*[fn:4]. |
|
||||
|
|
||||
+ Specify the repository |
|
||||
+ Use asynchronous completion |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package company-lsp |
|
||||
:after (lsp company) |
|
||||
:custom (company-lsp-async t) |
|
||||
(company-backend 'company-lsp) |
|
||||
:straight (company-lsp :type git |
|
||||
:host github |
|
||||
:repo "tigersoldier/company-lsp")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Docker containers |
|
||||
|
|
||||
Manage *Docker*[fn:9] containers with *Docker.el*[fn:10]. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package docker |
|
||||
:commands (docker)) |
|
||||
#+end_src |
|
||||
|
|
||||
Open the container management screen with =SPC k=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"k" '(docker :which-key "Docker")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Project management |
|
||||
|
|
||||
Configure *Projectile*[fn:11], a project interaction library for Emacs. It provides a nice set of features for operating on a project level without introducing external dependencies. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package projectile |
|
||||
:custom (projectile-project-search-path '("~/.local/source")) |
|
||||
:config (projectile-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://en.wikipedia.org/wiki/Integrated_development_environment |
|
||||
|
|
||||
[fn:2] https://en.wikipedia.org/wiki/Microsoft_and_open_source |
|
||||
|
|
||||
[fn:3] https://microsoft.github.io/debug-adapter-protocol |
|
||||
|
|
||||
[fn:4] https://microsoft.github.io/language-server-protocol |
|
||||
|
|
||||
[fn:5] https://emacs-lsp.github.io/dap-mode/ |
|
||||
|
|
||||
[fn:6] https://emacs-lsp.github.io/lsp-mode/ |
|
||||
|
|
||||
[fn:7] https://emacs-lsp.github.io/lsp-ui/ |
|
||||
|
|
||||
[fn:8] https://company-mode.github.io/ |
|
||||
|
|
||||
[fn:9] https://docker.com |
|
||||
|
|
||||
[fn:10] https://github.com/Silex/docker.el |
|
||||
|
|
||||
[fn:11] https://projectile.mx |
|
||||
|
|
||||
[fn:12] https://git.zx2c4.com/password-store/tree/contrib/emacs |
|
||||
|
|
||||
[fn:13] https://passwordstore.org |
|
@ -1,67 +0,0 @@ |
|||||
#+TITLE: Python |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle python.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Python is an interpreted high-level general-purpose programming language[fn:1]. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Ensure ~python3~[fn:1] is installed on the system, and the ~lsp~ and ~dap~ modules have been loaded before loading this module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y python3 python3-pip |
|
||||
#+end_src |
|
||||
|
|
||||
** Install the language server |
|
||||
|
|
||||
Install the ~pyls~[fn:2] language server. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN pip3 install --user "python-lsp-server[all]" |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Add support for ~python3~[fn:1], including ~dap~ and ~lsp~ integration. The built-in Emacs mode ~python-mode~[fn:3] handles the rest of the integration. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package python-mode |
|
||||
:hook (python-mode . lsp-deferred) |
|
||||
:config (require 'dap-python) |
|
||||
(add-to-list 'org-src-lang-modes '("python" . python)) |
|
||||
(add-to-list 'org-structure-template-alist '("py" . "src python")) |
|
||||
(org-babel-do-load-languages 'org-babel-load-languages '((python . t))) |
|
||||
:custom (python-shell-interpreter "python3") ;; Required if "python" is not python 3. |
|
||||
(org-babel-python-command "python3") ;; Same as above. |
|
||||
(dap-python-executable "python3") ;; Same as above. |
|
||||
(lsp-pyls-server-command "pylsp") |
|
||||
(dap-python-debugger 'debugpy)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Code symbols |
|
||||
|
|
||||
Programming buffers can be made prettier with ~pretty-mode~[fn:4], this is complimentary to ~prettify-symbols-mode~[fn:5], a built-in package containing similar (but lacking) functionality. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package pretty-mode |
|
||||
:hook (python-mode . turn-on-pretty-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://python.org |
|
||||
|
|
||||
[fn:2] https://pypi.org/project/python-language-server/ |
|
||||
|
|
||||
[fn:3] https://emacswiki.org/emacs/PythonProgrammingInEmacs |
|
||||
|
|
||||
[fn:4] https://emacswiki.org/emacs/pretty-mode.el |
|
||||
|
|
||||
[fn:5] https://emacswiki.org/emacs/PrettySymbol |
|
@ -1,55 +0,0 @@ |
|||||
#+TITLE: Reveal |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle reveal.el :comments org |
|
||||
#+PROPERTY: header-args :results silent :eval no-export |
|
||||
|
|
||||
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
|
||||
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
|
||||
|
|
||||
Create high-quality, portably presentations with ~reveal.js~[fn:1]. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Integrate ~reveal.js~[fn:1] with Emacs using the ~ox-reveal~[fn:2] package. Configure it to use a CDN to produce presentations that are not dependent on any locally installed software. An important caveat here is that the paths to images must be absolute URLs. I get around this by hosting all of the images myself, meaning I can load the presentations in any web browser. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ox-reveal |
|
||||
:after ox |
|
||||
:custom (org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Add a capture tempalte for quickly creating slide presentations with the desired markup and configuration already applied. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(add-to-list 'org-roam-capture-templates |
|
||||
'("s" "Slides" plain (function org-roam-capture--get-point) |
|
||||
"%?" |
|
||||
:file-name "docs/slides/${slug}" |
|
||||
:unnarrowed t |
|
||||
:head |
|
||||
" |
|
||||
,#+TITLE: ${title} |
|
||||
,#+AUTHOR: Christopher James Hayward |
|
||||
,#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
,#+REVEAL_ROOT: https://cdn.jsdelivr.net/npm/reveal.js |
|
||||
,#+REVEAL_THEME: serif |
|
||||
|
|
||||
,#+EXPORT_FILE_NAME: ${slug} |
|
||||
|
|
||||
,#+OPTIONS: reveal_title_slide:nil |
|
||||
,#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
|
||||
,#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
|
||||
"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://revealjs.com |
|
||||
|
|
||||
[fn:2] https://github.com/hexmode/ox-reveal |
|
@ -1,175 +0,0 @@ |
|||||
#+TITLE: Roam |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle roam.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 |
|
||||
|
|
||||
Plain-text knowledge management system. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Make sure ~sqlite~ is available on your system: |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install sqlite |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Configure ~org-roam~[fn:1], a plain-text knowledge management system for Emacs built on top of ~org-mode~. Here's a quick recap of the main principles: |
|
||||
|
|
||||
+ Notes can be arbitrarily referened |
|
||||
+ Contexts created by linking topics and notes |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package org-roam |
|
||||
:hook (after-init . org-roam-mode) ;; Lauch roam at startup, big performance cost. |
|
||||
:custom (org-roam-encrypt-files t) ;; Encrypt all roam captures. |
|
||||
(org-roam-directory org-directory) |
|
||||
(org-roam-capture-templates '()) |
|
||||
(org-roam-dailies-capture-templates '())) |
|
||||
#+end_src |
|
||||
|
|
||||
** Files |
|
||||
|
|
||||
The default behaviour of ~org-roam~[fn:1] when creating a title slug is to replace any non alpha numerical (whitespace) to ~_~. I wanted to change this to use ~_~ and have done so here in my own definition. The only substantial difference from the original definition is the character used. |
|
||||
|
|
||||
+ Define a new ~title-to-slug~ function |
|
||||
+ Override ~org-roam-title-to-slug-function~ |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(require 'cl-lib) |
|
||||
(defun dotfiles/title-to-slug (title) |
|
||||
"Convert TITLE to a filename-suitable slug." |
|
||||
(cl-flet* ((nonspacing-mark-p (char) |
|
||||
(eq 'Mn (get-char-code-property char 'general-category))) |
|
||||
(strip-nonspacing-marks (s) |
|
||||
(apply #'string (seq-remove #'nonspacing-mark-p |
|
||||
(ucs-normalize-NFD-string s)))) |
|
||||
(cl-replace (title pair) |
|
||||
(replace-regexp-in-string (car pair) (cdr pair) title))) |
|
||||
(let* ((pairs `(("[^[:alnum:][:digit:]]" . "-") ;; Convert anything not alphanumeric. |
|
||||
("--*" . "-") ;; Remove sequential dashes. |
|
||||
("^-" . "") ;; Remove starting dashes. |
|
||||
("-$" . ""))) ;; Remove ending dashes. |
|
||||
(slug (-reduce-from #'cl-replace (strip-nonspacing-marks title) pairs))) |
|
||||
(downcase slug)))) |
|
||||
(setq org-roam-title-to-slug-function #'dotfiles/title-to-slug)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Visualizer |
|
||||
|
|
||||
Use the ~org-roam-server~[fn:2] web application to visualize the ~org-roam~[fn:1] database. It's available whenever the editor is running at http://localhost:8080. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package org-roam-server |
|
||||
:after org-roam |
|
||||
:hook (org-roam-mode . org-roam-server-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Templates |
|
||||
|
|
||||
Collection of capture templates for various contexts. Here is one for a generic document. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(add-to-list 'org-roam-capture-templates |
|
||||
'("d" "Default" entry (function org-roam-capture--get-point) |
|
||||
"%?" |
|
||||
:file-name "docs/${slug}" |
|
||||
:unnarrowed t |
|
||||
:head |
|
||||
" |
|
||||
,#+TITLE: ${title} |
|
||||
,#+AUTHOR: Christopher James Hayward |
|
||||
,#+EMAIL: chris@chrishayward.xyz |
|
||||
"))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Course |
|
||||
|
|
||||
Capture template for a new course. Capture with =SPC r c c=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(add-to-list 'org-roam-capture-templates |
|
||||
'("c" "Course" plain (function org-roam-capture--get-point) |
|
||||
"%?" |
|
||||
:file-name "docs/courses/${slug}" |
|
||||
:unnarrowed t |
|
||||
:head |
|
||||
" |
|
||||
,#+TITLE: ${title} |
|
||||
,#+SUBTITLE: |
|
||||
,#+AUTHOR: Christopher James Hayward |
|
||||
,#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
,#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
|
||||
,#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
|
||||
"))) |
|
||||
#+end_src |
|
||||
|
|
||||
** Dailies |
|
||||
|
|
||||
Use the ~daily~ note feature of ~org-roam~[fn:1] to capture daily notes. Create the default capture template with some preconfigured headers. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(with-eval-after-load 'org-roam |
|
||||
(add-to-list 'org-roam-dailies-capture-templates |
|
||||
'("d" "Default" entry (function org-roam-capture--get-point) |
|
||||
"* %?" |
|
||||
:file-name "docs/daily/%<%Y-%m-%d>" |
|
||||
:head |
|
||||
" |
|
||||
,#+TITLE: %<%Y-%m-%d> |
|
||||
,#+AUTHOR: Christopher James Hayward |
|
||||
|
|
||||
,#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil |
|
||||
,#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil |
|
||||
"))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Configure custom keybindings for ~org-roam~[fn:1] behind =SPC r=: |
|
||||
|
|
||||
+ Find with =f= |
|
||||
+ Insert with =i= |
|
||||
+ Buffer with =b= |
|
||||
+ Capture with =c= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"r" '(:ignore t :which-key "Roam") |
|
||||
"ri" '(org-roam-insert :which-key "Insert") |
|
||||
"rf" '(org-roam-find-file :which-key "Find") |
|
||||
"rc" '(org-roam-capture :which-key "Capture") |
|
||||
"rb" '(org-roam-buffer-toggle-display :which-key "Buffer")) |
|
||||
#+end_src |
|
||||
|
|
||||
Place keybindings for daily notes behind =SPC r d=: |
|
||||
|
|
||||
+ Date with =d= |
|
||||
+ Today with =t= |
|
||||
+ Tomorrow with =m= |
|
||||
+ Yesterday with =y= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"rd" '(:ignore t :which-key "Dailies") |
|
||||
"rdd" '(org-roam-dailies-find-date :which-key "Date") |
|
||||
"rdt" '(org-roam-dailies-find-today :which-key "Today") |
|
||||
"rdm" '(org-roam-dailies-find-tomorrow :which-key "Tomorrow") |
|
||||
"rdy" '(org-roam-dailies-find-yesterday :which-key "Yesterday")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://github.com/org-roam/org-roam |
|
||||
|
|
||||
[fn:2] https://github.com/org-roam/org-roam-server |
|
@ -1,98 +0,0 @@ |
|||||
#+TITLE: Shell |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle shell.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 |
|
||||
|
|
||||
Shell environment integration. |
|
||||
|
|
||||
* Setup |
|
||||
:PROPERTIES: |
|
||||
:header-args: :tangle ../config/profile :comments org |
|
||||
:END: |
|
||||
|
|
||||
Override the default behaviour of the Shell environment to integrate with Emacs. |
|
||||
|
|
||||
** Force colours |
|
||||
|
|
||||
When using Emacs on the TTY, the colours sometimes will default to 16 or 8 colours, making it look horrible. It's possible to override this behaviour on every platform by manually set the terminal type to =xterm-256color=. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
export TERM=xterm-256color |
|
||||
#+end_src |
|
||||
|
|
||||
** Setting up the $PATH |
|
||||
|
|
||||
Ensure =~/.local/bin= has been added to the ~$PATH~ environment variable, this location is used frequently to deploy local binaries. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
export PATH=$PATH:~/.local/bin |
|
||||
#+end_src |
|
||||
|
|
||||
** Starting Emacs by default on TTY1 |
|
||||
|
|
||||
When launching into a new session on TTY1, if the display server is not running, run ~startx~[fn:1]. This will launch the window manager. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then |
|
||||
exec startx |
|
||||
fi |
|
||||
#+end_src |
|
||||
|
|
||||
** Creating symbolic links |
|
||||
|
|
||||
The system looks for the default shell profile under ~bash~[fn:2] at =~/.profile=. Creating a symbolic link from this location to our configuration will override the startup behaviour. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/profile" |
|
||||
"~/.profile") |
|
||||
#+end_src |
|
||||
|
|
||||
* Methods |
|
||||
|
|
||||
Define methods for interaction between Emacs and the underlying shell environment. |
|
||||
|
|
||||
** Run an external process |
|
||||
|
|
||||
Define a method to run an external process, launching any application on a new process without interferring with Emacs. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/run (cmd) |
|
||||
"Run an external process." |
|
||||
(interactive (list (read-shell-command "λ "))) |
|
||||
(start-process-shell-command cmd nil cmd)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Apply command to call process |
|
||||
|
|
||||
Define a method to apply commands to the current call process, this is to avoid issues with hooks but can impact the performance of Emacs. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/run-in-background (cmd) |
|
||||
(let ((command-parts (split-string cmd "[ ]+"))) |
|
||||
(apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts))))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Place keybindings for executing shell commands behind =SPC x=: |
|
||||
|
|
||||
+ Run shell commands with =x= |
|
||||
+ Run async shell commands with =z= |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"x" '(:ignore t :which-key "Run") |
|
||||
"xx" '(dotfiles/run :which-key "Run") |
|
||||
"xz" '(async-shell-command :which-key "Async")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://x.org |
|
||||
|
|
||||
[fn:2] https://gnu.org/software/bash/ |
|
@ -1,36 +0,0 @@ |
|||||
#+TITLE: Spelling |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle spelling.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 |
|
||||
|
|
||||
Real time checking and one-shot methods to check and correct common spelling mistakes. |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Configure ~ispell~[fn:1] as a back-end with ~flyspell~[fn:2] for real-time checking and highlighting of spelling mistakes. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package ispell |
|
||||
:after org |
|
||||
:custom (ispell-dictionary dotfiles/lang)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Toggle highlighting within buffer specific contexts with =SPC t s=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"ts" '(flyspell-buffer :which-key "Spelling")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://gnu.org/software/ispell/ |
|
||||
|
|
||||
[fn:2] https://emacswiki.org/emacs/FlySpell |
|
@ -1,48 +0,0 @@ |
|||||
#+TITLE: Themes |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle themes.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Configure a unified look and feel across the system with modern themes. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Easily swap between system themes using the ~lxappearance~[fn:1] tool. I tend to default to the ~arc-theme~[fn:2] as it looks really good with most themes. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y lxappearance |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
High quality and modern colour themes are provides inside of Emacs via the ~doom-themes~[fn:3] package. Some of the themes can be further configured, see the documentation for more details. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package doom-themes |
|
||||
:init (load-theme 'doom-moonlight t) |
|
||||
:custom (doom-themes-enable-bold t) |
|
||||
(doom-themes-enable-italic t)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Create a custom keybinding for loading a theme with =SPC t t=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"tt" '(counsel-load-theme t t :which-key "Theme")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://packages.debian.org/sid/lxappearance |
|
||||
|
|
||||
[fn:2] https://packages.debian.org/sid/arc-theme |
|
||||
|
|
||||
[fn:3] https://github.com/hlissner/emacs-doom-themes |
|
@ -1,38 +0,0 @@ |
|||||
#+TITLE: Trash |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle trash.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 |
|
||||
|
|
||||
Keep the system clean of debris. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Despite having the stateful and immutable configuration seprated, and the entire project under version control, it's still good practice to make efforts to reduce the trash created by Emacs. The package ~no-littering~ helps us achieve just that. |
|
||||
|
|
||||
+ Disable ~tooltip-mode~ |
|
||||
+ Disable ~tool-bar-mode~ |
|
||||
+ Disable ~menu-bar-mode~ |
|
||||
+ Disable ~scroll-bar-mode~ |
|
||||
+ Inhibit the startup message |
|
||||
# + Defer ~native-comp~ compilation |
|
||||
+ Clear the scratch buffer instructions |
|
||||
+ Increase the garbage collector threshold |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package no-littering |
|
||||
:custom (inhibit-startup-message t) |
|
||||
(initial-scratch-message "") |
|
||||
;; (comp-deferred-compilation t) |
|
||||
(gc-cons-threshold most-positive-fixnum) |
|
||||
:config (tooltip-mode -1) |
|
||||
(tool-bar-mode -1) |
|
||||
(menu-bar-mode -1) |
|
||||
(scroll-bar-mode -1)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
@ -1,55 +0,0 @@ |
|||||
#+TITLE: UML |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle uml.el :comments org |
|
||||
#+PROPERTY: header-args:shell :tangle no |
|
||||
#+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 |
|
||||
|
|
||||
Draw UML[fn:1] diagrams inside Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Make sure all of the required components are installed on your system before loading the module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y default-jre |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
Download and install ~PlantUML~[fn:2], a text-based markup language for creating UML[fn:1] diagrams. You can read my notes about using the software here[fn:3]. Support for Emacs is added through the ~plantuml-mode~[fn:4] package. Configure the ~babel~ language module and structure templates to write diagrams in ~org-mode~ buffers. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package plantuml-mode |
|
||||
:after org |
|
||||
:custom (plantuml-default-exec-mode 'jar) |
|
||||
(plantuml-jar-path "~/.local/bin/plantuml.jar") |
|
||||
(org-plantuml-jar-path (expand-file-name "~/.local/bin/plantuml.jar")) |
|
||||
(org-startup-with-inline-images t) |
|
||||
:config (add-to-list 'org-src-lang-modes '("plantuml" . plantuml)) |
|
||||
(add-to-list 'org-structure-template-alist '("pl" . "src plantuml")) |
|
||||
(org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t)))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Toggle inline imagines with =SPC t i=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"ti" '(org-toggle-inline-images :which-key "Images")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://tutorialspoint.com/uml/uml_standard_diagrams.htm |
|
||||
|
|
||||
[fn:2] https://plantuml.com |
|
||||
|
|
||||
[fn:3] https://chrishayward.xyz/notes/plantuml/ |
|
||||
|
|
||||
[fn:4] https://github.com/skuro/plantuml-mode |
|
@ -1,43 +0,0 @@ |
|||||
#+TITLE: VTerm |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle vterm.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 |
|
||||
|
|
||||
VTerm is an implementation of libvterm for Emacs. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Install the dependencies before loading the module. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y cmake libtool libtool-bin |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
|
|
||||
I noticed ~eshell~ wasn't enough when needing interactivity from the terminal. Going through [[https://chrishayward.xyz/notes/thinking-in-cpp/][Thinking in C++]] for one of my courses required lots of terminal interaction which ~eshell~ was unable to handle. Since ~vterm~ is based on ~libvterm~, an external C library, it's blazing fast and fully interactive. Add a few configurations: |
|
||||
|
|
||||
+ Always compile the module |
|
||||
+ Install the required packages on *Debian/Ubuntu* |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package vterm |
|
||||
:commands (vterm) |
|
||||
:custom (vterm-always-compile-module t)) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Open a new ~vterm~ buffer with =SPC v=: |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"v" '(vterm-other-window :which-key "VTerm")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
@ -1,165 +0,0 @@ |
|||||
#+TITLE: X11 |
|
||||
#+AUTHOR: Christopher James Hayward |
|
||||
#+EMAIL: chris@chrishayward.xyz |
|
||||
|
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle x11.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 |
|
||||
|
|
||||
X11[fn:1] is a graphical display manager. |
|
||||
|
|
||||
* Setup |
|
||||
|
|
||||
Install the required software on your system before loading the module. Installing X11[fn:1] without any install recommends may not include all of the packages you need on your system. Make sure you don't need any GNOME software utilities before using this example. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y xserver-xorg-core \ |
|
||||
--no-install-recommends \ |
|
||||
--no-install-suggests |
|
||||
#+end_src |
|
||||
|
|
||||
** Displays |
|
||||
|
|
||||
Setup ~autorandr~[fn:2] with pre-configured profiles for screen size and display output. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install autorandr -y |
|
||||
#+end_src |
|
||||
|
|
||||
** Screen locking |
|
||||
|
|
||||
If you want to be able to lock and unlock your screen when you're away from your machine, install ~xss-lock~[fn:3]. By default, it will show a blue screen, turning red if you input your password incorrectly, and returning to your previous screen when successful. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y xss-lock slock |
|
||||
#+end_src |
|
||||
|
|
||||
** Desktop compositor |
|
||||
|
|
||||
Download and install ~compton~[fn:4], a desktop compositor for X11[fn:1] that adds shadows, fading, translucency, and implements window frame opacity controls, inactive window transparency, and more. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y compton |
|
||||
#+end_src |
|
||||
|
|
||||
** Desktop notifications |
|
||||
|
|
||||
Make sure ~dbus~[fn:5] is installed to receive desktop notifications, it's an IPC system used by lots of utilities. |
|
||||
|
|
||||
#+begin_src shell |
|
||||
RUN apt install -y dbus |
|
||||
#+end_src |
|
||||
|
|
||||
* Config |
|
||||
:PROPERTIES: |
|
||||
:header-args: :tangle ../config/xinitrc :comments org |
|
||||
:END: |
|
||||
|
|
||||
My workflow includes launching Emacs under X11[fn:1] without the use of a display manager, controlling everything within Emacs, while still providing the functionality of a desktop environment. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
compton & |
|
||||
xss-lock -- slock & |
|
||||
exec dbus-launch --exit-with-session emacs -mm --debug-init |
|
||||
#+end_src |
|
||||
|
|
||||
** Create symbolic link |
|
||||
|
|
||||
By default ~xinit~[fn:1] will read the configuration file at =$HOME/.xinitrc=. Override this location with a link to the custom configuration. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/xinitrc" |
|
||||
"~/.xinitrc") |
|
||||
#+end_src |
|
||||
|
|
||||
** Desktop environment |
|
||||
|
|
||||
Use the ~desktop-environment~[fn:6] package to automatically bind well-known programs for controlling the volume, brightness, media playback, and many other XF86 functionality bindings. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(use-package desktop-environment |
|
||||
:after exwm |
|
||||
:custom (desktop-environment-brightness-small-increment "2%+") |
|
||||
(desktop-environment-brightness-small-decrement "2%-") |
|
||||
(desktop-environment-brightness-normal-decrement "5%-") |
|
||||
(desktop-environment-brightness-normal-decrement "5%-") |
|
||||
(desktop-environment-volume-small-increment "2%+") |
|
||||
(desktop-environment-volume-small-decrement "2%-") |
|
||||
(desktop-environment-volume-normal-increment "5%+") |
|
||||
(desktop-environment-volume-normal-decrement "5%-") |
|
||||
:config (desktop-environment-mode)) |
|
||||
#+end_src |
|
||||
|
|
||||
** Swapping CAPS and CTRL |
|
||||
:PROPERTIES: |
|
||||
:header-args: conf :tangle ../config/xmodmap |
|
||||
:END: |
|
||||
|
|
||||
Use ~Xmodmap~[fn:7] to swap CapsLock and Ctrl to keep common bindings on the home row. |
|
||||
|
|
||||
#+begin_src conf |
|
||||
clear lock |
|
||||
clear control |
|
||||
|
|
||||
keycode 66 = Control_L |
|
||||
|
|
||||
add control = Control_L |
|
||||
add Lock = Control_R |
|
||||
#+end_src |
|
||||
|
|
||||
Override the configuration file. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/symlink "~/.emacs.d/config/xmodmap" |
|
||||
"~/.Xmodmap") |
|
||||
#+end_src |
|
||||
|
|
||||
** Frame transparency |
|
||||
|
|
||||
Emacs supports frame transparency when running under the X Window System[fn:1]. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(defun dotfiles/toggle-transparency () |
|
||||
(interactive) |
|
||||
(let ((alpha (frame-parameter nil 'alpha))) |
|
||||
(set-frame-parameter nil 'alpha |
|
||||
(if (eql (cond ((numberp alpha) alpha) |
|
||||
((numberp (cdr alpha)) (cdr alpha)) |
|
||||
((numberp (cadr alpha)) (cadr alpha))) |
|
||||
100) |
|
||||
'(85 . 80) '(100 . 100))))) |
|
||||
#+end_src |
|
||||
|
|
||||
Enable frame transparency by default. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(set-frame-parameter (selected-frame) 'alpha '(85 . 80)) |
|
||||
(add-to-list 'default-frame-alist '(alpha . (85 . 80))) |
|
||||
#+end_src |
|
||||
|
|
||||
* Shortcuts |
|
||||
|
|
||||
Toggle frame transparency with =SPC t r=. |
|
||||
|
|
||||
#+begin_src emacs-lisp |
|
||||
(dotfiles/leader |
|
||||
"tr" '(dotfiles/toggle-transparency :which-key "Transparency")) |
|
||||
#+end_src |
|
||||
|
|
||||
* Footnotes |
|
||||
|
|
||||
[fn:1] https://en.wikipedia.org/wiki/X_Window_System |
|
||||
|
|
||||
[fn:2] https://github.com/phillipberndt/autorandr |
|
||||
|
|
||||
[fn:3] https://man.archlinux.org/man/xss-lock.1 |
|
||||
|
|
||||
[fn:4] https://github.com/chjj/compton |
|
||||
|
|
||||
[fn:5] https://packages.debian.org/stretch/dbus-x11 |
|
||||
|
|
||||
[fn:6] https://github.com/DamienCassou/desktop-environment |
|
||||
|
|
||||
[fn:7] https://wiki.archlinux.org/title/Xmodmap |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue