diff options
author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-09-29 22:30:58 +0100 |
---|---|---|
committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-09-29 22:30:58 +0100 |
commit | a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9 (patch) | |
tree | b0482444d66b598c13aa47636306aa42986de8d2 /Emacs/.config/emacs/app.org | |
parent | cc25dcf8121c7a0431f5fc1f27675b1229818041 (diff) | |
download | dotfiles-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.org | 787 |
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 |