From 846b48b0b179fcaa49c494d0da0e23db71b989dd Mon Sep 17 00:00:00 2001 From: Preston Pan Date: Sun, 11 Jun 2023 17:43:34 -0700 Subject: first commit --- .gitignore | 1 + LICENSE.org | 14 + README.org | 25 ++ config/doom.org | 174 +++++++++++ config/elfeed.org | 20 ++ config/fish.org | 55 ++++ config/index.org | 27 ++ config/kmonad.org | 720 ++++++++++++++++++++++++++++++++++++++++++++++ config/qtile.org | 286 ++++++++++++++++++ config/qutebrowser.org | 99 +++++++ index.org | 37 +++ journal/20230609.org | 10 + journal/20230610.org | 18 ++ journal/20230611.org | 16 ++ journal/index.org | 28 ++ mindmap/duality.org | 9 + mindmap/emergence.org | 9 + mindmap/everything.org | 36 +++ mindmap/factorial.org | 8 + mindmap/index.org | 21 ++ mindmap/python.org | 6 + mindmap/recursion.org | 71 +++++ mindmap/self-assembly.org | 9 + mindmap/stack.org | 6 + style.css | 323 +++++++++++++++++++++ track.sh | 8 + 26 files changed, 2036 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.org create mode 100644 README.org create mode 100644 config/doom.org create mode 100644 config/elfeed.org create mode 100644 config/fish.org create mode 100644 config/index.org create mode 100644 config/kmonad.org create mode 100644 config/qtile.org create mode 100644 config/qutebrowser.org create mode 100644 index.org create mode 100644 journal/20230609.org create mode 100644 journal/20230610.org create mode 100644 journal/20230611.org create mode 100644 journal/index.org create mode 100644 mindmap/duality.org create mode 100644 mindmap/emergence.org create mode 100644 mindmap/everything.org create mode 100644 mindmap/factorial.org create mode 100644 mindmap/index.org create mode 100644 mindmap/python.org create mode 100644 mindmap/recursion.org create mode 100644 mindmap/self-assembly.org create mode 100644 mindmap/stack.org create mode 100644 style.css create mode 100755 track.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..849e6ba --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +./website/** diff --git a/LICENSE.org b/LICENSE.org new file mode 100644 index 0000000..df18b21 --- /dev/null +++ b/LICENSE.org @@ -0,0 +1,14 @@ +#+title: The MIT License +#+author: Preston Pan +#+description: license for website +#+html_head: +#+date: <2023-06-11 Sun> +#+language: en + +Copyright © 2023 Preston Pan + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.org b/README.org new file mode 100644 index 0000000..f2c734d --- /dev/null +++ b/README.org @@ -0,0 +1,25 @@ +#+title: ret2pop +#+author: Preston Pan +#+date: <2023-06-11 Sun> +#+description: My website for all things. +#+options: num:nil broken-links:t tex:dvipng +#+html_head: + +* What is this? +It's ret2pop! My website for all things math. Wait, no. Computer science. +Music. Okay, let me try that again. + +It's ret2pop! My website for all things. + +** Sounds awesome! But why is it written in org instead of html? +Because I have converted to the church of emacs. Remember: +anything and everything that can be rewritten in org, can and should +be rewritten in org. +*** so how did you actually do that? +By using the ~org-publish~ function, ~org-roam~, and ~org-journal~, +as well as writing a lot of things with a literate config. +** So, where is this website of yours located? +https://ret2pop.nullring.xyz, it is the road to enlightenment. + +* License +See the [[file:LICENSE.org][license]]. The style.css has its own license. diff --git a/config/doom.org b/config/doom.org new file mode 100644 index 0000000..b3fce4b --- /dev/null +++ b/config/doom.org @@ -0,0 +1,174 @@ +#+title: Doom Literate Config +#+author: Preston Pan +#+date: <2023-06-09 Fri> +#+description: My doom emacs configuration +#+html_head: + +* Configuration +** Basic Information +My name, and the org mode directory on my computer, as well as basic editor configuration options. +Below is the old documentation. +#+begin_src emacs-lisp :tangle yes +(setq user-full-name "Preston Pan" + user-mail-address "prseton@nullring.xyz") + +(setq display-line-numbers-type t) + +(setq org-directory "~/org/") +#+end_src +- `load!' for loading external *.el files relative to this one +- `add-load-path!' for adding directories to the `load-path', relative to + this file. Emacs searches the `load-path' when you load packages with + `require' or `use-package'. +** Font +Now we configure fonts: +#+begin_src emacs-lisp :tangle yes +(setq doom-font (font-spec :family "FiraCode Nerd Font" :size 14 :weight 'semi-light) + doom-variable-pitch-font (font-spec :family "Fira Sans" :size 14) + doom-unicode-font (font-spec :family "Symbola" :size 14) + doom-serif-font (font-spec :family "Fira Sans" :size 14) + doom-big-font (font-spec :family "FiraCode Nerd Font" :size 28)) +#+end_src +** Color Scheme +I'm using the catppuccin theme, which is available on github. +#+begin_src emacs-lisp :tangle yes +(setq doom-theme 'catppuccin) +(setq catppuccin-flavor 'mocha) +#+end_src +** Doom Module and Programs Configuration +*** IRC +Set up circe to connect to my bouncer: +#+begin_src emacs-lisp :tangle yes +(after! circe + (set-irc-server! "nullring.xyz" + `(:tls t + :port 4095 + :nick "LiCoO2/AndreiNet" + :user "LiCoO2/AndreiNet" + :pass ,(+pass-get-secret "ZNC")))) +#+end_src +*** Email +In order to use this configuration, you must install and configure mu and mbsync. +#+begin_src emacs-lisp :tangle yes +(setq mu4e-get-mail-command "mbsync --config ~/.config/doom/mbsyncrc prestonpan") + +(setq send-mail-function 'smtpmail-send-it) +(setq smtpmail-smtp-server "mail.nullring.xyz") +(setq smtpmail-smtp-service 465) +(setq smtpmail-stream-type 'ssl) + +(setq mu4e-drafts-folder "/Drafts") +(setq mu4e-sent-folder "/Sent") +(setq mu4e-trash-folder "/Trash") + +(setq mu4e-html2text-command "w3m -T text/html" + mu4e-update-interval 300 + mu4e-headers-auto-update t + mu4e-view-show-images t + mu4e-compose-signature-auto-include nil + mu4e-use-fancy-chars t) +(setq mu4e-compose-reply-ignore-address '("no-?reply" "preston@nullring.xyz")) +#+end_src +*** RSS +We need to set up elfeed with a list of rss feeds. +#+begin_src emacs-lisp :tangle yes +(after! elfeed + (setq elfeed-search-filter "@1-month-ago +unread")) +(add-hook! 'elfeed-search-mode-hook #'elfeed-update) +(setq rmh-elfeed-org-files '("~/org/elfeed.org")) +#+end_src +*** Music +In order to use this configuration, you must have mpd configured to use the same directory. +We automatically connect to mpd. +#+begin_src emacs-lisp :tangle yes +(setq emms-player-mpd-music-directory "~/music/") +(setq emms-player-list '(emms-player-mpd)) +(emms-player-mpd-connect) +#+end_src +*** Journal +First we set the journal to be in the website directory: +#+begin_src emacs-lisp :tangle yes + +(setq org-journal-dir "~/org/website/journal/") +(setq org-journal-date-format "%A, %d %B %Y") +#+end_src +And then we add the headers needed to export the journal automatically: +#+begin_src emacs-lisp :tangle yes +(defun org-journal-file-header-func (time) + "Custom function to create journal header." + (concat + (pcase org-journal-file-type + (`daily "#+TITLE: Daily Journal\n#+STARTUP: showeverything\n#+DESCRIPTION: My daily journal entry\n#+AUTHOR: Preston Pan\n#+HTML_HEAD: \n#+html_head: \n#+html_head: ") + (`weekly "#+TITLE: Weekly Journal\n#+STARTUP: folded") + (`monthly "#+TITLE: Monthly Journal\n#+STARTUP: folded") + (`yearly "#+TITLE: Yearly Journal\n#+STARTUP: folded")))) + +(setq org-journal-file-header 'org-journal-file-header-func) +(setq org-journal-file-format "%Y%m%d.org") +#+end_src +*** Brain +#+begin_src emacs-lisp :tangle yes +(setq org-brain-path "~/org/website/brain/") +#+end_src +*** Roam +#+begin_src emacs-lisp :tangle yes +(setq org-roam-directory (file-truename "~/org/website/mindmap")) +(setq org-roam-capture-templates '(("d" "default" plain "%?" + :target (file+head "${title}.org" + "#+title: ${title}\n#+author: Preston Pan\n#+html_head: \n#+html_head: \n#+html_head: ") + :unnarrowed t))) +#+end_src +*** Publishing +#+begin_src emacs-lisp :tangle yes +(require 'ox-publish) +(setq org-publish-project-alist + '(("website-org" + :base-directory "~/org/website" + :base-extension "org" + :publishing-directory "~/website_html" + :recursive t + :publishing-function org-html-publish-to-html + :headline-levels 4 + :auto-preamble t) + ("website-static" + :base-directory "~/org/website" + :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf" + :publishing-directory "~/website_html/" + :recursive t + :publishing-function org-publish-attachment) + ("website" :components ("website-org" "website-static")))) + + +#+end_src +** Keybindings +Now we set up our keybindings for our applications: +#+begin_src emacs-lisp :tangle yes +(map! :leader + :desc "Open irc" + "i c" #'circe) +(map! :leader + :desc "Open audio manager" + "m m" #'emms) +(map! :leader + :desc "Open RSS feed reader" + "r s" #'elfeed) +(map! :leader + :desc "Open password manager" + "p w" #'ivy-pass) +#+end_src +** External Packages +we want to include some packages that don't come with doom emacs. +*** KBD-Mode +kbd-mode allows us to edit kmonad kbd files with syntax highlighting: +#+begin_src emacs-lisp :tangle yes +(use-package! kbd-mode) +#+end_src +*** Pinentry +We now set up pinentry for the pass program. We need to set the mode to loopback +in order to enable emacs to start itself as a pinentry program, and we need to allow +loopbacks in gpg-agent.conf. +#+begin_src emacs-lisp :tangle yes +(use-package! pinentry + :init (setq epa-pinentry-mode `loopback) + (pinentry-start)) +#+end_src diff --git a/config/elfeed.org b/config/elfeed.org new file mode 100644 index 0000000..bd71ffd --- /dev/null +++ b/config/elfeed.org @@ -0,0 +1,20 @@ +#+title: Elfeed Feed +#+author: Preston Pan +#+date: <2023-06-09 Fri> +#+description: My list of blogs, news sites, and channels. + +#+html_head: +* Feed +** Blogs :blog: +Here are some interesting blogs, many of which are from substack. +*** https://astralcodexten.substack.com/feed +*** https://graymirror.substack.com/feed +*** https://lukesmith.xyz/index.xml :lukesmith: +** News :news: +*** https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml +*** https://rss.nytimes.com/services/xml/rss/nyt/World.xml +*** https://rss.nytimes.com/services/xml/rss/nyt/Science.xml +*** https://rss.nytimes.com/services/xml/rss/nyt/AsiaPacific.xml +** Podcasts :podcast: +*** https://notrelated.xyz/rss :lukesmith: +** Misc. diff --git a/config/fish.org b/config/fish.org new file mode 100644 index 0000000..cb6e0af --- /dev/null +++ b/config/fish.org @@ -0,0 +1,55 @@ +#+title: Fish RC File +#+author: Preston Pan +#+date: <2023-06-09 Fri> +#+description: My fish shell configuration. + +#+html_head: + +* Configuration +** Environment Variables +We define our path and also some environment variables. Since +I use guix as one of my package managers, I set GUIX_LOCPATH. +Also, I have a ~/.local/bin directory where I keep my scripts. +#+begin_src fish :tangle config.fish +fish_add_path -m ~/.local/bin +fish_add_path -m ~/gems/bin +fish_add_path -m ~/.local/share/gem/ruby/3.0.0/bin +set -x GUIX_LOCPATH $HOME/.guix-profile/lib/locale +set -x GEM_HOME "~/gems" +#+end_src +** Aliases +Now we define some aliases: +*** Git +We want to define aliases only if we call fish as an interactive shell. +We also define some common aliases for git commands: +#+begin_src fish :tangle config.fish +if status is-interactive + alias gcl="git clone" + alias gp="git push" + alias gpu="git pull" + alias gcm="git commit" +#+end_src +*** Pacman +Now we define aliases for commonly used pacman commands in the form +of the paru aur helper: +#+begin_src fish :tangle config.fish + alias p="paru -S" + alias pq="paru -sS" + alias pd="paru -Rncs" + alias syncweb="rsync -uvrP --delete-after website_html/ root@nullring.xyz:/var/www/ret2pop/" +#+end_src +*** Misc. +These are generally useful commands. Since I use mbsync, I wrote an alias +for it. +#+begin_src fish :tangle config.fish + alias c="clear" + alias l="ls -a" + alias mkdir="mkdir -pv" + alias syncmail="mbsync -c ~/.config/doom/mbsyncrc prestonpan" +#+end_src +** Vi Mode +Now we want to use vi mode because it is better. +#+begin_src fish :tangle config.fish + fish_vi_key_bindings +end +#+end_src diff --git a/config/index.org b/config/index.org new file mode 100644 index 0000000..1932468 --- /dev/null +++ b/config/index.org @@ -0,0 +1,27 @@ +#+title: Configurations +#+author: Preston Pan +#+date: <2023-06-10 Sat> +#+language: en +#+html_head: +#+OPTIONS: broken-links:t +* What is this magic? +They're configurations for extremely obscure programs I use. Yeah, I know, I'm somewhat of a hipster myself. +** Configurations +Here is a list of my configurations for various programs: +#+begin_src shell :results output raw :exports both +for f in *; +do + if [[ "$f" == "index.org" ]]; then + continue + fi + printf -- "- [[file:$f][$f]]\n" +done +#+end_src + +#+RESULTS: +- [[file:doom.org][doom.org]] +- [[file:elfeed.org][elfeed.org]] +- [[file:fish.org][fish.org]] +- [[file:kmonad.org][kmonad.org]] +- [[file:qtile.org][qtile.org]] +- [[file:qutebrowser.org][qutebrowser.org]] diff --git a/config/kmonad.org b/config/kmonad.org new file mode 100644 index 0000000..4f38a86 --- /dev/null +++ b/config/kmonad.org @@ -0,0 +1,720 @@ +#+title: KMonad Configuration +#+author: Preston Pan +#+description: My Literate KMonad Configuration +#+html_head: + +* Goals +** It should be the most efficient keyboard layout possible. +*** Ergonomic key positions and more frequent keys closer to home row. +*** Optimize the layers in such a way where we do not need to change layer frequently +however, layers are still needed because it is sometimes more economical to switch layers rather than to reach. + +* Configuration +** Initial Values +We must set our initial values for the configuration: +#+begin_src kbd :tangle config.kbd +(defcfg + input (device-file "/dev/input/by-path/platform-i8042-serio-0-event-kbd") + output (uinput-sink "My KMonad output" + "/usr/bin/sleep 1 && /usr/bin/setxkbmap -option compose:ralt") + cmp-seq ralt ;; Set the compose key to `RightAlt' + cmp-seq-delay 5 ;; 5ms delay between each compose-key sequence press + fallthrough true + allow-cmd true +) +#+end_src +you need to set your input device according to your hardware. +** defsrc +The defsrc block specifies the default layout that our keyboard uses. Note that when you are, +for example, using a 40% keyboard, some of these keys will not be present. +However, it is still syntactically valid and you will be able to use this +configuration. +#+begin_src kbd :tangle config.kbd +(defsrc + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w e r t y u i o p [ ] \ + caps a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lctl lmet lalt spc ralt rmet cmp rctl +) +#+end_src +Also note that the defsrc block is not used for custom key configuration. It +is used only to describe the shape of the current keyboard. +** defalias +defalias defines aliases for buttons. Buttons are used in deflayer blocks +in order to remap the keys. +#+begin_src kbd :tangle config.kbd +(defalias + num (layer-toggle numbers) + kil C-A-del +) +#+end_src +** deflayer +#+begin_src kbd :tangle config.kbd +#| -------------------------------------------------------------------------- + Necessary: at least 1 `deflayer` block + + It is also important to mention that the 'keymap' in KMonad is modelled as a + stack of layers (just like in QMK). When an event is registered we look in the + top-most layer for a handler. If we don't find one we try the next layer, and + then the next. + + Exactly what 'evaluates-to-a-button' will be expanded on in more detail below. + There are very many different specialist buttons in KMonad that we will touch + upon. However, for now, these 4 are a good place to begin: + + 1. Any keycode evaluates to a button that, on press, emits the press of that + keycode, and on release, emits the release of that keycode. Just a 'normal' + button. The exception is '\', which gets used as an escape character. Use + '\\' instead. Other characters that need to be escaped to match the literal + character are '(', ')', and '_'. + + 2. An @-prefixed name evaluates to an alias lookup. We named two buttons in + the `defalias` block above, we could now refer to these buttons using + `@num` and `@kil`. This is also why we only use alias-names no longer than + 3 characters in this tutorial. Also, note that we are already referencing + some aliases that have not yet been defined, this is not an issue. + + 3. The '_' character evaluates to transparent. I.e. no handler for that + key-event in this layer, causing this event to be handed down the layer + stack to perhaps be handled by the next layer. + + 4. The 'XX' character evaluates to blocked. I.e. no action bound to that + key-event in this layer, but do actually catch event, preventing any + underlying layer from handling it. + + Finally, it is important to note that the *first* `deflayer` statement in a + KMonad config will be the layer that is active when KMonad starts up. + + -------------------------------------------------------------------------- |# + + +(deflayer qwerty + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w e r t y u i o p [ ] \ + esc a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lctl lmet lalt spc @num rmet @sym rctl +) + +(deflayer numbers + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ XX / 7 8 9 - _ _ _ + _ _ _ _ _ XX * 4 5 6 + _ _ + _ _ \( \) . XX 0 1 2 3 _ _ + _ _ _ _ _ _ _ _ +) + +#+end_src + +#+begin_src kbd :tangle config.kbd +#| -------------------------------------------------------------------------- + Optional: modded buttons + + Let's start by exploring the various special buttons that are supported by + KMonad by looking at 'modded' buttons, that is to say, buttons that activate + some kind of 'mod', then perform some button, and finally release that 'mod' + again. + + We have already seen an example of this style of button, our `kil` button is + one such button. Let's look at it in more detail: + C-A-del + + This looks like a simple declarative statement, but it's helpful to realize + that is simply syntactic sugar around 2 function calls. This statement is + equivalent to: + (around ctl (around alt del)) + + This highlights a core design principle in KMonad: we try to provide very + simple buttons, and then we provide rules and functions for combining them + into new buttons. Although note: still very much a work in progress. + + So, looking at this statement: + (around foo bar) + + Here, `around` is a function that takes two buttons and creates a new button. + This new button will, on a press, first press foo, then press bar, and on a + release first release bar, and then foo. Once created, this new button can be + passed to anything in KMonad that expects a button. + + We have already seen other examples of modded buttons, \(, \), *, and +. There + are no Keycodes for these buttons in KMonad, but they are buttons. They simply + evaluate to `(around lsft x)`. All shifted numbers have their corresponding + characters, the same is true for all capitals, and < > : ~ " | { } \_ + and ?. + + To wrap up 'modded-buttons', let's look back at C-A-del. We have 8 variants: + C- : (around lctl X) + A- : (around lalt X) + M- : (around lmet X) + S- : (around lsft X) + + Then RC-, RA-, RM-, and RS- behave exactly the same, except using the + right-modifier. + + These can be combined however you please: + C-A-M-S-x ;; Perfectly valid + C-% ;; Perfectly valid: same as C-S-5 + C-RC-RA-A-M-S-RS-m ;; Sure, but why would you? + + Also, note that although we provide special syntax for certain modifiers, + these buttons are in no way 'special' in KMonad. There is no concept of 'modifier'. + (around a (around b c)) ;; Perfectly valid + + -------------------------------------------------------------------------- |# + +(defalias + + ;; Something useful + cpy C-c + pst C-v + cut C-x + + ;; Something silly + md1 (around a (around b c)) ;; abc + md2 (around a (around lsft b)) ;; aB + md3 C-A-M-S-l + md4 (around % b) ;; BEWARE: %B, not %b, do you see why? +) + +#| -------------------------------------------------------------------------- + Optional: sticky keys + + KMonad also support so called "sticky keys". These are keys that will + behave as if they were pressed after just tapping them. This behaviour + wears off after the next button is pressed, which makes them ideal for + things like a quick control or shift. For example, tapping a sticky and + then pressing `abc' will result in `Abc'. + + You can create these keys with the `sticky-key' keyword: + + (defalias + slc (sticky-key 500 lctl)) + + The number after `sticky-key' is the timeout you want, in milliseconds. If + a key is tapped and that time has passed, it won't act like it's pressed + down when we receive the next keypress. + + It is also possible to combine sticky keys. For example, to + get a sticky shift+control you can do + + (defalias + ssc (around + (sticky-key 500 lsft) + (sticky-key 500 lctl))) + + -------------------------------------------------------------------------- |# + +;; Let's make both shift keys sticky +(defalias + sl (sticky-key 300 lsft) + sr (sticky-key 300 rsft)) + + +;; Now we define the 'tst' button as opening and closing a bunch of layers at +;; the same time. If you understand why this works, you're starting to grok +;; KMonad. +;; +;; Explanation: we define a bunch of testing-layers with buttons to illustrate +;; the various options in KMonad. Each of these layers makes sure to have its +;; buttons not overlap with the buttons from the other layers, and specifies all +;; its other buttons as transparent. When we use the nested `around` statement, +;; whenever we push the button linked to '@tst' (check `qwerty` layer, we bind +;; it to `rctl`), any button we press when holding `rctl` will be pressed in the +;; context of those 4 layers overlayed on the stack. When we release `rctl`, all +;; these layers will be popped again. +(defalias tst (around (layer-toggle macro-test) + (around (layer-toggle layer-test) + (around (layer-toggle around-next-test) + (around (layer-toggle command-test) + (layer-toggle modded-test)))))) + +(deflayer modded-test + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ @md4 _ _ _ _ _ _ _ _ _ _ _ + _ _ @md1 @md2 @md3 _ _ _ _ _ _ _ _ + _ _ @cut @cpy @pst _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ +) + +#| -------------------------------------------------------------------------- + Optional: tap-macros + + Let's look at a button we haven't seen yet, tap-macros. + + `tap-macro` is a function that takes an arbitrary number of buttons and + returns a new button. When this new button is pressed it rapidly taps all its + stored buttons in quick succesion except for its last button, which it only + presses. This last button gets released when the `tap-macro` gets released. + + There are two ways to define a `tap-macro`, using the `tap-macro` function + directly, or through the #() syntactic sugar. Both evaluate to exactly the + same button. + + (tap-macro K M o n a d) + #(K M o n a d) + + If you are going to use a `tap-macro` to perform a sequence of actions inside + some program you probably want to include short pauses between inputs to give + the program time to register all the key-presses. Therefore we also provide + the 'pause' function, which simply pauses processing for a certain amount of + milliseconds. Pauses can be created like this: + + (pause 20) + P20 + + You can also pause between each key stroke by specifying the `:delay' keyword, + as well as a time in ms, at the end of a `tap-macro': + + (tap-macro K M o n a d :delay 5) + #(K M o n a d :delay 5) + + The above would be equivalent to e.g. + + (tap-macro K P5 M P5 o P5 n P5 a P5 d) + + The `tap-macro-release` is like `tap-macro`, except that it + waits to press the last button when the `tap-macro-release` + gets released. It might be useful when combined with a + footswitch that sends keyboard scan codes. + + (tap-macro-release i K M o n a d esc) + + WARNING: DO NOT STORE YOUR PASSWORDS IN PLAIN TEXT OR IN YOUR KEYBOARD + + I know it might be tempting to store your password as a macro, but there are 2 + huge risks: + 1. You accidentally leak your config and expose your password + 2. Anyone who knows about the button can get clear-text representation of your + password with any text editor, shell, or text-input field. + + Support for triggering shell commands directly from KMonad is described in the + command buttons section below. + + This concludes this public service announcement. + + -------------------------------------------------------------------------- |# + +(defalias + mc1 #(K M o n a d) + mc2 #(C-c P50 A-tab P50 C-v) ;; Careful, this might do something + mc3 #(P200 h P150 4 P100 > < P50 > < P20 0 r z 1 ! 1 ! !) + mc4 (tap-macro a (pause 50) @md2 (pause 50) c) + mc5 (tap-macro-release esc esc esc) + mc6 #(@mc3 spc @mc3 spc @mc3) +) + +(deflayer macro-test + _ @mc1 @mc2 @mc3 @mc4 @mc5 @mc6 _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ +) + + +#| -------------------------------------------------------------------------- + Optional: layer manipulation + + You have already seen the basics of layer-manipulation. The `layer-toggle` + button. This button adds a layer to the top of KMonad's layer stack when + pressed, and removes it again when released. There are a number of other ways + to manipulate the layer stack, some safer than others. Let's go through all of + them from safest to least safe: + + `layer-toggle` works as described before, 2 things to note: + 1. If you are confused or worried about pressing a key, changing layers, and + then releasing a key and this causing issues: don't be. KMonad handles + presses and releases in very different ways. Presses get passed directly to + the stacked keymap as previously described. When a KMonad button has its + press-action triggered, it then registers a callback that will catch its + own release before we ever touch the keymap. This guarantees that the + button triggered by the press of X *will be* the button whose release is + triggered by the release of X (the release of X might trigger other things + as well, but that is besides the point.) + 2. If `layer-toggle` can only ever add and then necessarily remove 1 layer + from the stack, then it will never cause a permanent change, and is + perfectly safe. + + `layer-delay`, once pressed, temporarily switches to some layer for some + milliseconds. Just like `layer-toggle` this will never permanently mess-up the + layer stack. This button was initially implemented to provide some + 'leader-key' style behavior. Although I think in the future better solutions + will be available. For now this will temporarily add a layer to the top of the + stack: + (layer-delay 500 my-layer) + + `layer-next`, once pressed, primes KMonad to handle the next press from some + arbitrary layer. This aims to fill the same usecase as `layer-delay`: the + beginnings of 'leader-key' style behavior. I think this whole button will get + deleted soon, because the more general `around-next` now exists (see below) + and this is nothing more than: + (around-next (layer-toggle layer-name)) + Until then though, use `layer-next` like this: + (layer-next layer-name) + + `layer-switch`: change the base-layer of KMonad. As described at the top of + this document, the first `deflayer` statement is the layer that is active when + KMonad starts. Since `layer-toggle` can only ever add on and remove from the + top of that, it can never change the base-layer. The following button will + unregister the bottom-most layer of the keymap, and replace it with another + layer. + (layer-switch my-layer) + + This is where things start getting potentially dangerous (i.e. get KMonad into + an unusuable state until a restart has occured). It is perfectly possible to + switch into a layer that you can never get out of. Or worse, you could + theoretically have a layer full of only `XX`s and switch into that, rendering + your keyboard unuseable until you somehow manage to kill KMonad (without using + your keyboard). + + However, when handled well, `layer-switch` is very useful, letting you switch + between 'modes' for your keyboard. I have a tiny keyboard with a weird keymap, + but I switch into a simple 'qwerty' keymap shifted 1 button to the right for + gaming. Just make sure that any 'mode' you switch into has a button that + allows you to switch back out of the 'mode' (or content yourself restarting + KMonad somehow). + + `layer-add` and `layer-rem`. This is where you can very quickly cause yourself + a big headache. Originally I didn't expose these operations, but someone + wanted to use them, and I am not one to deny someone else a chainsaw. As the + names might give away: + (layer-add name) ;; Add a layer to the top of the stack + (layer-rem name) ;; Remove a layer by name (noop if no such layer) + + To use `layer-add` and `layer-rem` well, you should take a moment to think + about how to create a layout that will prevent you from getting into + situations where you enter a key-configuration you cannot get out of again. + These two operations together, however, are very useful for activating a + permanent overlay for a while. This technique is illustrated in the tap-hold + overlay a bit further down. + + + -------------------------------------------------------------------------- |# + +(defalias + + yah (layer-toggle asking-for-trouble) ;; Completely safe + nah (layer-add asking-for-trouble) ;; Completely unsafe + + ld1 (layer-delay 500 numbers) ;; One way to get a leader-key + ld2 (layer-next numbers) ;; Another way to get a leader key + + ;; NOTE, this is safe because both `qwerty` and `colemak` contain the `@tst` + ;; button which will get us to the `layer-test` layer, which itself contains + ;; both `@qwe` and `@col`. + qwe (layer-switch qwerty) ;; Set qwerty as the base layer + col (layer-switch colemak) ;; Set colemak as the base layer +) +(deflayer layer-test + @qwe _ _ _ _ _ _ _ _ _ _ @add _ @nah + @col _ _ _ _ _ _ _ _ _ _ _ _ @yah + _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ @ld1 @ld2 _ + _ _ _ _ _ _ _ _ +) + +;; Exactly like qwerty, but with the letters switched around +(deflayer colemak + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w f p g j l u y ; [ ] \ + @xcp a r s t d h n e i o ' ret + @sl z x c v b k m , . / @sr + lctl @num lalt spc ralt rmet @sym @tst +) + +(defalias lol #(: - D)) + +;; Contrived example +(deflayer asking-for-trouble + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol +) + +;; One way to safely use layer-add and layer-rem: the button bound to layer-add +;; is the same button bound to layer-rem in the layer that `add` adds to the +;; stack. I.e., it becomes impossible to add or remove multiple copies of a +;; layer. +(defalias + add (layer-add multi-overlay) ;; multi-overlay is defined in the next + rem (layer-rem multi-overlay) ;; section below this + ) + +#| -------------------------------------------------------------------------- + Optional: Multi-use buttons + + Perhaps one of the most useful features of KMonad, where a lot of work has + gone into, but also an area with many buttons that are ever so slightly + different. The naming and structuring of these buttons might change sometime + soon, but for now, this is what there is. + + For the next section being able to talk about examples is going to be handy, + so consider the following scenario and mini-language that will be the same + between scenarios. + - We have some button `foo` that will be different between scenarios + - `foo` is bound to 'Esc' on the input keyboard + - the letters a s d f are bound to themselves + - Px signifies the press of button x on the keyboard + - Rx signifies the release of said button + - Tx signifies the sequential and near instantaneous press and release of x + - 100 signifies 100ms pass + + So for example: + Tesc Ta: + tap of 'Esc' (triggering `foo`), tap of 'a' triggering `a` + Pesc 100 Ta Tb Resc: + press of 'Esc', 100ms pause, tap of 'a', tap of 'b', release of 'Esc' + + The `tap-next` button takes 2 buttons, one for tapping, one for holding, and + combines them into a single button. When pressed, if the next event is its own + release, we tap the 'tapping' button. In all other cases we first press the + 'holding' button then we handle the event. Then when the `tap-next` gets + released, we release the 'holding' button. + + So, using our mini-language, we set foo to: + (tap-next x lsft) + Then: + Tesc -> x + Tesc Ta -> xa + Pesc Ta Resc -> A + Pesc Ta Tr Resc -> AR + + The `tap-hold` button is very similar to `tap-next` (a theme, trust me). The + difference lies in how the decision is made whether to tap or hold. A + `tap-hold` waits for a particular timeout, if the `tap-hold` is released + anywhere before that moment we execute a tap immediately. If the timeout + occurs and the `tap-hold` is still held, we switch to holding mode. + + The additional feature of a `tap-hold` is that it pauses event-processing + until it makes its decision and then rolls back processing when the decision + has been made. + + So, again with the mini-language, we set foo to: + (tap-hold 200 x lsft) ;; Like tap-next, but with a 200ms timeout + Then: + Tesc -> x + Tesc Ta -> xa + Pesc 300 a -> A (the moment you press a) + Pesc a 300 -> A (after 200 ms) + Pesc a 100 Resc -> xa (both happening immediately on Resc) + + The `tap-hold-next` button is a combination of the previous 2. Essentially, + think of it as a `tap-next` button, but it also switches to held after a + period of time. This is useful, because if you have a (tap-next ret ctl) for + example, and you press it thinking you want to press C-v, but then you change + your mind, you now cannot release the button without triggering a 'ret', that + you then have to backspace. With the `tap-hold-next` button, you simply + outwait the delay, and you're good. I see no benefit of `tap-next` over + `tap-hold-next` with a decent timeout value. + + You can use the `:timeout-button` keyword to specify a button other than the + hold button which should be held when the timeout expires. For example, we + can construct a button which types one x when tapped, multiple x's when held, + and yet still acts as shift when another button is pressed before the timeout + expires. So, using the minilanguage and foo as: + (tap-hold-next 200 x lsft :timeout-button x) + Then: + Tesc -> Tx + Pesc 100 a -> A (the moment you press a) + Pesc 5000 Resc -> xxxxxxx (some number of auto-repeated x's) + + Note that KMonad does not itself auto-repeat the key. In this last example, + KMonad emits 200 Px 4800 Rx, and the operating system's auto-repeat feature, + if any, emits multiple x's because it sees that the x key is held for 4800 ms. + + The `tap-next-release` is like `tap-next`, except it decides whether to tap or + hold based on the next release of a key that was *not* pressed before us. This + also performs rollback like `tap-hold`. So, using the minilanguage and foo as: + (tap-next-release x lsft) + Then: + Tesc Ta -> xa + Pa Pesc Ra Resc -> ax (because 'a' was already pressed when we started, so + foo decides it is tapping) + Pesc Pa Resc Ra -> xa (because the first release we encounter is of esc) + Pesc Ta Resc -> A (because a was pressed *and* released after we started, + so foo decides it is holding) + + `tap-next-press` is also a lot like `tap-next`, but decides whether to tap or + hold based on whether another key is pressed before this one is released. + Using the minilanguage: + (tap-next-press x lsft) + Then: + Tesc Ta -> xa + Pa Pesc Ra Resc -> ax (because esc is released before another key is pressed) + Pesc Pa Resc Ra -> A (because a is pressed before esc is released) + Pesc Ta Resc -> A (a is pressed before esc is released here as well) + + These increasingly stranger buttons are, I think, coming from the stubborn + drive of some of my more eccentric (and I mean that in the most positive way) + users to make typing with modifiers on the home-row more comfortable. + Especially layouts that encourage a lot of rolling motions are nicer to use + with the `release` style buttons. + + The `tap-hold-next-release` (notice a trend?) is just like `tap-next-release`, + but it comes with an additional timeout that, just like `tap-hold-next` will + jump into holding-mode after a timeout. + + I honestly think that `tap-hold-next-release`, although it seems the most + complicated, probably is the most comfortable to use. But I've put all of them + in a testing layer down below, so give them a go and see what is nice. + + -------------------------------------------------------------------------- |# + + +(defalias + xtn (tap-next x lsft) ;; Shift that does 'x' on tap + xth (tap-hold 400 x lsft) ;; Long delay for easier testing + thn (tap-hold-next 400 x lsft) + tnr (tap-next-release x lsft) + tnp (tap-next-press x lsft) + tnh (tap-hold-next-release 2000 x lsft) + + ;; Used it the colemak layer + xcp (tap-hold-next 400 esc ctl) +) + +;; Some of the buttons used here are defined in the next section +(deflayer multi-overlay + @mt _ _ _ _ _ _ _ _ _ _ _ @rem _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + @thn _ _ _ _ _ _ _ _ _ _ _ _ + @xtn _ _ _ _ _ _ _ _ _ _ @xth + @tnr @tnp _ _ _ _ _ @tnh +) + + +#| -------------------------------------------------------------------------- + Optional: Multi-tap + + Besides the tap-hold style buttons there is another multi-use button (with. + only 1 variant, at the moment). The `multi-tap`. + + A `multi-tap` codes for different buttons depending on how often it is tapped. + It is defined by a series of delays and buttons, followed by a last button + without delay. As long as you tap the `multi-tap` within the delay specified, + it will jump to the next button. Once the delay is exceeded the selected + button is pressed. If the last button in the list is reached, it is + immediately pressed. When another key is pressed down while we're tapping, + `multi-tap' also immediately exits and taps the current button. + + Note that you can actually hold the button, so in the below example, going: + tap-tap-hold (wait 300ms) will get you a pressed c, until you release again. + + -------------------------------------------------------------------------- |# + +(defalias + mt (multi-tap 300 a 300 b 300 c 300 d e)) + + +#| -------------------------------------------------------------------------- + Optional: Around-next + + The `around-next` function creates a button that primes KMonad to perform the + next button-press inside some context. This could be the context of 'having + Shift pressed' or 'being inside some layer' or, less usefully, 'having d + pressed'. It is a more general and powerful version of `layer-next`. + + There is also an `around-next-timeout` button that does the same thing as + `around-next`, except that if some other button press is not detected within + some timeout, some other button is tapped. This can be used to create a + leader-key that simply times out (by passing a non-button), or a key that can + still function as a normal key, but also as a leader key when used slowly. + + I think expansion of this button-style is probably the future of leader-key, + hydra-style functionality support in KMonad. + + -------------------------------------------------------------------------- |# + +(defalias + ns (around-next sft) ;; Shift the next press + nnm (around-next @num) ;; Perform next press in numbers layer + ntm (around-next-timeout 500 sft XX) + + +) + +(deflayer around-next-test + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + @ns _ _ _ _ _ _ _ _ _ _ _ _ + @nnm _ _ _ _ _ _ _ _ _ _ _ + @ntm _ _ _ _ _ _ _ +) + +#| -------------------------------------------------------------------------- + Optional: Compose-key sequences + + Compose-key sequences are series of button-presses that your operating system + will interpret as the insertion of a special character, like accented + characters, or various special-languages. In that sense, they are just + syntactic sugar for keyboard macros. + + To get this to work on Linux you will need to set your compose-key with a tool + like `setxkbmap', as well as tell kmonad that information. See the `defcfg' + block at the top of this file for a working example. Note that you need to + wait ever so slightly for the keyboard to register with linux before the + command gets executed, that's why the `sleep 1`. Also, note that all the + `/run/current-system' stuff is because the author uses NixOS. Just find a + shell-command that will: + + 1. Sleep a moment + 2. Set the compose-key to your desired key + + Please be aware that what `setxkbmap' calls the `menu' key is not actually the + `menu' key! If you want to use the often suggested + + setxkbmap -option compose:menu + + you will have to set your compose key within kmonad to `compose' and not + `menu'. + + After this, this should work out of the box under Linux. Windows does not + recognize the same compose-key sequences, but WinCompose will make most of the + sequences line up with KMonad: http://wincompose.info/ + This has not in any way been tested on Mac. + + In addition to hard-coded symbols, we also provide 'uncompleted' macros. Since + a compose-key sequence is literally just a series of keystrokes, we can omit + the last one, and enter the sequence for 'add an umlaut' and let the user then + press some letter to add this umlaut to. These are created using the `+"` + syntax. + + -------------------------------------------------------------------------- |# + +(defalias + sym (layer-toggle symbols) + +) + +(deflayer symbols + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ ä é © _ _ _ _ _ _ _ _ _ _ + _ +' +~ +` +^ _ _ _ _ _ _ _ _ + _ +" +, _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _) + + +#| -------------------------------------------------------------------------- + Optional: Command buttons + + Currently we also provide the ability to launch arbitrary shell-commands from + inside kmonad. These commands are simply handed off to the command-shell + without any further checking or waiting. + + NOTE: currently only tested on Linux, but should work on any platform, as long + as the command is valid for that platform. + + The `cmd-button' function takes two arguments, the second one of which is + optional. These represent the commands to be executed on pressing and + releasing the button respectively. + + BEWARE: never run anyone's configuration without looking at it. You wouldn't + want to push: + + (cmd-button "rm -rf ~/*") ;; Delete all this user's data + + + -------------------------------------------------------------------------- |# +#+end_src diff --git a/config/qtile.org b/config/qtile.org new file mode 100644 index 0000000..75f90e0 --- /dev/null +++ b/config/qtile.org @@ -0,0 +1,286 @@ +#+title: My Qtile Config (Mocha) +#+author: Preston Pan +#+date: <2023-06-09 Fri> +#+description: a catppuccin qtile configuration written in emacs +#+html_head: +* Goals +** We want the configuration to have efficient and ergonomic keybindings. +Commonly used keybindings should be two keys, less common ones should use more. +** We want it to work with other programs that it references. +For example, the qutebrowser and qtile configurations should not cause conflict +and they should have mutual consistency. +*** This will therefore make the configuration self sufficient. +** General enough that it will work for most purposes. +Specialized programs or tools should be in a separate section which will make +it easy to parse and remove. + +* Configuration +** Imports and Definitions +All of this is also in the default configuration. +#+begin_src python :tangle config.py +from libqtile import bar, layout, widget +from libqtile.config import Click, Drag, Group, Key, Match, Screen +from libqtile.lazy import lazy +from libqtile.utils import guess_terminal +from libqtile import hook +from libqtile.backend.wayland import InputConfig + +import os +import subprocess + + +mod = "mod4" +terminal = guess_terminal() +wl_import_rules = None +auto_minimize = True +wmname = "LG3D" +#+end_src +** Hex Colors +We then load the catppuccin colors for the bar and window borders. +#+begin_src python :tangle config.py +def get_colors(): + return [ + # Normal colors + '#45475a', + '#f38ba8', + '#a6e3a1', + '#f9e2af', + '#89b4fa', + '#f5c2e7', + '#94e2d5', + '#bac2de', + + # Bright colors + '#585b70', + '#f38ba8', + '#a6e3a1', + '#f9e2af', + '#89b4fa', + '#f5c2e7', + '#94e2d5', + '#a6adc8', + + # background + '#1e1e2e', + # foreground + '#cdd6f4', + ] + +colors = get_colors() +#+end_src +** Keybindings +The _keys_ variable is going to be our final list of keybindings. We start by initializing it +wth our window manipulation bindings with vim keys: +*** Focus controls +Vi inspired keybindings to manipulate focus: +#+begin_src python :tangle config.py +keys = [ + Key([mod], "h", lazy.layout.left(), desc="Move focus to left"), + Key([mod], "l", lazy.layout.right(), desc="Move focus to right"), + Key([mod], "j", lazy.layout.down(), desc="Move focus down"), + Key([mod], "k", lazy.layout.up(), desc="Move focus up"), + Key([mod], "space", lazy.layout.next(), desc="Move window focus to other window"), + + Key([mod, "shift"], "h", lazy.layout.shuffle_left(), desc="Move window to the left"), + Key([mod, "shift"], "l", lazy.layout.shuffle_right(), desc="Move window to the right"), + Key([mod, "shift"], "j", lazy.layout.shuffle_down(), desc="Move window down"), + Key([mod, "shift"], "k", lazy.layout.shuffle_up(), desc="Move window up"), + + Key([mod, "control"], "h", lazy.layout.grow_left(), desc="Grow window to the left"), + Key([mod, "control"], "l", lazy.layout.grow_right(), desc="Grow window to the right"), + Key([mod, "control"], "j", lazy.layout.grow_down(), desc="Grow window down"), + Key([mod, "control"], "k", lazy.layout.grow_up(), desc="Grow window up"), + Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"), + Key( + [mod, "shift"], + "Return", + lazy.layout.toggle_split(), + desc="Toggle between split and unsplit sides of stack", + ), + Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"), +] +#+end_src +*** Quit/Restart +#+begin_src python :tangle config.py +keys.extend([ + Key([mod], "q", lazy.window.kill(), desc="Kill focused window"), + Key([mod, "control"], "r", lazy.reload_config(), desc="Reload the config"), + Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"), +]) +#+end_src +*** Programs +These are our keybindings for user programs. +#+begin_src python :tangle config.py +keys.extend([ + Key([mod], "r", lazy.spawncmd(), desc="Spawn a command using a prompt widget"), + Key([mod], "Return", lazy.spawn(terminal), desc="Launch terminal"), + Key([mod], "e", lazy.spawn("emacs"), desc="Run emacs"), + Key([mod], "w", lazy.spawn("qutebrowser"), desc="Run Qutebrowser"), + Key([mod], "f", lazy.spawn("firefox"), desc="Run Firefox"), + Key([mod], "b", lazy.spawn("blender"), desc="Run Blender"), + Key([mod], "p", lazy.spawn("krita"), desc="Run Krita"), + Key([mod], "t", lazy.spawn("torbrowser-launcher"), desc="Run Tor Browser"), + Key([mod], "i", lazy.spawn("emacsclient --eval \"(emacs-everywhere)\""), desc="Emacs Everywhere!"), +]) +#+end_src +*** XF86 +Now we need keybindings for the function keys: +#+begin_src python :tangle config.py +keys.extend([ + Key([], 'XF86AudioLowerVolume', lazy.spawn("pactl set-sink-volume @DEFAULT_SINK@ -5%")), + Key([], 'XF86AudioRaiseVolume', lazy.spawn("pactl set-sink-volume @DEFAULT_SINK@ +5%")), + Key([], 'XF86AudioMute', lazy.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle")), + Key([], 'XF86MonBrightnessUp', lazy.spawn("light -A 10")), + Key([], 'XF86MonBrightnessDown', lazy.spawn("light -U 10")), + Key([], 'XF86AudioNext', lazy.spawn("mpc next")), + Key([], 'XF86AudioPrev', lazy.spawn("mpc prev")), + Key([], "XF86AudioPlay", lazy.spawn("mpc toggle"), desc="Play/Pause player"), +]) +#+end_src +** Groups +Now we name our groups: +#+begin_src python :tangle config.py +groups = [Group(i) for i in "123456789"] + +for i in groups: + keys.extend( + [ + Key( + [mod], + i.name, + lazy.group[i.name].toscreen(), + desc="Switch to group {}".format(i.name), + ), + Key( + [mod, "shift"], + i.name, + lazy.window.togroup(i.name, switch_group=True), + desc="Switch to & move focused window to group {}".format(i.name), + ), + ] + ) +#+end_src +** Layouts +This is our list of enabled layouts. You can enable more of them if you want. +#+begin_src python :tangle config.py +layouts = [ + layout.Columns(border_focus=colors[2], border_normal=colors[0], border_width=4, margin=7), + layout.Max(), + # Try more layouts by unleashing below layouts. + # layout.Stack(num_stacks=2), + # layout.Bsp(), + # layout.Matrix(), + # layout.MonadTall(), + # layout.MonadWide(), + # layout.RatioTile(), + # layout.Tile(), + # layout.TreeTab(), + # layout.VerticalTile(), + # layout.Zoomy(), +] +#+end_src +** Bar +#+begin_src python :tangle config.py +widget_defaults = dict( + font="FiraCode Nerd Font", + fontsize=16, + padding=4, + foreground=colors[17], + background=colors[16], +) +extension_defaults = widget_defaults.copy() + +screens = [ + Screen( + top=bar.Bar( + [ + # widget.CurrentLayout(), + widget.GroupBox(active=colors[6], inactive=colors[15], this_current_screen_border=colors[4], highlight_color=colors[3]), + widget.Prompt(), + widget.WindowName(), + widget.Chord( + chords_colors={ + "launch": ("#ff0000", "#ffffff"), + }, + name_transform=lambda name: name.upper(), + ), + # widget.StatusNotifier(), + + widget.Systray(), + widget.Battery(charge_char="🔋", discharge_char="🔋", full_char="🔋", format="{char} {percent:2.0%}"), + # widget.TextBox("|", foreground=colors[1]), + widget.Sep(padding=16, size_percent=80, foreground=colors[1]), + widget.Clock(format="🕒 %a %I:%M %p"), + widget.Sep(padding=16, size_percent=80, foreground=colors[1]), + widget.Mpd2(), + widget.TextBox(" "), + + ], + 24, + + # border_width=[2, 0, 2, 0], # Draw top and bottom borders + # border_color=["ff00ff", "000000", "ff00ff", "000000"] # Borders are magenta + ), + bottom=bar.Gap(4), + left=bar.Gap(3), + right=bar.Gap(3), + ), +] +#+end_src +** Mouse +We configure the mouse to interact with floating windows. +#+begin_src python :tangle config.py +mouse = [ + Drag([mod], "Button1", lazy.window.set_position_floating(), start=lazy.window.get_position()), + Drag([mod], "Button3", lazy.window.set_size_floating(), start=lazy.window.get_size()), + Click([mod], "Button2", lazy.window.bring_to_front()), +] +#+end_src + +Also, we need to toggle some options: +#+begin_src python :tangle config.py +dgroups_app_rules = [] # type: list +follow_mouse_focus = True +bring_front_click = False +cursor_warp = False +#+end_src + +And then we add the applications that need to start in floating: +#+begin_src python :tangle config.py +floating_layout = layout.Floating( + float_rules=[ + # Run the utility of `xprop` to see the wm class and name of an X client. + *layout.Floating.default_float_rules, + Match(wm_class="confirmreset"), # gitk + Match(wm_class="makebranch"), # gitk + Match(wm_class="maketag"), # gitk + Match(wm_class="ssh-askpass"), # ssh-askpass + Match(title="branchdialog"), # gitk + Match(title="pinentry"), # GPG key password entry + ] +) +#+end_src +** I have no idea what these are +but they work for some reason. +#+begin_src python :tangle config.py +auto_fullscreen = True +focus_on_window_activation = "smart" +reconfigure_screens = True +#+end_src +** Autostart +If we used wayland, then we must autostart here: +#+begin_src python :tangle config.py +@hook.subscribe.startup_once +def autostart(): + home = os.path.expanduser("~") + subprocess.call([home + '/.config/qtile/autostart.sh']) +#+end_src +** Input Rules +in wayland, setxkbmap is not possible. Therefore: +#+begin_src python :tangle config.py +wl_input_rules = { + "1267:12377:ELAN1300:00 04F3:3059 Touchpad": InputConfig(left_handed=True), + "*": InputConfig(left_handed=True, pointer_accel=True), + "type:keyboard": InputConfig(kb_options="caps:swapescape,compose:ralt"), +} +#+end_src diff --git a/config/qutebrowser.org b/config/qutebrowser.org new file mode 100644 index 0000000..fe70f07 --- /dev/null +++ b/config/qutebrowser.org @@ -0,0 +1,99 @@ +#+title: Qutebrowser Configuration +#+author: Preston Pan +#+date: <2023-06-09 Fri> +#+description: a catppuccin configuration for qutebrowser. + +#+html_head: + +* Configuration +** Imports +We start with imports: +#+begin_src python :tangle config.py +from pathlib import Path +from urllib.parse import urlparse +import catppuccin +#+end_src +We import pathlib to get our home directory. +** Variables +We need the location of the home directory. +#+begin_src python :tangle config.py +home = str(Path.home()) +#+end_src +** Fonts +We are using Fira Code for the font in all the non-webpage ui elements. +#+begin_src python :tangle config.py +c.fonts.hints = '14pt FiraCode Nerd Font' +c.fonts.keyhint = '14pt FiraCode Nerd Font' +c.fonts.prompts = '14pt FiraCode Nerd Font' +c.fonts.downloads = '14pt FiraCode Nerd Font' +c.fonts.statusbar = '14pt FiraCode Nerd Font' +c.fonts.contextmenu = '14pt FiraCode Nerd Font' +c.fonts.messages.info = '14pt FiraCode Nerd Font' +c.fonts.debug_console = '14pt FiraCode Nerd Font' +c.fonts.completion.entry = '14pt FiraCode Nerd Font' +c.fonts.completion.category = '14pt FiraCode Nerd Font' +c.fonts.tabs.selected = '14pt FiraCode Nerd Font' +c.fonts.tabs.unselected = '14pt FiraCode Nerd Font' +#+end_src +** Search Engine +We should set our default search engine to google because duckduckgo is useless, and +we should give other search engine bang options. +#+begin_src python :tangle config.py +c.url.searchengines = { + 'DEFAULT': 'https://google.com/search?hl=en&q={}', + '!a': 'https://www.amazon.com/s?k={}', + '!d': 'https://duckduckgo.com/?ia=web&q={}', + '!dd': 'https://thefreedictionary.com/{}', + '!e': 'https://www.ebay.com/sch/i.html?_nkw={}', + '!fb': 'https://www.facebook.com/s.php?q={}', + '!gh': 'https://github.com/search?o=desc&q={}&s=stars', + '!gist': 'https://gist.github.com/search?q={}', + '!gi': 'https://www.google.com/search?tbm=isch&q={}&tbs=imgo:1', + '!gn': 'https://news.google.com/search?q={}', + '!ig': 'https://www.instagram.com/explore/tags/{}', + '!m': 'https://www.google.com/maps/search/{}', + '!p': 'https://pry.sh/{}', + '!r': 'https://www.reddit.com/search?q={}', + '!sd': 'https://slickdeals.net/newsearch.php?q={}&searcharea=deals&searchin=first', + '!t': 'https://www.thesaurus.com/browse/{}', + '!tw': 'https://twitter.com/search?q={}', + '!w': 'https://en.wikipedia.org/wiki/{}', + '!yelp': 'https://www.yelp.com/search?find_desc={}', + '!yt': 'https://www.youtube.com/results?search_query={}' +} +#+end_src +** Start Page +Set the default start page to my own website. +#+begin_src python :tangle config.py +c.url.start_pages = ["https://preston.nullring.xyz"] +c.url.default_page = "https://preston.nullring.xyz" +#+end_src +** Keybindings +Now we define our keybindings for useful programs while browsing: +#+begin_src python :tangle config.py +config.bind('xm', 'hint links spawn mpv {hint-url}') +config.bind('xy', 'hint links spawn yt-dlp {hint-url} -o "~/videos/youtube/%(title)s.%(ext)s"') +config.bind('xr', 'hint links spawn bash -c "echo \'*** {hint-url}\' >> ~/org/elfeed.org"') +config.bind('xj', 'spawn bash -c "echo {url} >> ~/.config/qutebrowser/js_blacklist.txt"') +#+end_src +** Paywall Bypassing +Sometimes websites like the New York Times try to make money. I won't let that happen. +#+begin_src python :tangle config.py +with open(f"{home}/.config/qutebrowser/js_blacklist.txt") as f: + js_blacklist = f.read().splitlines() + +for item in js_blacklist: + domain = urlparse(item).netloc + config.set('content.javascript.enabled', False, f"*://{domain}/*") + config.set('content.javascript.enabled', False, f"*://www.{domain}/*") +#+end_src +** Misc. +Doing mundane things like setting the downloads directory to not use an upper case letter. +#+begin_src python :tangle config.py +c.downloads.location.directory = "~/downloads" +#+end_src +** End of Config +#+begin_src python :tangle config.py +config.load_autoconfig() +catppuccin.setup(c, 'mocha', False) +#+end_src diff --git a/index.org b/index.org new file mode 100644 index 0000000..30036d0 --- /dev/null +++ b/index.org @@ -0,0 +1,37 @@ +#+title: ret2pop +#+author: Preston Pan +#+description: My personal website +#+html_head: +#+date: <2023-06-09 Fri> +#+language: en +#+OPTIONS: broken-links:t + +* Introducing ret2pop +Hello! I'm a person on the internet that does things, such as: +- Music +- Programming +- Mathematics +- Physics +- Thinking +And if you're here to do one of these things, I guarantee you're in the right place! +** [[file:journal/index.org][Journal]] +If you're interested, you can read my [[file:journal/index.org][journal]]. Note that this journal is not my +entire personal life but instead will be a focus on interesting things that I +think of or things that are of a technical nature. +** [[file:mindmap/index.org][Mindmap]] +I also have a mindmap, for those of you who are interested in knowing everything. +*** What is a mindmap? +Click the hyperlink to find out! In case you didn't see: +- [[file:mindmap/index.org][Mindmap]] +- [[file:mindmap/index.org][Mindmap]] +- [[file:mindmap/index.org][Mindmap]] +** [[file:config/index.org][Configurations]] +Most of my configurations/dotfiles for various programs are literate configurations, and I +can therefore publish them. So I did! Configurations include: +- doom emacs +- QTile +- QuteBrowser +- Elfeed +…and many more! +* About this Website +I wrote this website in org mode. For more information, see the [[file:README.org][README]]. diff --git a/journal/20230609.org b/journal/20230609.org new file m