aboutsummaryrefslogtreecommitdiff
path: root/Emacs/.config/emacs/app.org
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2023-09-29 22:30:58 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2023-09-29 22:30:58 +0100
commita0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9 (patch)
treeb0482444d66b598c13aa47636306aa42986de8d2 /Emacs/.config/emacs/app.org
parentcc25dcf8121c7a0431f5fc1f27675b1229818041 (diff)
downloaddotfiles-a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9.tar.gz
dotfiles-a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9.tar.bz2
dotfiles-a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9.zip
(Emacs)~config->app,core
The two largest sections of my config are separated into their own files now. Does increase init time, but I just can't handle how big this thing is. It'll be a bit nicer to look at and manage with separate files.
Diffstat (limited to 'Emacs/.config/emacs/app.org')
-rw-r--r--Emacs/.config/emacs/app.org787
1 files changed, 787 insertions, 0 deletions
diff --git a/Emacs/.config/emacs/app.org b/Emacs/.config/emacs/app.org
new file mode 100644
index 0000000..46839d8
--- /dev/null
+++ b/Emacs/.config/emacs/app.org
@@ -0,0 +1,787 @@
+#+title: Applications for Emacs
+#+author: Aryadev Chavali
+#+description: Applications for my Emacs OS™
+#+date: 2023-09-29
+#+property: header-args:emacs-lisp :tangle app.el :comments link :results none
+#+options: toc:nil
+#+startup: noindent
+
+Applications are greater than packages; they provide a set of
+functionality to create an interface in Emacs. Emacs comes with
+applications and others may be installed.
+
+* WIP Dashboard
+:PROPERTIES:
+:header-args:emacs-lisp: :tangle no
+:END:
+Dashboard creates a custom dashboard for Emacs that replaces the
+initial startup screen in default Emacs. It has a lot of customising
+options.
+
+Unfortunately not that useful, many things are easier to invoke
+directly such as recent files or project changing.
+#+begin_src emacs-lisp
+(use-package dashboard
+ :straight t
+ :demand t
+ :general
+ (app-leader
+ "b" #'dashboard-refresh-buffer)
+ (:states '(normal motion emacs)
+ :keymaps 'dashboard-mode-map
+ "q" (proc (interactive) (kill-this-buffer)))
+ (nmmap
+ :keymaps 'dashboard-mode-map
+ "r" #'dashboard-jump-to-recent-files
+ "p" #'dashboard-jump-to-projects
+ "}" #'dashboard-next-section
+ "{" #'dashboard-previous-section)
+ :init
+ (setq initial-buffer-choice nil
+ dashboard-banner-logo-title "Oreomacs"
+ dashboard-center-content t
+ dashboard-set-init-info t
+ dashboard-startup-banner (no-littering-expand-etc-file-name "dashboard/logo.png")
+ dashboard-set-footer t
+ dashboard-set-navigator t
+ dashboard-items '((projects . 5)
+ (recents . 5))
+ dashboard-footer-messages (list
+ "Collecting parentheses..."
+ "Linking 'coffee_machine.o'..."
+ "Uploading ip to hacker named 4chan..."
+ "Dividing by zero..."
+ "Solving 3-sat..."
+ "Obtaining your health record..."
+ (format "Recompiling Emacs for the %dth time..." (random 1000))
+ "Escaping the cycle of samsara..."))
+ :config
+ (dashboard-setup-startup-hook))
+#+end_src
+* EWW
+Emacs Web Wowser is the inbuilt text based web browser for Emacs. It
+can render images and basic CSS styles but doesn't have a JavaScript
+engine, which makes sense as it's primarily a text interface.
+#+begin_src emacs-lisp
+(use-package eww
+ :defer t
+ :general
+ (app-leader
+ "w" #'eww)
+ :straight nil
+ :config
+ (with-eval-after-load "evil-collection"
+ (evil-collection-eww-setup)))
+#+end_src
+* Calendar
+Calendar is a simple inbuilt application that helps with date
+functionalities. I add functionality to copy dates from the calendar
+to the kill ring and bind it to "Y".
+#+begin_src emacs-lisp
+(use-package calendar
+ :straight nil
+ :defer t
+ :commands (+calendar/copy-date +calendar/toggle-calendar)
+ :display
+ ("\\*Calendar\\*"
+ (display-buffer-at-bottom)
+ (inhibit-duplicate-buffer . t)
+ (window-height . 0.17))
+ :general
+ (nmmap
+ :keymaps 'calendar-mode-map
+ "Y" #'+calendar/copy-date)
+ (app-leader
+ "d" #'+calendar/toggle-calendar)
+ :config
+ (defun +calendar/copy-date ()
+ "Copy date under cursor into kill ring."
+ (interactive)
+ (if (use-region-p)
+ (call-interactively #'kill-ring-save)
+ (let ((date (calendar-cursor-to-date)))
+ (when date
+ (setq date (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))
+ (kill-new (format-time-string "%Y-%m-%d" date))))))
+ (+oreo/create-toggle-function
+ +calendar/toggle-calendar
+ "*Calendar*"
+ calendar
+ nil))
+#+end_src
+* Mail
+Mail is a funny thing; most people use it just for business or
+advertising and it's come out of use in terms of personal
+communication in the west for the most part (largely due to "social"
+media applications). However, this isn't true for the open source and
+free software movement who heavily use mail for communication.
+
+Integrating mail into Emacs helps as I can send source code and
+integrate it into my workflow just a bit better.
+** Notmuch
+#+begin_src emacs-lisp
+(use-package notmuch
+ :defer t
+ :commands (notmuch +mail/flag-thread)
+ :general
+ (app-leader "m" #'notmuch)
+ (nmap
+ :keymaps 'notmuch-search-mode-map
+ "f" #'+mail/flag-thread)
+ :init
+ (defconst +mail/signature "---------------\nAryadev Chavali")
+ (defconst +mail/local-dir (concat user-emacs-directory ".mail/"))
+ (setq notmuch-show-logo nil
+ notmuch-search-oldest-first nil
+ notmuch-hello-sections '(notmuch-hello-insert-saved-searches
+ notmuch-hello-insert-alltags
+ notmuch-hello-insert-recent-searches)
+ notmuch-archive-tags '("-inbox" "-unread" "+archive")
+ mail-signature +mail/signature
+ mail-default-directory +mail/local-dir
+ mail-source-directory +mail/local-dir
+ message-signature +mail/signature
+ message-auto-save-directory +mail/local-dir
+ message-directory +mail/local-dir)
+
+ (defun +mail/sync-mail ()
+ "Sync mail via mbsync."
+ (interactive)
+ (start-process-shell-command "" nil "mbsync -a"))
+ (defun +mail/trash-junk ()
+ "Delete any mail in junk"
+ (interactive)
+ (start-process-shell-command "" nil "notmuch search --output=files --format=text0 tag:deleted tag:spam tag:trash tag:junk | xargs -r0 rm"))
+ :config
+ (defun +mail/flag-thread (&optional unflag beg end)
+ (interactive (cons current-prefix-arg (notmuch-interactive-region)))
+ (notmuch-search-tag
+ (notmuch-tag-change-list '("-inbox" "+flagged") unflag) beg end)
+ (when (eq beg end)
+ (notmuch-search-next-thread)))
+ (advice-add #'notmuch-poll-and-refresh-this-buffer :before
+#'+mail/sync-mail)
+ (advice-add #'notmuch-poll-and-refresh-this-buffer :after
+#'+mail/trash-junk)
+ (with-eval-after-load "evil-collection"
+ (evil-collection-notmuch-setup)))
+#+end_src
+** Smtpmail
+#+begin_src emacs-lisp
+(use-package smtpmail
+ :after notmuch
+ :commands mail-send
+ :custom
+ (smtpmail-smtp-server "mail.aryadevchavali.com")
+ (smtpmail-smtp-user "aryadev")
+ (smtpmail-smtp-service 587)
+ (smtpmail-stream-type 'starttls)
+ :init
+ (setq send-mail-function #'smtpmail-send-it
+ message-send-mail-function #'smtpmail-send-it))
+#+end_src
+* Dired
+Setup for dired. Make dired-hide-details-mode the default mode when
+using dired-mode, as it removes the clutter. Setup evil collection
+for dired (even though dired doesn't really conflict with evil, there
+are some corners I'd like to adjust).
+#+begin_src emacs-lisp
+(use-package dired
+ :straight nil
+ :commands (dired find-dired)
+ :hook
+ (dired-mode-hook . auto-revert-mode)
+ (dired-mode-hook . dired-hide-details-mode)
+ :init
+ (setq-default dired-listing-switches "-AFBl --group-directories-first"
+ dired-omit-files "^\\."
+ dired-dwim-target t)
+ (with-eval-after-load "evil-collection"
+ (evil-collection-dired-setup))
+ :general
+ (nmmap
+ :keymaps 'dired-mode-map
+ "T" #'dired-create-empty-file
+ "H" #'dired-up-directory
+ "L" #'dired-find-file)
+ (dir-leader
+ "f" #'find-dired
+ "d" #'dired
+ "D" #'dired-other-frame
+ "i" #'image-dired
+ "p" `((proc (interactive)
+ (dired "~/Text/PDFs/"))
+ :which-key "Open PDFs"))
+ :config
+ (defun +dired/insert-all-subdirectories ()
+ "Insert all subdirectories currently viewable."
+ (interactive)
+ (dired-mark-directories nil)
+ (dolist #'dired-insert-subdir (dired-get-marked-files))
+ (dired-unmark-all-marks))
+
+ (nmmap
+ :keymaps 'dired-mode-map
+ "SPC" nil
+ "SPC ," nil)
+
+ (nmmap
+ :keymaps 'image-dired-thumbnail-mode-map
+ "h" #'image-dired-backward-image
+ "l" #'image-dired-forward-image
+ "j" #'image-dired-next-line
+ "k" #'image-dired-previous-line
+ "H" #'image-dired-display-previous
+ "L" #'image-dired-display-next
+ "RET" #'image-dired-display-this
+ "m" #'image-dired-mark-thumb-original-file
+ "q" #'quit-window)
+
+ (local-leader
+ :keymaps 'dired-mode-map
+ "l" #'dired-maybe-insert-subdir
+ "m" #'dired-mark-files-regexp
+ "u" #'dired-undo))
+#+end_src
+
+** fd-dired
+Uses fd for finding file results in a directory: ~find-dired~ ->
+~fd-dired~.
+
+#+begin_src emacs-lisp
+(use-package fd-dired
+ :after dired
+ :straight t
+ :general
+ (dir-leader
+ "g" #'fd-dired))
+#+end_src
+* Xwidget
+Xwidget is a package which allows for the insertion of arbitrary
+xwidgets into Emacs through buffers. It must be compiled into Emacs
+so you might need to customise your install. One of its premier uses
+is in navigating the web which it provides through the function
+~xwidget-webkit-browse-url~. This renders a fully functional web
+browser within Emacs.
+
+Though I am not to keen on using Emacs to browse the web /via/ xwidget
+(EWW does a good job on its own), I am very interested in its
+capability to render pages with JavaScript, as it may come of use when
+doing web development. I can see the results of work very quickly
+without switching windows all within Emacs.
+** Xwidget Core
+#+begin_src emacs-lisp
+(use-package xwidget
+ :straight nil
+ :general
+ (app-leader
+ "u" #'xwidget-webkit-browse-url)
+ (nmmap
+ :keymaps 'xwidget-webkit-mode-map
+ "q" #'quit-window
+ "h" #'xwidget-webkit-scroll-backward
+ "j" #'xwidget-webkit-scroll-up
+ "k" #'xwidget-webkit-scroll-down
+ "l" #'xwidget-webkit-scroll-forward
+ "+" #'xwidget-webkit-zoom-in
+ "-" #'xwidget-webkit-zoom-out
+ (kbd "C-f") #'xwidget-webkit-scroll-up
+ (kbd "C-b") #'xwidget-webkit-scroll-down
+ "H" #'xwidget-webkit-back
+ "L" #'xwidget-webkit-forward
+ "gu" #'xwidget-webkit-browse-url
+ "gr" #'xwidget-webkit-reload
+ "gg" #'xwidget-webkit-scroll-top
+ "G" #'xwidget-webkit-scroll-bottom))
+#+end_src
+** Xwidget Extensions
+Define a function ~+xwidget/render-file~ that reads a file name and
+presents it in an xwidget. If the current file is an HTML file, ask
+if user wants to open current file. Bind it to ~aU~ in the leader.
+
+Also define a function ~+xwidget/search-query~ that first asks the
+user what search engine they want to use ([[https://duckduckgo.com][Duck Duck Go]] and [[https://devdocs.io][DevDocs]]
+currently) then asks for a query, which it parses then presents in an
+xwidget window. Bind to ~as~ in the leader.
+#+begin_src emacs-lisp
+(use-package xwidget
+ :straight nil
+ :commands (+xwidget/render-file +xwidget/search)
+ :general
+ (app-leader
+ "U" #'+xwidget/render-file
+ "s" #'+xwidget/search)
+ :config
+ (setenv "WEBKIT_FORCE_SANDBOX" "0")
+ (defun +xwidget/render-file (&optional FORCE)
+ "Find file (or use current file) and render in xwidget."
+ (interactive)
+ (cond
+ ((and (not FORCE) (or (string= (replace-regexp-in-string ".*.html"
+ "html" (buffer-name)) "html")
+ (eq major-mode 'web-mode)
+ (eq major-mode 'html-mode))) ; If in html file
+ (if (y-or-n-p "Open current file?: ") ; Maybe they want to open a separate file
+ (xwidget-webkit-browse-url (format "file://%s" (buffer-file-name)))
+ (+xwidget/render-file t))) ; recurse and open file via prompt
+ (t
+ (xwidget-webkit-browse-url
+ (format "file://%s" (read-file-name "Enter file to open: "))))))
+
+ (defun +xwidget/search ()
+ "Run a search query on some search engine and display in
+xwidget."
+ (interactive)
+ (let* ((engine (completing-read "Engine: " '("duckduckgo.com" "devdocs.io") nil t))
+ (query-raw (read-string "Enter query: "))
+ (query
+ (cond
+ ((string= engine "duckduckgo.com") query-raw)
+ ((string= engine "devdocs.io") (concat "_ " query-raw)))))
+ (xwidget-webkit-browse-url (concat "https://" engine "/?q=" query)))))
+#+end_src
+* Eshell
+** Why Eshell?
+Eshell is an integrated shell environment for Emacs, written in Emacs
+Lisp. I argue that it is the best shell/command interpreter to use in
+Emacs.
+
+Eshell is unlike the alternatives in Emacs as it's a /shell/ first,
+not a terminal emulator. It has the ability to spoof some aspects of a
+terminal emulator (through the shell parser), but it is NOT a terminal
+emulator.
+
+The killer benefits of eshell (which would appeal to Emacs users) are
+a direct result of eshell being written in Emacs lisp:
+- incredible integration with Emacs utilities (such as ~dired~,
+ ~find-file~, any read functions, to name a few)
+- very extensible, easy to write new commands which leverage Emacs
+ commands as well as external utilities
+- agnostic of platform: "eshell/cd" will call the underlying change
+ directory function for you, so commands will (usually) mean the same
+ thing regardless of platform
+ - this means as long as Emacs runs, you can run eshell
+
+However, my favourite feature of eshell is the set of evaluators that
+run on command input. Some of the benefits listed above come as a
+result of this powerful feature. These evaluators are described below.
+
+Lisp evaluator: works on braced expressions, evaluating them as Lisp
+expressions (e.g. ~(message "Hello, World!\n")~). Any returned
+objects are printed. This makes eshell a LISP REPL!
+
+External evaluator: works within curly braces, evaluating them via
+some external shell process (like sh) (e.g. ~{echo "Hello,
+world!\n"}~). This makes eshell a (kinda dumb) terminal emulator!
+
+The alias evaluator is the top level evaluator. It is the main
+evaluator for each expression given to eshell. When given an
+expression it tries to evaluate it by testing against these conditions:
+- it's an alias defined by the user or in the ~eshell/~ namespace of
+ functions (simplest evaluator)
+- it's some form of lisp expression (lisp evaluator)
+- it's an external command (bash evaluator)
+Essentially, you get the best of both Emacs and external shell
+programs *ALL WITHIN* Emacs for free.
+** Eshell functionality
+Bind some evil-like movements for easy shell usage, and a toggle
+function to pull up the eshell quickly.
+#+begin_src emacs-lisp
+(use-package eshell
+ :commands +shell/toggle-eshell
+ :general
+ (shell-leader
+ "t" #'+shell/toggle-eshell)
+ :init
+ (add-hook
+ 'eshell-mode-hook
+ (proc
+ (interactive)
+ (general-def
+ :states '(normal insert)
+ :keymaps 'eshell-mode-map
+ "M-l" (proc (interactive) (eshell/clear)
+ "M-j" #'eshell-next-matching-input-from-input
+ "M-k" #'eshell-previous-matching-input-from-input)
+ (local-leader
+ :keymaps 'eshell-mode-map
+ "c" (proc (interactive) (eshell/clear)
+ (recenter))
+ "k" #'eshell-kill-process))))
+ :config
+ (+oreo/create-toggle-function
+ +shell/toggle-eshell
+ "*eshell*"
+ eshell
+ t))
+#+end_src
+** Eshell pretty symbols and display
+Pretty symbols and a display record.
+#+begin_src emacs-lisp
+(use-package eshell
+ :defer t
+ :pretty
+ (eshell-mode-hook
+ ("lambda" . "λ")
+ ("numberp" . "ℤ")
+ ("t" . "⊨")
+ ("nil" . "Ø"))
+ :display
+ ("\\*e?shell\\*" ; for general shells as well
+ (display-buffer-at-bottom)
+ (window-height . 0.25)))
+#+end_src
+** Eshell variables and aliases
+Set some sane defaults, a banner and a prompt. The prompt checks for
+a git repo in the current directory and provides some extra
+information in that case (in particular, branch name and if there any
+changes that haven't been committed).
+
+Also add ~eshell/goto~, which is actually a command accessible from
+within eshell (this is because ~eshell/*~ creates an accessible
+function within eshell with name ~*~). ~eshell/goto~ makes it easier
+to change directories by using Emacs' find-file interface (which is
+much faster than ~cd ..; ls -l~).
+#+begin_src emacs-lisp
+(use-package eshell
+ :config
+ (defun +eshell/get-git-properties ()
+ (let* ((git-branch (shell-command-to-string "git branch"))
+ (is-repo (string= (if (string= git-branch "") ""
+ (substring git-branch 0 1)) "*")))
+ (if (not is-repo) ""
+ (concat
+ "("
+ (nth 2 (split-string git-branch "\n\\|\\*\\| "))
+ "<"
+ (if (string= "" (shell-command-to-string "git status | grep 'up to date'"))
+ "×"
+ "✓")
+ ">)"))))
+ (setq eshell-cmpl-ignore-case t
+ eshell-cd-on-directory t
+ eshell-banner-message (concat (shell-command-to-string "figlet eshell") "\n")
+ eshell-prompt-function
+ (proc
+ (let ((properties (+eshell/get-git-properties)))
+ (concat
+ properties
+ (format "[%s]\n" (abbreviate-file-name (eshell/pwd)))
+ "λ ")))
+ eshell-prompt-regexp "^λ ")
+
+ (defun eshell/goto (&rest args)
+ "Use `read-directory-name' to change directories."
+ (eshell/cd (list (read-directory-name "Enter directory to go to:")))))
+#+end_src
+** Eshell change directory quickly
+~eshell/goto~ is a better ~cd~ for eshell. However it is really just
+a plaster over a bigger issue for my workflow; many times I want
+eshell to be present in the current directory of the buffer I am
+using.
+
+#+begin_src emacs-lisp
+(use-package eshell
+ :straight nil
+ :general
+ (shell-leader
+ "T" #'+eshell/current-buffer)
+ :config
+ (defun +eshell/current-buffer ()
+ (interactive)
+ (let ((dir (if buffer-file-name
+ (file-name-directory buffer-file-name)
+ (if default-directory
+ default-directory
+ nil)))
+ (buf (eshell)))
+ (if dir
+ (with-current-buffer buf
+ (eshell/cd dir)
+ (eshell-send-input))
+ (message "Could not switch eshell: buffer is not real file")))))
+#+end_src
+* Elfeed
+Elfeed is the perfect RSS feed reader, integrated into Emacs
+perfectly. I've got a set of feeds that I use for a large variety of
+stuff, mostly media and entertainment. I've also bound "<leader> ar"
+to elfeed for loading the system.
+#+begin_src emacs-lisp
+(use-package elfeed
+ :general
+ (app-leader "r" #'elfeed)
+ (nmmap
+ :keymaps 'elfeed-search-mode-map
+ "gr" #'elfeed-update
+ "s" #'elfeed-search-live-filter
+ "<return>" #'elfeed-search-show-entry)
+ :init
+ (setq elfeed-db-directory (no-littering-expand-var-file-name "elfeed/"))
+ (setq +rss/feed-urls
+ '(("Arch Linux"
+ "https://www.archlinux.org/feeds/news/"
+ Linux)
+ ("LEMMiNO"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UCRcgy6GzDeccI7dkbbBna3Q"
+ YouTube Stories)
+ ("The Onion"
+ "https://www.theonion.com/rss"
+ Social)
+ ("Stack exchange"
+ "http://morss.aryadevchavali.com/stackexchange.com/feeds/questions"
+ Social)
+ ("Dark Sominium"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UC_e39rWdkQqo5-LbiLiU10g"
+ YouTube Stories)
+ ("Dark Sominium Music"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UCkLiZ_zLynyNd5fd62hg1Kw"
+ YouTube Music)
+ ("Nexpo"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UCpFFItkfZz1qz5PpHpqzYBw"
+ YouTube)
+ ("Techquickie"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UC0vBXGSyV14uvJ4hECDOl0Q"
+ YouTube)
+ ("3B1B"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UCYO_jab_esuFRV4b17AJtAw"
+ YouTube)
+ ("Fredrik Knusden"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UCbWcXB0PoqOsAvAdfzWMf0w"
+ YouTube Stories)
+ ("Barely Sociable"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UC9PIn6-XuRKZ5HmYeu46AIw"
+ YouTube Stories)
+ ("Atrocity Guide"
+ "https://www.youtube.com/feeds/videos.xml?channel_id=UCn8OYopT9e8tng-CGEWzfmw"
+ YouTube Stories)
+ ("Hacker News"
+ "http://morss.aryadevchavali.com/news.ycombinator.com/rss"
+ Social)
+ ("Hacker Factor"
+ "https://www.hackerfactor.com/blog/index.php?/feeds/index.rss2"
+ Social)
+ ("BBC Top News"
+ "http://morss.aryadevchavali.com/feeds.bbci.co.uk/news/rss.xml"
+ News)
+ ("BBC Tech News"
+ "http://morss.aryadevchavali.com/feeds.bbci.co.uk/news/technology/rss.xml"
+ News)))
+ :config
+ (with-eval-after-load "evil-collection"
+ (evil-collection-elfeed-setup))
+ (setq elfeed-feeds (cl-map 'list #'(lambda (item)
+ (append (list (nth 1 item)) (cdr (cdr item))))
+ +rss/feed-urls)))
+#+end_src
+* Magit
+Magit is *the* git porcelain for Emacs, which perfectly encapsulates
+the git cli. In this case I just need to setup the bindings for it.
+As magit will definitely load after evil (as it must be run by a
+binding, and evil will load after init), I can use evil-collection
+freely. Also, define an auto insert for commit messages so that I
+don't need to write everything myself.
+
+#+begin_src emacs-lisp
+(use-package magit
+ :defer t
+ :display
+ ("magit:.*"
+ (display-buffer-same-window)
+ (inhibit-duplicate-buffer . t))
+ ("magit-diff:.*"
+ (display-buffer-below-selected))
+ ("magit-log:.*"
+ (display-buffer-same-window))
+ :general
+ (leader
+ "g" '(magit-dispatch :which-key "Magit")
+ "vf" '(magit-file-dispatch :which-key "Magit file")
+ "vb" '(magit-blame :which-key "Magit blame"))
+ (code-leader
+ "b" #'magit-blame)
+ :auto-insert
+ (("COMMIT_EDITMSG" . "Commit skeleton")
+ ""
+ "(" (read-string "Enter feature/module: ") ")"
+ (read-string "Enter simple description: ") "\n\n")
+ :init
+ (setq vc-follow-symlinks t
+ magit-blame-echo-style 'lines)
+ :config
+ (with-eval-after-load "evil"
+ (evil-set-initial-state 'magit-status-mode 'motion))
+ (with-eval-after-load "evil-collection"
+ (evil-collection-magit-setup)))
+#+end_src
+* IBuffer
+#+begin_src emacs-lisp
+(use-package ibuffer
+ :general
+ (buffer-leader
+ "i" #'ibuffer)
+ :config
+ (with-eval-after-load "evil-collection"
+ (evil-collection-ibuffer-setup)))
+#+end_src
+* Processes
+Emacs has two systems for process management:
++ proced: a general 'top' like interface which allows general
+ management of linux processes
++ list-processes: a specific Emacs based system that lists processes
+ spawned by Emacs (similar to a top for Emacs specifically)
+
+** Proced
+Core proced config, just a few bindings and evil collection setup.
+#+begin_src emacs-lisp
+(use-package proced
+ :straight nil
+ :general
+ (app-leader
+ "p" #'proced)
+ (nmap
+ :keymaps 'proced-mode-map
+ "za" #'proced-toggle-auto-update)
+ :display
+ ("\\*Proced\\*"
+ (display-buffer-at-bottom)
+ (window-height . 0.25))
+ :init
+ (setq proced-auto-update-interval 0.5)
+ :config
+ (with-eval-after-load "evil-collection"
+ (evil-collection-proced-setup)))
+#+end_src
+
+Along with that I setup the package ~proced-narrow~ which allows
+further filtering of the process list.
+#+begin_src emacs-lisp
+(use-package proced-narrow
+ :straight t
+ :after proced
+ :general
+ (nmap
+ :keymaps 'proced-mode-map
+ "%" #'proced-narrow))
+#+end_src
+* Calculator
+Surprise, surprise Emacs comes with a calculator.
+
+Greater surprise, this thing is over powered. It can perform the
+following (and more):
+- Matrix calculations
+- Generalised calculus operations
+- Equation solvers for n-degree multi-variable polynomials
+- Embedded mode (check below)!
+
+~calc-mode~ is a calculator system within Emacs that provides a
+diverse array of mathematical operations. It uses reverse polish
+notation to do calculations (though there is a standard infix
+algebraic notation mode).
+
+Embedded mode allows computation with the current buffer as the echo
+area. This basically means I can compute stuff within a buffer
+without invoking calc directly: $1 + 2\rightarrow_{\text{calc-embed}} 3$.
+
+#+begin_src emacs-lisp
+(use-package calc
+ :straight nil
+ :display
+ ("*Calculator*"
+ (display-buffer-at-bottom)
+ (window-height . 0.18))
+ :general
+ (app-leader
+ "c" #'calc-dispatch)
+ (mode-leader
+ "c" #'calc-embedded)
+ :init
+ (setq calc-algebraic-mode t)
+ :config
+ (with-eval-after-load "evil-collection"
+ (evil-collection-calc-setup)))
+#+end_src
+** WIP Calctex
+:PROPERTIES:
+:header-args:emacs-lisp: :tangle no
+:END:
+~calc-mode~ also has a 3rd party package called ~calctex~. It renders
+mathematical expressions within calc as if they were rendered in TeX.
+You can also copy the expressions in their TeX forms, which is pretty
+useful when writing a paper. I've set a very specific lock on this
+repository as it's got quite a messy work-tree and this commit seems to
+work for me given the various TeX utilities installed via Arch.
+
+#+begin_src emacs-lisp
+(use-package calctex
+ :after calc
+ :straight (calctex :type git :host github :repo "johnbcoughlin/calctex")
+ :hook (calc-mode-hook . calctex-mode))
+#+end_src
+* Ledger
+#+begin_src emacs-lisp
+(use-package ledger-mode
+ :defer t)
+
+(use-package evil-ledger
+ :after ledger-mode)
+#+end_src
+* WIP Zone
+:PROPERTIES:
+:header-args:emacs-lisp: :tangle no
+:END:
+Of course Emacs has a cool screensaver software.
+
+#+begin_src emacs-lisp
+(use-package zone-matrix
+ :straight t
+ :after dashboard
+ :init
+ (setq zone-programs
+ [zone-pgm-jitter
+ zone-pgm-putz-with-case
+ zone-pgm-dissolve
+ zone-pgm-whack-chars
+ zone-pgm-drip
+ zone-pgm-rat-race
+ zone-pgm-random-life
+ zone-matrix
+ ])
+ :config
+ (zone-when-idle 15))
+#+end_src
+* (Wo)man
+Man pages are the user manuals for most software on Linux. Really
+useful when writing code for Un*x systems, though they can be very
+verbose.
+
+2023-08-17: `Man-notify-method' is the reason the `:display' record
+doesn't work here. I think it's to do with how Man pages are rendered
+or something, but very annoying as it's a break from standards!
+#+begin_src emacs-lisp
+(use-package man
+ :demand t
+ :straight nil
+ :init
+ (setq Man-notify-method 'pushy)
+ :display
+ ("^\\*Man.*"
+ (display-buffer-reuse-mode-window display-buffer-same-window))
+ :general
+ (file-leader
+ "m" #'man) ;; kinda like "find man page"
+ (nmmap
+ :keymaps 'Man-mode-map
+ "RET" #'man-follow))
+#+end_src
+* gif-screencast
+Little application that uses =gifsicle= to make essentially videos of
+Emacs. Useful for demonstrating features.
+#+begin_src emacs-lisp
+(use-package gif-screencast
+ :straight t
+ :general
+ (app-leader
+ "x" #'gif-screencast-start-or-stop)
+ :init
+ (setq gif-screencast-output-directory (expand-file-name "~/Media/emacs/")))
+#+end_src