summaryrefslogtreecommitdiff
path: root/dotfiles/system/.local
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/system/.local')
-rwxr-xr-xdotfiles/system/.local/bin/AAXtoMP3908
-rwxr-xr-xdotfiles/system/.local/bin/airplanemodetoggle33
-rwxr-xr-xdotfiles/system/.local/bin/audioselect70
-rwxr-xr-xdotfiles/system/.local/bin/battery_monitor52
-rwxr-xr-xdotfiles/system/.local/bin/bookfind5
-rwxr-xr-xdotfiles/system/.local/bin/brightness36
-rwxr-xr-xdotfiles/system/.local/bin/bsdnet_bounce6
-rwxr-xr-xdotfiles/system/.local/bin/build.emacs.aur.sh6
-rwxr-xr-xdotfiles/system/.local/bin/build.emacs.src.sh76
-rwxr-xr-xdotfiles/system/.local/bin/calibre-install10
-rwxr-xr-xdotfiles/system/.local/bin/colorpick6
-rw-r--r--dotfiles/system/.local/bin/cron/README.md11
-rwxr-xr-xdotfiles/system/.local/bin/cron/checkup17
-rwxr-xr-xdotfiles/system/.local/bin/cron/crontog6
-rwxr-xr-xdotfiles/system/.local/bin/debugemacs4
-rwxr-xr-xdotfiles/system/.local/bin/displayselect83
-rwxr-xr-xdotfiles/system/.local/bin/dmenuexitmenu12
-rwxr-xr-xdotfiles/system/.local/bin/dmenuhandler21
-rwxr-xr-xdotfiles/system/.local/bin/dmenumount67
-rwxr-xr-xdotfiles/system/.local/bin/dmenumountcifs19
-rwxr-xr-xdotfiles/system/.local/bin/dmenurecord123
-rwxr-xr-xdotfiles/system/.local/bin/dmenuumount44
-rwxr-xr-xdotfiles/system/.local/bin/dmenuunicode18
-rwxr-xr-xdotfiles/system/.local/bin/dotfiles_pushall6
-rwxr-xr-xdotfiles/system/.local/bin/dwmstatus79
-rwxr-xr-xdotfiles/system/.local/bin/ec2
-rwxr-xr-xdotfiles/system/.local/bin/em2
-rwxr-xr-xdotfiles/system/.local/bin/et2
-rwxr-xr-xdotfiles/system/.local/bin/exitmenu16
-rwxr-xr-xdotfiles/system/.local/bin/extractaudio2
-rwxr-xr-xdotfiles/system/.local/bin/gitconfig_defaults5
-rwxr-xr-xdotfiles/system/.local/bin/gruv3
-rwxr-xr-xdotfiles/system/.local/bin/ifinstalled12
-rwxr-xr-xdotfiles/system/.local/bin/lfrun19
-rwxr-xr-xdotfiles/system/.local/bin/lfub24
-rwxr-xr-xdotfiles/system/.local/bin/linkhandler26
-rwxr-xr-xdotfiles/system/.local/bin/lkg4
-rwxr-xr-xdotfiles/system/.local/bin/lkg_rollback12
-rwxr-xr-xdotfiles/system/.local/bin/lsbak1
-rwxr-xr-xdotfiles/system/.local/bin/mkplaylist173
-rwxr-xr-xdotfiles/system/.local/bin/monitor50
-rwxr-xr-xdotfiles/system/.local/bin/mpd_play_yt_stream14
-rwxr-xr-xdotfiles/system/.local/bin/msmtp-enqueue.sh44
-rwxr-xr-xdotfiles/system/.local/bin/msmtp-listqueue.sh8
-rwxr-xr-xdotfiles/system/.local/bin/msmtp-runqueue.sh69
-rwxr-xr-xdotfiles/system/.local/bin/open-file-in-eww2
-rwxr-xr-xdotfiles/system/.local/bin/opus2mp33
-rwxr-xr-xdotfiles/system/.local/bin/project100
-rwxr-xr-xdotfiles/system/.local/bin/prompt8
-rwxr-xr-xdotfiles/system/.local/bin/protonvpn3
-rwxr-xr-xdotfiles/system/.local/bin/ps-mem28
-rwxr-xr-xdotfiles/system/.local/bin/recordnow26
-rwxr-xr-xdotfiles/system/.local/bin/refresharchkeys6
-rwxr-xr-xdotfiles/system/.local/bin/remaps11
-rwxr-xr-xdotfiles/system/.local/bin/resetmimetypes273
-rwxr-xr-xdotfiles/system/.local/bin/samedir10
-rwxr-xr-xdotfiles/system/.local/bin/screenshotmenu13
-rwxr-xr-xdotfiles/system/.local/bin/setbg34
-rwxr-xr-xdotfiles/system/.local/bin/ssh-createkeys3
-rwxr-xr-xdotfiles/system/.local/bin/startdwm47
-rwxr-xr-xdotfiles/system/.local/bin/starth9
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-battery37
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-clock29
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-cpu12
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-cpubars44
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-disk23
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-doppler279
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-forecast35
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-help-icon17
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-internet26
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-iplocate10
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-kbselect16
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-mailbox20
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-memory12
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-moonphase37
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-mpdup8
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-music19
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-nettraf29
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-news17
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-pacpackages29
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-popupgrade9
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-price50
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-tasks20
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-torrent27
-rwxr-xr-xdotfiles/system/.local/bin/statusbar/sb-volume30
-rwxr-xr-xdotfiles/system/.local/bin/steam2
-rwxr-xr-xdotfiles/system/.local/bin/sudo-update-grub1
-rwxr-xr-xdotfiles/system/.local/bin/sysupdate5
-rwxr-xr-xdotfiles/system/.local/bin/td-toggle12
-rwxr-xr-xdotfiles/system/.local/bin/timezone-change68
-rwxr-xr-xdotfiles/system/.local/bin/timezone-set17
-rwxr-xr-xdotfiles/system/.local/bin/toggle-touchpad16
-rwxr-xr-xdotfiles/system/.local/bin/torwrap7
-rwxr-xr-xdotfiles/system/.local/bin/touchpad-app3
-rwxr-xr-xdotfiles/system/.local/bin/transadd9
-rwxr-xr-xdotfiles/system/.local/bin/update-backup-repositories56
-rwxr-xr-xdotfiles/system/.local/bin/updatemirrors20
-rwxr-xr-xdotfiles/system/.local/bin/virtstart8
-rwxr-xr-xdotfiles/system/.local/bin/wallsearch43
-rwxr-xr-xdotfiles/system/.local/bin/ytp1
-rw-r--r--dotfiles/system/.local/share/applications/dwm.desktop7
-rw-r--r--dotfiles/system/.local/share/applications/emacsclient-mail.desktop20
-rw-r--r--dotfiles/system/.local/share/applications/file.desktop4
-rw-r--r--dotfiles/system/.local/share/applications/img.desktop4
-rw-r--r--dotfiles/system/.local/share/applications/mail.desktop4
-rw-r--r--dotfiles/system/.local/share/applications/mimeapps.list0
-rw-r--r--dotfiles/system/.local/share/applications/org-protocol.desktop11
-rw-r--r--dotfiles/system/.local/share/applications/pdf.desktop4
-rw-r--r--dotfiles/system/.local/share/applications/text.desktop4
-rw-r--r--dotfiles/system/.local/share/applications/torrent.desktop4
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/2a03.wszbin0 -> 19553 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Adidas2-3.zipbin0 -> 29938 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Blac.wszbin0 -> 129798 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Classic_70's_Marshall_Stack.wszbin0 -> 226617 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Digital_Stereo_73.wszbin0 -> 64065 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Expensive_HI_FI_Sony_2005.wszbin0 -> 244168 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Future_Audio_1.wszbin0 -> 92650 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Modern_Stereo_Amp_2.wszbin0 -> 75766 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Modern_Style_Marshall_Stack.wszbin0 -> 311586 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Nucleo_NLog_v102_.wszbin0 -> 139475 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/PioneerAmp.wszbin0 -> 55340 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/RAZORIX 50 % Uriel - 50% Kript.wszbin0 -> 105829 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/SONY3.WSZbin0 -> 42268 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Sony MD.wszbin0 -> 79957 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Spy Amp.zipbin0 -> 51211 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Heaven.wszbin0 -> 202473 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Zeus.wszbin0 -> 198970 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/SpyAMP_professional_edition_mV1.wszbin0 -> 191945 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/SpyAmp-Pro-Heaven.wszbin0 -> 208361 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Steel_Stereo.wszbin0 -> 224116 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/Technoia_ver001.wszbin0 -> 148428 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/base-2.91.wszbin0 -> 101121 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/deviantamp.zipbin0 -> 77218 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/iWinamp_V1.wszbin0 -> 142681 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/nadamp.zipbin0 -> 38073 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/s_Pioneer.wszbin0 -> 54003 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/satellite.wszbin0 -> 46562 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/sonympfx3lcdv111.wszbin0 -> 41131 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/spyamp.zipbin0 -> 76065 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/spyamp_sepia.wszbin0 -> 61038 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/spyampy2k.wszbin0 -> 124124 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/spyampy2k3.wszbin0 -> 100716 bytes
-rw-r--r--dotfiles/system/.local/share/audacious/Skins/v2_technics_white_resting_by_johnnyg0.wszbin0 -> 143271 bytes
-rw-r--r--dotfiles/system/.local/share/emoji1593
-rw-r--r--dotfiles/system/.local/share/fonts/AppleColorEmoji.ttfbin0 -> 42722048 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.otfbin0 -> 74596 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.ttfbin0 -> 114872 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woffbin0 -> 41892 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff2bin0 -> 38584 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.otfbin0 -> 75756 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.ttfbin0 -> 116664 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woffbin0 -> 42536 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff2bin0 -> 39272 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.otfbin0 -> 75172 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.ttfbin0 -> 115636 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woffbin0 -> 42116 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff2bin0 -> 38948 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.otfbin0 -> 72688 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.ttfbin0 -> 114656 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woffbin0 -> 40708 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff2bin0 -> 37736 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.ttfbin0 -> 103704 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woffbin0 -> 49132 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff2bin0 -> 40404 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.ttfbin0 -> 101012 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woffbin0 -> 45572 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff2bin0 -> 37568 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-Bold.otfbin0 -> 112176 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-BoldItalic.otfbin0 -> 120580 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-DemiBold.otfbin0 -> 110188 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-DemiBoldItalic.otfbin0 -> 121136 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-ExtraBold.otfbin0 -> 111532 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-ExtraBoldItalic.otfbin0 -> 120080 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-ExtraLight.otfbin0 -> 108024 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-ExtraLightItalic.otfbin0 -> 118496 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-Heavy.otfbin0 -> 113700 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-HeavyItalic.otfbin0 -> 123024 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-Light.otfbin0 -> 108372 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-LightItalic.otfbin0 -> 118272 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-Regular.otfbin0 -> 107884 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-RegularItalic.otfbin0 -> 117452 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-Thin.otfbin0 -> 105640 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CartographCF-ThinItalic.otfbin0 -> 116284 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CodeliaLigatures-Bold.otfbin0 -> 118064 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CodeliaLigatures-BoldItalic.otfbin0 -> 117860 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CodeliaLigatures-Italic.otfbin0 -> 114384 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/CodeliaLigatures-Regular.otfbin0 -> 116684 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Bold.otfbin0 -> 92016 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-BoldItalic.otfbin0 -> 92188 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Italic.otfbin0 -> 95120 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Light.otfbin0 -> 95088 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-LightItalic.otfbin0 -> 96648 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Medium.otfbin0 -> 94056 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-MediumItalic.otfbin0 -> 95256 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Regular.otfbin0 -> 93004 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-SBIta.otfbin0 -> 96380 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Semibold.otfbin0 -> 94744 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-Thin.otfbin0 -> 89560 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-ThinItalic.otfbin0 -> 90044 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-ULIta.otfbin0 -> 97832 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/ComicCodeLigatures-UltraLight.otfbin0 -> 95728 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Courier 10 Pitch Regular.otfbin0 -> 35196 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/MERIFONT.TTFbin0 -> 49504 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-Black.ttfbin0 -> 141700 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-BlackItalic.ttfbin0 -> 142620 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-Bold.ttfbin0 -> 142040 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-BoldItalic.ttfbin0 -> 143832 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-Italic.ttfbin0 -> 142648 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-Light.ttfbin0 -> 148124 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-LightItalic.ttfbin0 -> 142056 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/Merriweather-Regular.ttfbin0 -> 149120 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/MonoLisa-Bold.otfbin0 -> 118736 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/MonoLisa-BoldItalic.otfbin0 -> 119056 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/MonoLisa-Regular.otfbin0 -> 116244 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/MonoLisa-RegularItalic.otfbin0 -> 116892 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-Bold.otfbin0 -> 64528 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-BoldItalic.otfbin0 -> 66320 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBold.otfbin0 -> 64428 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBoldItalic.otfbin0 -> 65864 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBold.otfbin0 -> 63976 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBoldItalic.otfbin0 -> 65820 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-Heavy.otfbin0 -> 63884 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-HeavyItalic.otfbin0 -> 66264 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-Light.otfbin0 -> 64140 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-LightItalic.otfbin0 -> 66732 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-Medium.otfbin0 -> 64364 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-MediumItalic.otfbin0 -> 66216 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-Regular.otfbin0 -> 64392 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/NovaletraSerifCF-RegularItalic.otfbin0 -> 66240 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProB_09.ttfbin0 -> 4607292 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProB_liga_09.ttfbin0 -> 4624112 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProI_09.ttfbin0 -> 4490692 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProI_liga_09.ttfbin0 -> 4507588 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProR_09.ttfbin0 -> 5051440 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProR_liga_09.ttfbin0 -> 5068260 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProZ_09.ttfbin0 -> 4439452 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataProZ_liga_09.ttfbin0 -> 4456268 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_09.ttfbin0 -> 3900260 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_liga_09.ttfbin0 -> 3917076 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_09.ttfbin0 -> 3822344 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_liga_09.ttfbin0 -> 3839140 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_09.ttfbin0 -> 4233500 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_liga_09.ttfbin0 -> 4250320 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_09.ttfbin0 -> 3752628 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_liga_09.ttfbin0 -> 3769444 bytes
-rw-r--r--dotfiles/system/.local/share/fonts/all-the-icons.ttfbin0 -> 44732 bytes
-rw-r--r--dotfiles/system/.local/share/thequestionconcerningtechnology.txt180
247 files changed, 5720 insertions, 0 deletions
diff --git a/dotfiles/system/.local/bin/AAXtoMP3 b/dotfiles/system/.local/bin/AAXtoMP3
new file mode 100755
index 0000000..adc91ef
--- /dev/null
+++ b/dotfiles/system/.local/bin/AAXtoMP3
@@ -0,0 +1,908 @@
+#!/usr/bin/env bash
+
+
+# ========================================================================
+# Command Line Options
+
+# Usage Synopsis.
+usage=$'\nUsage: AAXtoMP3 [--flac] [--aac] [--opus ] [--single] [--level <COMPRESSIONLEVEL>]
+[--chaptered] [-e:mp3] [-e:m4a] [-e:m4b] [--authcode <AUTHCODE>] [--no-clobber]
+[--target_dir <PATH>] [--complete_dir <PATH>] [--validate] [--loglevel <LOGLEVEL>]
+[--keep-author <N>] [--author <AUTHOR>] [--{dir,file,chapter}-naming-scheme <STRING>]
+[--use-audible-cli-data] [--continue <CHAPTERNUMBER>] {FILES}\n'
+codec=libmp3lame # Default encoder.
+extension=mp3 # Default encoder extension.
+level=-1 # Compression level. Can be given for mp3, flac and opus. -1 = default/not specified.
+mode=chaptered # Multi file output
+auth_code= # Required to be set via file or option.
+targetdir= # Optional output location. Note default is basedir of AAX file.
+dirNameScheme= # Custom directory naming scheme, default is $genre/$author/$title
+customDNS=0
+fileNameScheme= # Custom file naming scheme, default is $title
+customFNS=0
+chapterNameScheme= # Custom chapter naming scheme, default is '$title-$(printf %0${#chaptercount}d $chapternum) $chapter' (BookTitle-01 Chapter 1)
+customCNS=0
+completedir= # Optional location to move aax files once the decoding is complete.
+container=mp3 # Just in case we need to change the container. Used for M4A to M4B
+VALIDATE=0 # Validate the input aax file(s) only. No Transcoding of files will occur
+loglevel=1 # Loglevel: 0: Show progress only; 1: default; 2: a little more information, timestamps; 3: debug
+noclobber=0 # Default off, clobber only if flag is enabled
+continue=0 # Default off, If set Transcoding is skipped and chapter splitting starts at chapter continueAt.
+continueAt=1 # Optional chapter to continue splitting the chapters.
+keepArtist=-1 # Default off, if set change author metadata to use the passed argument as field
+authorOverride= # Override the author, ignoring the metadata
+audibleCli=0 # Default off, Use additional data gathered from mkb79/audible-cli
+aaxc_key= # Initialize variables, in case we need them in debug_vars
+aaxc_iv= # Initialize variables, in case we need them in debug_vars
+
+# -----
+# Code tip Do not have any script above this point that calls a function or a binary. If you do
+# the $1 will no longer be a ARGV element. So you should only do basic variable setting above here.
+#
+# Process the command line options. This allows for un-ordered options. Sorta like a getops style
+while true; do
+ case "$1" in
+ # Flac encoding
+ -f | --flac ) codec=flac; extension=flac; mode=single; container=flac; shift ;;
+ # Apple m4a music format.
+ -a | --aac ) codec=copy; extension=m4a; mode=single; container=m4a; shift ;;
+ # Ogg Format
+ -o | --opus ) codec=libopus; extension=opus; container=ogg; shift ;;
+ # If appropriate use only a single file output.
+ -s | --single ) mode=single; shift ;;
+ # If appropriate use only a single file output.
+ -c | --chaptered ) mode=chaptered; shift ;;
+ # This is the same as --single option.
+ -e:mp3 ) codec=libmp3lame; extension=mp3; mode=single; container=mp3; shift ;;
+ # Identical to --acc option.
+ -e:m4a ) codec=copy; extension=m4a; mode=single; container=mp4; shift ;;
+ # Similar to --aac but specific to audio books
+ -e:m4b ) codec=copy; extension=m4b; mode=single; container=mp4; shift ;;
+ # Change the working dir from AAX directory to what you choose.
+ -t | --target_dir ) targetdir="$2"; shift 2 ;;
+ # Use a custom directory naming scheme, with variables.
+ -D | --dir-naming-scheme ) dirNameScheme="$2"; customDNS=1; shift 2 ;;
+ # Use a custom file naming scheme, with variables.
+ -F | --file-naming-scheme ) fileNameScheme="$2"; customFNS=1; shift 2 ;;
+ # Use a custom chapter naming scheme, with variables.
+ --chapter-naming-scheme ) chapterNameScheme="$2"; customCNS=1; shift 2 ;;
+ # Move the AAX file to a new directory when decoding is complete.
+ -C | --complete_dir ) completedir="$2"; shift 2 ;;
+ # Authorization code associate with the AAX file(s)
+ -A | --authcode ) auth_code="$2"; shift 2 ;;
+ # Don't overwrite the target directory if it already exists
+ -n | --no-clobber ) noclobber=1; shift ;;
+ # Extremely verbose output.
+ -d | --debug ) loglevel=3; shift ;;
+ # Set loglevel.
+ -l | --loglevel ) loglevel="$2"; shift 2 ;;
+ # Validate ONLY the aax file(s) No transcoding occurs
+ -V | --validate ) VALIDATE=1; shift ;;
+ # continue splitting chapters at chapter continueAt
+ --continue ) continueAt="$2"; continue=1; shift 2 ;;
+ # Use additional data got with mkb79/audible-cli
+ --use-audible-cli-data ) audibleCli=1; shift ;;
+ # Compression level
+ --level ) level="$2"; shift 2 ;;
+ # Keep author number n
+ --keep-author ) keepArtist="$2"; shift 2 ;;
+ # Author override
+ --author ) authorOverride="$2"; shift 2 ;;
+ # Command synopsis.
+ -h | --help ) printf "$usage" $0 ; exit ;;
+ # Standard flag signifying the end of command line processing.
+ -- ) shift; break ;;
+ # Anything else stops command line processing.
+ * ) break ;;
+
+ esac
+done
+
+# -----
+# Empty argv means we have nothing to do so lets bark some help.
+if [ "$#" -eq 0 ]; then
+ printf "$usage" $0
+ exit 1
+fi
+
+# Setup safer bash script defaults.
+set -o errexit -o noclobber -o nounset -o pipefail
+
+# ========================================================================
+# Utility Functions
+
+# -----
+# debug
+# debug "Some longish message"
+debug() {
+ if [ $loglevel == 3 ] ; then
+ echo "$(date "+%F %T%z") DEBUG ${1}"
+ fi
+}
+
+# -----
+# debug dump contents of a file to STDOUT
+# debug "<full path to file>"
+debug_file() {
+ if [ $loglevel == 3 ] ; then
+ echo "$(date "+%F %T%z") DEBUG"
+ echo "=Start=========================================================================="
+ cat "${1}"
+ echo "=End============================================================================"
+ fi
+}
+
+# -----
+# debug dump a list of internal script variables to STDOUT
+# debug_vars "Some Message" var1 var2 var3 var4 var5
+debug_vars() {
+ if [ $loglevel == 3 ] ; then
+ msg="$1"; shift ; # Grab the message
+ args=("$@") # Grab the rest of the args
+
+ # determine the length of the longest key
+ l=0
+ for (( n=0; n<${#args[@]}; n++ )) ; do
+ (( "${#args[$n]}" > "$l" )) && l=${#args[$n]}
+ done
+
+ # Print the Debug Message
+ echo "$(date "+%F %T%z") DEBUG ${msg}"
+ echo "=Start=========================================================================="
+
+ # Using the max length of a var name we dynamically create the format.
+ fmt="%-"${l}"s = %s\n"
+
+ for (( n=0; n<${#args[@]}; n++ )) ; do
+ eval val="\$${args[$n]}" ; # We save off the value of the var in question for ease of coding.
+
+ echo "$(printf "${fmt}" ${args[$n]} "${val}" )"
+ done
+ echo "=End============================================================================"
+ fi
+}
+
+# -----
+# log
+log() {
+ if [ "$((${loglevel} > 1))" == "1" ] ; then
+ echo "$(date "+%F %T%z") ${1}"
+ else
+ echo "${1}"
+ fi
+}
+
+# -----
+#progressbar produces a progressbar in the style of
+# process: |####### | XX% (part/total unit)
+# which is gonna be overwritten by the next line.
+
+progressbar() {
+ #get input
+ part=${1}
+ total=${2}
+
+ #compute percentage and make print_percentage the same length regardless of the number of digits.
+ percentage=$((part*100/total))
+ if [ "$((percentage<10))" = "1" ]; then print_percentage=" $percentage"
+ elif [ "$((percentage<100))" = "1" ]; then print_percentage=" $percentage"
+ else print_percentage="$percentage"; fi
+
+ #draw progressbar with one # for every 5% and blank spaces for the missing part.
+ progressbar=""
+ for (( n=0; n<(percentage/5); n++ )) ; do progressbar="$progressbar#"; done
+ for (( n=0; n<(20-(percentage/5)); n++ )) ; do progressbar="$progressbar "; done
+
+ #print progressbar
+ echo -ne "Chapter splitting: |$progressbar| $print_percentage% ($part/$total chapters)\r"
+}
+# Print out what we have already after command line processing.
+debug_vars "Command line options as set" codec extension mode container targetdir completedir auth_code keepArtist authorOverride audibleCli
+
+# ========================================================================
+# Variable validation
+
+if [ $(uname) = 'Linux' ]; then
+ GREP="grep"
+ FIND="find"
+ SED="sed"
+else
+ GREP="ggrep"
+ FIND="gfind"
+ SED="gsed"
+fi
+
+
+# -----
+# Detect which annoying version of grep we have
+if ! [[ $(type -P "$GREP") ]]; then
+ echo "$GREP (GNU grep) is not in your PATH"
+ echo "Without it, this script will break."
+ echo "On macOS, you may want to try: brew install grep"
+ exit 1
+fi
+
+# -----
+# Detect which annoying version of find we have
+if ! [[ $(type -P "$FIND") ]]; then
+ echo "$FIND (GNU find) is not in your PATH"
+ echo "Without it, this script will break."
+ echo "On macOS, you may want to try: brew install findutils"
+ exit 1
+fi
+
+# -----
+# Detect which annoying version of sed we have
+if ! [[ $(type -P "$SED") ]]; then
+ echo "$SED (GNU sed) is not in your PATH"
+ echo "Without it, this script will break."
+ echo "On macOS, you may want to try: brew install gnu-sed"
+ exit 1
+fi
+
+# -----
+# Detect ffmpeg and ffprobe
+if [[ "x$(type -P ffmpeg)" == "x" ]]; then
+ echo "ERROR ffmpeg was not found on your env PATH variable"
+ echo "Without it, this script will break."
+ echo "INSTALL:"
+ echo "MacOS: brew install ffmpeg"
+ echo "Ubuntu: sudo apt-get update; sudo apt-get install ffmpeg libav-tools x264 x265 bc"
+ echo "Ubuntu (20.04): sudo apt-get update; sudo apt-get install ffmpeg x264 x265 bc"
+ echo "RHEL: yum install ffmpeg"
+ exit 1
+fi
+
+# -----
+# Detect ffmpeg and ffprobe
+if [[ "x$(type -P ffprobe)" == "x" ]]; then
+ echo "ERROR ffprobe was not found on your env PATH variable"
+ echo "Without it, this script will break."
+ echo "INSTALL:"
+ echo "MacOS: brew install ffmpeg"
+ echo "Ubuntu: sudo apt-get update; sudo apt-get install ffmpeg libav-tools x264 x265 bc"
+ echo "RHEL: yum install ffmpeg"
+ exit 1
+fi
+
+
+# -----
+# Detect if we need mp4art for cover additions to m4a & m4b files.
+if [[ "x${container}" == "xmp4" && "x$(type -P mp4art)" == "x" ]]; then
+ echo "WARN mp4art was not found on your env PATH variable"
+ echo "Without it, this script will not be able to add cover art to"
+ echo "m4b files. Note if there are no other errors the AAXtoMP3 will"
+ echo "continue. However no cover art will be added to the output."
+ echo "INSTALL:"
+ echo "MacOS: brew install mp4v2"
+ echo "Ubuntu: sudo apt-get install mp4v2-utils"
+fi
+
+# -----
+# Detect if we need mp4chaps for adding chapters to m4a & m4b files.
+if [[ "x${container}" == "xmp4" && "x$(type -P mp4chaps)" == "x" ]]; then
+ echo "WARN mp4chaps was not found on your env PATH variable"
+ echo "Without it, this script will not be able to add chapters to"
+ echo "m4a/b files. Note if there are no other errors the AAXtoMP3 will"
+ echo "continue. However no chapter data will be added to the output."
+ echo "INSTALL:"
+ echo "MacOS: brew install mp4v2"
+ echo "Ubuntu: sudo apt-get install mp4v2-utils"
+fi
+
+# -----
+# Detect if we need mediainfo for adding description and narrator
+if [[ "x$(type -P mediainfo)" == "x" ]]; then
+ echo "WARN mediainfo was not found on your env PATH variable"
+ echo "Without it, this script will not be able to add the narrator"
+ echo "and description tags. Note if there are no other errors the AAXtoMP3"
+ echo "will continue. However no such tags will be added to the output."
+ echo "INSTALL:"
+ echo "MacOS: brew install mediainfo"
+ echo "Ubuntu: sudo apt-get install mediainfo"
+fi
+
+# -----
+# Obtain the authcode from either the command line, local directory or home directory.
+# See Readme.md for details on how to acquire your personal authcode for your personal
+# audible AAX files.
+if [ -z $auth_code ]; then
+ if [ -r .authcode ]; then
+ auth_code=`head -1 .authcode`
+ elif [ -r ~/.authcode ]; then
+ auth_code=`head -1 ~/.authcode`
+ fi
+fi
+
+# -----
+# Check the target dir for if set if it is writable
+if [[ "x${targetdir}" != "x" ]]; then
+ if [[ ! -w "${targetdir}" || ! -d "${targetdir}" ]] ; then
+ echo "ERROR Target Directory does not exist or is not writable: \"$targetdir\""
+ echo "$usage"
+ exit 1
+ fi
+fi
+
+# -----
+# Check the completed dir for if set if it is writable
+if [[ "x${completedir}" != "x" ]]; then
+ if [[ ! -w "${completedir}" || ! -d "${completedir}" ]] ; then
+ echo "ERROR Complete Directory does not exist or is not writable: \"$completedir\""
+ echo "$usage"
+ exit 1
+ fi
+fi
+
+# -----
+# Check whether the loglevel is valid
+if [ "$((${loglevel} < 0 || ${loglevel} > 3 ))" = "1" ]; then
+ echo "ERROR loglevel has to be in the range from 0 to 3!"
+ echo " 0: Show progress only"
+ echo " 1: default"
+ echo " 2: a little more information, timestamps"
+ echo " 3: debug"
+ echo "$usage"
+ exit 1
+fi
+# -----
+# If a compression level is given, check whether the given codec supports compression level specifiers and whether the level is valid.
+if [ "${level}" != "-1" ]; then
+ if [ "${codec}" == "flac" ]; then
+ if [ "$((${level} < 0 || ${level} > 12 ))" = "1" ]; then
+ echo "ERROR Flac compression level has to be in the range from 0 to 12!"
+ echo "$usage"
+ exit 1
+ fi
+ elif [ "${codec}" == "libopus" ]; then
+ if [ "$((${level} < 0 || ${level} > 10 ))" = "1" ]; then
+ echo "ERROR Opus compression level has to be in the range from 0 to 10!"
+ echo "$usage"
+ exit 1
+ fi
+ elif [ "${codec}" == "libmp3lame" ]; then
+ if [ "$((${level} < 0 || ${level} > 9 ))" = "1" ]; then
+ echo "ERROR MP3 compression level has to be in the range from 0 to 9!"
+ echo "$usage"
+ exit 1
+ fi
+ else
+ echo "ERROR This codec doesnt support compression levels!"
+ echo "$usage"
+ exit 1
+ fi
+fi
+
+# -----
+# Clean up if someone hits ^c or the script exits for any reason.
+trap 'rm -r -f "${working_directory}"' EXIT
+
+# -----
+# Set up some basic working files ASAP. Note the trap will clean this up no matter what.
+working_directory=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`
+metadata_file="${working_directory}/metadata.txt"
+
+# -----
+# Validate the AAX and extract the metadata associated with the file.
+validate_aax() {
+ local media_file
+ media_file="$1"
+
+ # Test for existence
+ if [[ ! -r "${media_file}" ]] ; then
+ log "ERROR File NOT Found: ${media_file}"
+ return 1
+ else
+ if [[ "${VALIDATE}" == "1" ]]; then
+ log "Test 1 SUCCESS: ${media_file}"
+ fi
+ fi
+
+ # Clear the errexit value we want to capture the output of the ffprobe below.
+ set +e errexit
+
+ # Take a look at the aax file and see if it is valid. If the source file is aaxc, we give ffprobe additional flags
+ output="$(ffprobe -loglevel warning ${decrypt_param} -i "${media_file}" 2>&1)"
+
+ # If invalid then say something.
+ if [[ $? != "0" ]] ; then
+ # No matter what lets bark that something is wrong.
+ log "ERROR: Invalid File: ${media_file}"
+ elif [[ "${VALIDATE}" == "1" ]]; then
+ # If the validate option is present then lets at least state what is valid.
+ log "Test 2 SUCCESS: ${media_file}"
+ fi
+
+ # This is a big test only performed when the --validate switch is passed.
+ if [[ "${VALIDATE}" == "1" ]]; then
+ output="$(ffmpeg -hide_banner ${decrypt_param} -i "${media_file}" -vn -f null - 2>&1)"
+ if [[ $? != "0" ]] ; then
+ log "ERROR: Invalid File: ${media_file}"
+ else
+ log "Test 3 SUCCESS: ${media_file}"
+ fi
+ fi
+
+ # Dump the output of the ffprobe command.
+ debug "$output"
+
+ # Turn it back on. ffprobe is done.
+ set -e errexit
+}
+
+validate_extra_files() {
+ local extra_media_file extra_find_command
+ extra_media_file="$1"
+ # Bash trick to delete, non greedy, from the end up until the first '-'
+ extra_title="${extra_media_file%-*}"
+
+ # Using this is not ideal, because if the naming scheme is changed then
+ # this part of the script will break
+ # AAX file: BookTitle-LC_128_44100_stereo.aax
+ # Cover file: BookTitle_(1215).jpg
+ # Chapter file: BookTitle-chapters.json
+
+ # Chapter
+ extra_chapter_file="${extra_title}-chapters.json"
+
+ # Cover
+ extra_dirname="$(dirname "${extra_media_file}")"
+ extra_find_command='$FIND "${extra_dirname}" -maxdepth 1 -regex ".*/${extra_title##*/}_([0-9]+)\.jpg"'
+ # We want the output of the find command, we will turn errexit on later
+ set +e errexit
+ extra_cover_file="$(eval ${extra_find_command})"
+ extra_eval_comm="$(eval echo ${extra_find_command})"
+ set -e errexit
+
+ if [[ "${aaxc}" == "1" ]]; then
+ # bash trick to get file w\o extention (delete from end to the first '.')
+ extra_voucher="${extra_media_file%.*}.voucher"
+ if [[ ! -r "${extra_voucher}" ]] ; then
+ log "ERROR File NOT Found: ${extra_voucher}"
+ return 1
+ fi
+ aaxc_key=$(jq -r '.content_license.license_response.key' "${extra_voucher}")
+ aaxc_iv=$(jq -r '.content_license.license_response.iv' "${extra_voucher}")
+ fi
+
+ debug_vars "Audible-cli variables" extra_media_file extra_title extra_chapter_file extra_cover_file extra_find_command extra_eval_comm extra_dirname extra_voucher aaxc_key aaxc_iv
+
+ # Test for chapter file existence
+ if [[ ! -r "${extra_chapter_file}" ]] ; then
+ log "ERROR File NOT Found: ${extra_chapter_file}"
+ return 1
+ fi
+ if [[ "x${extra_cover_file}" == "x" ]] ; then
+ log "ERROR Cover File NOT Found"
+ return 1
+ fi
+
+ debug "All expected audible-cli related file are here"
+}
+
+# -----
+# Inspect the AAX and extract the metadata associated with the file.
+save_metadata() {
+ local media_file
+ media_file="$1"
+ ffprobe -i "$media_file" 2> "$metadata_file"
+ if [[ $(type -P mediainfo) ]]; then
+ echo "Mediainfo data START" >> "$metadata_file"
+ # Mediainfo output is structured like ffprobe, so we append it to the metadata file and then parse it with get_metadata_value()
+ # mediainfo "$media_file" >> "$metadata_file"
+ # Or we only get the data we are intrested in:
+ # Description
+ echo "Track_More :" "$(mediainfo --Inform="General;%Track_More%" "$media_file")" >> "$metadata_file"
+ # Narrator
+ echo "nrt :" "$(mediainfo --Inform="General;%nrt%" "$media_file")" >> "$metadata_file"
+ # Publisher
+ echo "pub :" "$(mediainfo --Inform="General;%pub%" "$media_file")" >> "$metadata_file"
+ echo "Mediainfo data END" >> "$metadata_file"
+ fi
+ if [[ "${audibleCli}" == "1" ]]; then
+ # If we use data we got with audible-cli, we delete conflicting chapter infos
+ $SED -i '/^ Chapter #/d' "${metadata_file}"
+ # Some magic: we parse the .json generated by audible-cli.
+ # to get the output structure like the one generated by ffprobe,
+ # we use some characters (#) as placeholder, add some new lines,
+ # put a ',' after the start value, we calculate the end of each chapter
+ # as start+length, and we convert (divide) the time stamps from ms to s.
+ # Then we delete all ':' since they make a filename invalid.
+ jq -r '.content_metadata.chapter_info.chapters[] | "Chapter # start: \(.start_offset_ms/1000), end: \((.start_offset_ms+.length_ms)/1000) \n#\n# Title: \(.title)"' "${extra_chapter_file}" \
+ | tr -d ':' >> "$metadata_file"
+ fi
+ debug "Metadata file $metadata_file"
+ debug_file "$metadata_file"
+}
+
+# -----
+# Reach into the meta data and extract a specific value.
+# This is a long pipe of transforms.
+# This finds the first occurrence of the key : value pair.
+get_metadata_value() {
+ local key
+ key="$1"
+ # Find the key in the meta data file # Extract field value # Remove the following /'s "(Unabridged) <blanks> at start end and multiples.
+ echo "$($GREP --max-count=1 --only-matching "${key} *: .*" "$metadata_file" | cut -d : -f 2- | $SED -e 's#/##g;s/ (Unabridged)//;s/^[[:blank:]]\+//g;s/[[:blank:]]\+$//g' | $SED 's/[[:blank:]]\+/ /g')"
+}
+
+# -----
+# specific variant of get_metadata_value bitrate is important for transcoding.
+get_bitrate() {
+ get_metadata_value bitrate | $GREP --only-matching '[0-9]\+'
+}
+
+# Save the original value, since in the for loop we overwrite
+# $audibleCli in case the file is aaxc. If the file is the
+# old aax, reset the variable to be the one passed by the user
+originalAudibleCliVar=$audibleCli
+# ========================================================================
+# Main Transcode Loop
+for aax_file
+do
+ # If the file is in aaxc format, set the proper variables
+ if [[ ${aax_file##*.} == "aaxc" ]]; then
+ # File is the new .aaxc
+ aaxc=1
+ audibleCli=1
+ else
+ # File is the old .aax
+ aaxc=0
+ # If some previous file in the loop are aaxc, the $audibleCli variable has been overwritten, so we reset it to the original one
+ audibleCli=$originalAudibleCliVar
+ fi
+
+ debug_vars "Variables set based on file extention" aaxc originalAudibleCliVar audibleCli
+
+ # No point going on if no authcode found and the file is aax.
+ # If we use aaxc as input, we do not need it
+ # if the string $auth_code is null and the format is not aaxc; quit. We need the authcode
+ if [ -z $auth_code ] && [ "${aaxc}" = "0" ]; then
+ echo "ERROR Missing authcode, can't decode $aax_file"
+ echo "$usage"
+ exit 1
+ fi
+
+ # Validate the input aax file. Note this happens no matter what.
+ # It's just that if the validate option is set then we skip to next file.
+ # If however validate is not set and we proceed with the script any errors will
+ # case the script to stop.
+
+ # If the input file is aaxc, we need to first get the audible_key and audible_iv
+ # We get them in the function validate_extra_files
+
+ if [[ ${audibleCli} == "1" ]] ; then
+ # If we have additional files (obtained via audible-cli), be sure that they
+ # exists and they are in the correct location.
+ validate_extra_files "${aax_file}"
+ fi
+
+ # Set the needed params to decrypt the file. Needed in all command that require ffprobe or ffmpeg
+ # After validate_extra_files, since the -audible_key and -audible_iv are read in that function
+ if [[ ${aaxc} == "1" ]] ; then
+ decrypt_param="-audible_key ${aaxc_key} -audible_iv ${aaxc_iv}"
+ else
+ decrypt_param="-activation_bytes ${auth_code}"
+ fi
+
+ validate_aax "${aax_file}"
+ if [[ ${VALIDATE} == "1" ]] ; then
+ # Don't bother doing anything else with this file.
+ continue
+ fi
+
+ # -----
+ # Make sure everything is a variable. Simplifying Command interpretation
+ save_metadata "${aax_file}"
+ genre=$(get_metadata_value genre)
+ if [ "x${authorOverride}" != "x" ]; then
+ #Manual Override
+ artist="${authorOverride}"
+ album_artist="${authorOverride}"
+ else
+ if [ "${keepArtist}" != "-1" ]; then
+ # Choose artist from the one that are present in the metadata. Comma separated list of names
+ # remove leading space; 'C. S. Lewis' -> 'C.S. Lewis'
+ artist="$(get_metadata_value artist | cut -d',' -f"$keepArtist" | $SED -E 's|^ ||g; s|\. +|\.|g; s|((\w+\.)+)|\1 |g')"
+ album_artist="$(get_metadata_value album_artist | cut -d',' -f"$keepArtist" | $SED -E 's|^ ||g; s|\. +|\.|g; s|((\w+\.)+)|\1 |g')"
+ else
+ # The default
+ artist=$(get_metadata_value artist)
+ album_artist="$(get_metadata_value album_artist)"
+ fi
+ fi
+ title=$(get_metadata_value title)
+ title=${title:0:128}
+ bitrate="$(get_bitrate)k"
+ album="$(get_metadata_value album)"
+ album_date="$(get_metadata_value date)"
+ copyright="$(get_metadata_value copyright)"
+
+ # Get more tags with mediainfo
+ if [[ $(type -P mediainfo) ]]; then
+ narrator="$(get_metadata_value nrt)"
+ description="$(get_metadata_value Track_More)"
+ publisher="$(get_metadata_value pub)"
+ else
+ narrator=""
+ description=""
+ publisher=""
+ fi
+
+ # Define the output_directory
+ if [ "${customDNS}" == "1" ]; then
+ currentDirNameScheme="$(eval echo "${dirNameScheme}")"
+ else
+ # The Default
+ currentDirNameScheme="${genre}/${artist}/${title}"
+ fi
+
+ # If we defined a target directory, use it. Otherwise use the location of the AAX file
+ if [ "x${targetdir}" != "x" ] ; then
+ output_directory="${targetdir}/${currentDirNameScheme}/"
+ else
+ output_directory="$(dirname "${aax_file}")/${currentDirNameScheme}/"
+ fi
+
+ # Define the output_file
+ if [ "${customFNS}" == "1" ]; then
+ currentFileNameScheme="$(eval echo "${fileNameScheme}")"
+ else
+ # The Default
+ currentFileNameScheme="${title}"
+ fi
+ output_file="${output_directory}/${currentFileNameScheme}.${extension}"
+
+ if [[ "${noclobber}" = "1" ]] && [[ -d "${output_directory}" ]]; then
+ log "Noclobber enabled but directory '${output_directory}' exists. Exiting to avoid overwriting"
+ exit 0
+ fi
+ mkdir -p "${output_directory}"
+
+ if [ "$((${loglevel} > 0))" = "1" ]; then
+ # Fancy declaration of which book we are decoding. Including the AUTHCODE.
+ dashline="----------------------------------------------------"
+ log "$(printf '\n----Decoding---%s%s--%s--' "${title}" "${dashline:${#title}}" "${auth_code}")"
+ log "Source: ${aax_file}"
+ fi
+
+ # Big long DEBUG output. Fully describes the settings used for transcoding.
+ # Note this is a long debug command. It's not critical to operation. It's purely for people debugging
+ # and coders wanting to extend the script.
+ debug_vars "Book and Variable values" title auth_code aaxc aaxc_key aaxc_iv mode aax_file container codec bitrate artist album_artist album album_date genre copyright narrator description publisher currentDirNameScheme output_directory currentFileNameScheme output_file metadata_file working_directory
+
+
+ # Display the total length of the audiobook in format hh:mm:ss
+ # 10#$var force base-10 interpretation. By default it's base-8, so values like 08 or 09 are not octal numbers
+ total_length="$(ffprobe -v error ${decrypt_param} -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${aax_file}" | cut -d . -f 1)"
+ hours="$((total_length/3600))"
+ if [ "$((hours<10))" = "1" ]; then hours="0$hours"; fi
+ minutes="$((total_length/60-60*10#$hours))"
+ if [ "$((minutes<10))" = "1" ]; then minutes="0$minutes"; fi
+ seconds="$((total_length-3600*10#$hours-60*10#$minutes))"
+ if [ "$((seconds<10))" = "1" ]; then seconds="0$seconds"; fi
+ log "Total length: $hours:$minutes:$seconds"
+
+ # If level != -1 specify a compression level in ffmpeg.
+ compression_level_param=""
+ if [ "${level}" != "-1" ]; then
+ compression_level_param="-compression_level ${level}"
+ fi
+
+ # -----
+ if [ "${continue}" == "0" ]; then
+ # This is the main work horse command. This is the primary transcoder.
+ # This is the primary transcode. All the heavy lifting is here.
+ debug 'ffmpeg -loglevel error -stats ${decrypt_param} -i "${aax_file}" -vn -codec:a "${codec}" -ab ${bitrate} -map_metadata -1 -metadata title="${title}" -metadata artist="${artist}" -metadata album_artist="${album_artist}" -metadata album="${album}" -metadata date="${album_date}" -metadata track="1/1" -metadata genre="${genre}" -metadata copyright="${copyright}" "${output_file}"'
+ </dev/null ffmpeg -loglevel error \
+ -stats \
+ ${decrypt_param} \
+ -i "${aax_file}" \
+ -vn \
+ -codec:a "${codec}" \
+ ${compression_level_param} \
+ -ab ${bitrate} \
+ -map_metadata -1 \
+ -metadata title="${title}" \
+ -metadata artist="${artist}" \
+ -metadata album_artist="${album_artist}" \
+ -metadata album="${album}" \
+ -metadata date="${album_date}" \
+ -metadata track="1/1" \
+ -metadata genre="${genre}" \
+ -metadata copyright="${copyright}" \
+ -metadata description="${description}" \
+ -metadata composer="${narrator}" \
+ -metadata publisher="${publisher}" \
+ -f ${container} \
+ "${output_file}"
+ if [ "$((${loglevel} > 0))" == "1" ]; then
+ log "Created ${output_file}."
+ fi
+ # -----
+ fi
+ # Grab the cover art if available.
+ cover_file="${output_directory}/cover.jpg"
+ extra_crop_cover=''
+ if [ "${continue}" == "0" ]; then
+ if [ "${audibleCli}" == "1" ]; then
+ # We have a better quality cover file, copy it.
+ if [ "$((${loglevel} > 1))" == "1" ]; then
+ log "Copy cover file to ${cover_file}..."
+ fi
+ cp "${extra_cover_file}" "${cover_file}"
+
+ # We now set a variable, ${extra_crop_cover}, which contains an additional
+ # ffmpeg flag. It crops the cover so the width and the height is divisible by two.
+ # Since the standard (in the aax file) image resolution is 512, we set the flag
+ # only if we use a custom cover art.
+ extra_crop_cover='-vf crop=trunc(iw/2)*2:trunc(ih/2)*2'
+ else
+ # Audible-cli not used, extract the cover from the aax file
+ if [ "$((${loglevel} > 1))" == "1" ]; then
+ log "Extracting cover into ${cover_file}..."
+ fi
+ </dev/null ffmpeg -loglevel error -activation_bytes "${auth_code}" -i "${aax_file}" -an -codec:v copy "${cover_file}"
+ fi
+ fi
+
+ # -----
+ # If mode=chaptered, split the big converted file by chapter and remove it afterwards.
+ # Not all audio encodings make sense with multiple chapter outputs (see options section)
+ if [ "${mode}" == "chaptered" ]; then
+ # Playlist m3u support
+ playlist_file="${output_directory}/${currentFileNameScheme}.m3u"
+ if [ "${continue}" == "0" ]; then
+ if [ "$((${loglevel} > 0))" == "1" ]; then
+ log "Creating PlayList ${currentFileNameScheme}.m3u"
+ fi
+ echo '#EXTM3U' > "${playlist_file}"
+ fi
+
+ # Determine the number of chapters.
+ chaptercount=$($GREP -Pc "Chapter.*start.*end" $metadata_file)
+ if [ "$((${loglevel} > 0))" == "1" ]; then
+ log "Extracting ${chaptercount} chapter files from ${output_file}..."
+ if [ "${continue}" == "1" ]; then
+ log "Continuing at chapter ${continueAt}:"
+ fi
+ fi
+ chapternum=1
+ #start progressbar for loglevel 0 and 1
+ if [ "$((${loglevel} < 2))" == "1" ]; then
+ progressbar 0 ${chaptercount}
+ fi
+ # We pipe the metadata_file in read.
+ # Example of the section that we are interested in:
+ #
+ # Chapter #0:0: start 0.000000, end 1928.231474
+ # Metadata:
+ # title : Chapter 1
+ #
+ # Then read the line in these variables:
+ # first Chapter
+ # _ #0:0:
+ # _ start
+ # chapter_start 0.000000,
+ # _ end
+ # chapter_end 1928.231474
+ while read -r -u9 first _ _ chapter_start _ chapter_end
+ do
+ # Do things only if the line starts with 'Chapter'
+ if [[ "${first}" = "Chapter" ]]; then
+ # The next line (Metadata:...) gets discarded
+ read -r -u9 _
+ # From the line 'title : Chapter 1' we save the third field and those after in chapter
+ read -r -u9 _ _ chapter
+
+ # The formatting of the chapters names and the file names.
+ # Chapter names are used in a few place.
+ # Define the chapter_file
+ if [ "${customCNS}" == "1" ]; then
+ chapter_title="$(eval echo "${chapterNameScheme}")"
+ else
+ # The Default
+ chapter_title="${title}-$(printf %0${#chaptercount}d $chapternum) ${chapter}"
+ fi
+ chapter_file="${output_directory}/${chapter_title}.${extension}"
+
+ # Since the .aax file allready got converted we can use
+ # -acodec copy, which is much faster than a reencodation.
+ # Since there is an issue when using copy on flac, where
+ # the duration of the chapters gets shown as if they where
+ # as long as the whole audiobook.
+ chapter_codec=""
+ if test "${extension}" = "flac"; then
+ chapter_codec="flac "${compression_level_param}""
+ else
+ chapter_codec="copy"
+ fi
+
+ #Since there seems to be a bug in some older versions of ffmpeg, which makes, that -ss and -to
+ #have to be apllied to the output file, this makes, that -ss and -to get applied on the input for
+ #ffmpeg version 4+ and on the output for all older versions.
+ split_input=""
+ split_output=""
+ if [ "$(($(ffmpeg -version | $SED -E 's/[^0-9]*([0-9]).*/\1/g;1q') > 3))" = "1" ]; then
+ split_input="-ss ${chapter_start%?} -to ${chapter_end}"
+ else
+ split_output="-ss ${chapter_start%?} -to ${chapter_end}"
+ fi
+
+ # Big Long chapter debug
+ debug_vars "Chapter Variables:" cover_file chapter_start chapter_end chapternum chapter chapterNameScheme chapter_title chapter_file
+ if [ "$((${continueAt} > ${chapternum}))" = "0" ]; then
+ # Extract chapter by time stamps start and finish of chapter.
+ # This extracts based on time stamps start and end.
+ if [ "$((${loglevel} > 1))" == "1" ]; then
+ log "Splitting chapter ${chapternum}/${chaptercount} start:${chapter_start%?}(s) end:${chapter_end}(s)"
+ fi
+ </dev/null ffmpeg -loglevel quiet \
+ -nostats \
+ ${split_input} \
+ -i "${output_file}" \
+ -i "${cover_file}" \
+ ${extra_crop_cover} \
+ ${split_output} \
+ -map 0:0 \
+ -map 1:0 \
+ -acodec ${chapter_codec} \
+ -metadata:s:v title="Album cover" \
+ -metadata:s:v comment="Cover (Front)" \
+ -metadata track="${chapternum}" \
+ -metadata title="${chapter}" \
+ -metadata:s:a title="${chapter}" \
+ -metadata:s:a track="${chapternum}" \
+ -map_chapters -1 \
+ -f ${container} \
+ "${chapter_file}"
+ # -----
+ if [ "$((${loglevel} < 2))" == "1" ]; then
+ progressbar ${chapternum} ${chaptercount}
+ fi
+ # OK lets get what need for the next chapter in the Playlist m3u file.
+ # Playlist creation.
+ duration=$(echo "${chapter_end} - ${chapter_start%?}" | bc)
+ echo "#EXTINF:${duration%.*},${title} - ${chapter}" >> "${playlist_file}"
+ echo "${chapter_title}.${extension}" >> "${playlist_file}"
+ fi
+ chapternum=$((chapternum + 1 ))
+ fi
+ done 9< "$metadata_file"
+
+ # Clean up of working directory stuff.
+ rm "${output_file}"
+ if [ "$((${loglevel} > 1))" == "1" ]; then
+ log "Done creating chapters for ${output_directory}."
+ else
+ #ending progress bar
+ echo ""
+ fi
+ else
+ # Perform file tasks on output file.
+ # ----
+ # ffmpeg seems to copy only chapter position, not chapter names.
+ if [[ ${container} == "mp4" && $(type -P mp4chaps) ]]; then
+ ffprobe -i "${aax_file}" -print_format csv -show_chapters 2>/dev/null | awk -F "," '{printf "CHAPTER%02d=%02d:%02d:%02.3f\nCHAPTER%02dNAME=%s\n", NR, $5/60/60, $5/60%60, $5%60, NR, $8}' > "${output_directory}/${currentFileNameScheme}.chapters.txt"
+ mp4chaps -i "${output_file}"
+ fi
+ fi
+
+ # -----
+ # Announce that we have completed the transcode
+ if [ "$((${loglevel} > 0))" == "1" ]; then
+ log "Complete ${title}"
+ fi
+ # Lastly get rid of any extra stuff.
+ rm "${metadata_file}"
+
+ # Move the aax file if the decode is completed and the --complete_dir is set to a valid location.
+ # Check the target dir for if set if it is writable
+ if [[ "x${completedir}" != "x" ]]; then
+ if [ "$((${loglevel} > 0))" == "1" ]; then
+ log "Moving Transcoded ${aax_file} to ${completedir}"
+ fi
+ mv "${aax_file}" "${completedir}"
+ fi
+
+done
diff --git a/dotfiles/system/.local/bin/airplanemodetoggle b/dotfiles/system/.local/bin/airplanemodetoggle
new file mode 100755
index 0000000..c98e144
--- /dev/null
+++ b/dotfiles/system/.local/bin/airplanemodetoggle
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+if [ "$(printf "On\\nOff" | dmenu -i -p "Set airplane mode:")" = "On" ]
+then
+ notify-send "Airplane Mode" "Turning on airplane mode...."
+ sudo systemctl stop bluetooth.service
+ sudo systemctl stop expressvpn.service
+ sudo systemctl stop sshd.service
+ sudo systemctl stop syncthing@cjennings.service
+ sudo systemctl stop avahi-daemon.service
+ sudo systemctl stop cronie.service
+ sudo systemctl stop cups.service
+ sudo ip link set wlp170s0 down
+ sudo systemctl stop wpa_supplicant.service
+ sudo systemctl stop NetworkManager.service
+ sudo nmcli radio all off
+ sudo powertop --auto-tune
+ notify-send "Airplane Mode" "Airplane mode is now on."
+else
+ notify-send "Airplane Mode" "Turning off airplane mode....."
+ sudo nmcli radio wifi on
+ sudo systemctl start NetworkManager.service
+ sudo systemctl start wpa_supplicant.service
+ sudo ip link set wlp170s0 up
+ sudo systemctl start bluetooth.service
+ sudo systemctl start expressvpn.service
+ sudo systemctl start sshd.service
+ sudo systemctl start syncthing@cjennings.service
+ sudo systemctl start avahi-daemon.service
+ sudo systemctl start cronie.service
+ sudo systemctl start cups.service
+ notify-send "Airplane Mode" "Airplane mode is now off."
+fi
diff --git a/dotfiles/system/.local/bin/audioselect b/dotfiles/system/.local/bin/audioselect
new file mode 100755
index 0000000..13ffc36
--- /dev/null
+++ b/dotfiles/system/.local/bin/audioselect
@@ -0,0 +1,70 @@
+#!/bin/sh
+# Craig Jennings
+# convenience script to switch audio devices
+# need bluez and bluez-utils
+
+# DEVICE MAC ADDRESSES
+marshall_earbuds_device="00:25:D1:1B:39:CA"
+marshall_headset_device="9C:0D:AC:05:1E:C9"
+
+# SINKS (Audio Out)
+marshall_headset_sink="bluez_output.9C_0D_AC_05_1E_C9.a2dp-sink"
+marshall_earbuds_sink="bluez_output.00_25_D1_1B_39_CA.a2dp_sink"
+builtin_sink="alsa_output.pci-0000_00_1f.3.analog-stereo"
+jabra_510_sink="alsa_output.usb-0b0e_Jabra_SPEAK_510_USB_1C48F9C067D5020A00-00.analog-stereo"
+steelseries_sink="alsa_output.usb-SteelSeries_SteelSeries_Arctis_7-00.stereo-game"
+emberton_sink="bluez_sink.04_21_44_89_D0_BE.a2dp_sink"
+
+# SOURCES (Audio In)
+jabra_510_source="alsa_input.usb-0b0e_Jabra_SPEAK_510_USB_1C48F9C067D5020A00-00.mono-fallback"
+builtin_source="alsa_input.pci-0000_00_1f.3.analog-stereo"
+steelseries_source="alsa_input.usb-SteelSeries_SteelSeries_Arctis_7-00.mono-chat"
+
+CHOICES="Cancel\nToggle Mute Speaker\nToggle Mute Mic\nMarshall Headset & Jabra Mic\nMarshall Headset & Default Mic\nMarshall Earbuds & Jabra Mic\nJabra Speaker & Mic\nBuilt-In Audio"
+
+CHOSEN=$(echo -e "$CHOICES" | dmenu -l 10)
+
+case "$CHOSEN" in
+"Toggle Mute Speaker")
+ pactl set-sink-mute 0 toggle
+ dwmstatus
+ ;;
+"Toggle Mute Mic")
+ pactl set-source-mute 0 toggle
+ dwmstatus
+ ;;
+"Marshall Headset & Jabra Mic")
+ bluetooth power on
+ bluetoothctl connect $marshall_headset_device
+ pactl set-default-sink $marshall_headset_sink
+ pactl set-default-source $jabra_510_source
+ ;;
+"Marshall Headset & Default Mic")
+ bluetooth power on
+ bluetoothctl connect $marshall_headset_device
+ pactl set-default-sink $marshall_headset_sink
+ pactl set-default-source $builtin_source
+ ;;
+"Marshall Earbuds & Jabra Mic")
+ bluetooth power on
+ bluetoothctl connect $marshall_earbuds_device
+ pactl set-default-sink $marshall_earbuds_sink
+ pactl set-default-source $jabra_510_source
+ ;;
+"Built-In Audio")
+ pactl set-default-sink $builtin_audio_sink
+ pactl set-default-source $builtin_audio_source
+ ;;
+"Jabra Speaker & Mic")
+ pactl set-default-sink $jabra_510_sink
+ pactl set-default-source $jabra_510_source
+ ;;
+"Emberton & Built-In")
+ pactl set-default-sink $emberton_sink
+ pactl set-default-source $builtin_audio_source
+ ;;
+"Steelseries Headset")
+ pactl set-default-sink $steelseries_sink
+ pactl set-default-source $steelseries_source
+ ;;
+esac
diff --git a/dotfiles/system/.local/bin/battery_monitor b/dotfiles/system/.local/bin/battery_monitor
new file mode 100755
index 0000000..7c6e013
--- /dev/null
+++ b/dotfiles/system/.local/bin/battery_monitor
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+# battery_monitor
+# Intended to be run via .xinitrc
+# - Exit automatically if no battery (desktop)
+# - When below 15%, warn user of low battery
+# - When below 10%, suspend within 10 seconds if not charging
+#
+# Craig Jennings <c@cjennings.net>
+
+# check if acpi is installed
+if ! command -v acpi &> /dev/null; then
+ echo "acpi is not installed. Cannot continue. Exiting...."
+ exit 1
+fi
+
+# exit if a battery exists
+if [ ! -d "/sys/class/power_supply/BAT0" ] && [ ! -d "/sys/class/power_supply/BAT1" ]; then
+ echo "Acpi is installed but no battery detected. Assuming this is a desktop and exiting...."
+ exit 1
+fi
+
+while true; do
+ # Get the current battery percentage using acpi
+ battery_percentage=$(acpi -b | awk -F ', ' '{print $2}' | tr -d '%')
+ # battery_percentage=$(acpi -b | awk -F ', ' '{print $2}' | sed 's/%//')
+
+ # When below 10%, suspend within 10 seconds if not charging
+ if [ "$battery_percentage" -lt 11 ] && ! acpi -a | grep -q "on-line" ; then
+ # Send a notification of sleeping in 10 seconds
+ notify-send "Critical Battery" "Battery is at $battery_percentage%. System entering sleep in 30 seconds."
+
+ # sleep for 10 seconds, then abort if charging
+ sleep 30
+
+ # Check if the system is charging (AC adapter connected)
+ if acpi -a | grep -q "on-line"; then
+ notify-send "Charging" "The system is now charging. No action taken."
+ else
+ notify-send "Critical Battery" "Putting the system to sleep."
+ sudo systemctl suspend
+ fi
+ fi
+
+ # When below 15%, warn user
+ if [ "$battery_percentage" -lt 15 ] && ! acpi -a | grep -q "on-line" ; then
+ # Send a notification using notify-send and dunst
+ notify-send "Low Battery" "Battery is at $battery_percentage%. System will automatically sleep at 10%."
+ fi
+
+ # Sleep for 5 minutes before checking again
+ sleep 300
+done
diff --git a/dotfiles/system/.local/bin/bookfind b/dotfiles/system/.local/bin/bookfind
new file mode 100755
index 0000000..c5cc1bc
--- /dev/null
+++ b/dotfiles/system/.local/bin/bookfind
@@ -0,0 +1,5 @@
+#!/bin/sh
+# allows user to open a calibre book using dmenu
+
+find ~/Library/ -type f \( -iname \*.pdf -o -iname \*.epub \) | dmenu -i -l 20 -p "Choose an ebook:"
+
diff --git a/dotfiles/system/.local/bin/brightness b/dotfiles/system/.local/bin/brightness
new file mode 100755
index 0000000..9142f33
--- /dev/null
+++ b/dotfiles/system/.local/bin/brightness
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+# Craig Jennings <c@cjennings.net>
+# DWM convenience script for changing backlight
+# depends on xbacklight
+
+increment=10
+
+case $1 in
+ "max")
+ sudo xbacklight -set 100%;
+ ;;
+ "min")
+ sudo xbacklight -set 5%;
+ ;;
+ "up")
+ # get current setting as an int
+ current=$( printf "%.0f" "$(xbacklight -get)" )
+
+ # add the increment
+ newvalue=$(("$current" + "$increment"))
+
+ # don't let the brightness go above 100
+ [ "$newvalue" -ge 100 ] && newvalue=100;
+
+ # set the value
+ xbacklight -set "$newvalue";
+ ;;
+ "down")
+ current=$( printf "%.0f" "$(xbacklight -get)" )
+ newvalue=$(("$current" - "$increment"))
+ [ "$newvalue" -le 5 ] && newvalue=5;
+ xbacklight -set "$newvalue";
+ ;;
+esac
+newvalue=$( printf "%.0f" "$(xbacklight -get)")
+notify-send "backlight" "backlight now set to $newvalue"
diff --git a/dotfiles/system/.local/bin/bsdnet_bounce b/dotfiles/system/.local/bin/bsdnet_bounce
new file mode 100755
index 0000000..e4eec08
--- /dev/null
+++ b/dotfiles/system/.local/bin/bsdnet_bounce
@@ -0,0 +1,6 @@
+if [ $(id -u) -eq 0 ]
+then
+ service netif restart && service routing restart
+else
+ echo "You must be root to run this script"
+fi
diff --git a/dotfiles/system/.local/bin/build.emacs.aur.sh b/dotfiles/system/.local/bin/build.emacs.aur.sh
new file mode 100755
index 0000000..a185437
--- /dev/null
+++ b/dotfiles/system/.local/bin/build.emacs.aur.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+rm -rf emacs-git
+git clone https://aur.archlinux.org/emacs-git.git
+cd emacs-git
+sed -i 's/^JIT=\( \)/JIT="YES"/' PKGBUILD
+makepkg --syncdeps --install
diff --git a/dotfiles/system/.local/bin/build.emacs.src.sh b/dotfiles/system/.local/bin/build.emacs.src.sh
new file mode 100755
index 0000000..275a453
--- /dev/null
+++ b/dotfiles/system/.local/bin/build.emacs.src.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+EMACSGITREPO=~/code/emacs
+TAG=emacs-29.3
+
+printf "\n\n... buildin' Emacs time ...\n"
+
+clone_repo() {
+ printf "...grabbing a fresh copy of the source. this takes a minute...\n\n"
+ git clone https://github.com/mirrors/emacs.git $EMACSGITREPO
+ cd $EMACSGITREPO
+}
+
+nuke_repo() {
+ cd $HOME
+ printf "...nuking %s...\n\n" $EMACSGITREPO
+ sudo rm -rf $EMACSGITREPO
+}
+
+pull_latest() {
+ printf "...okay, but lemme tidy up this mess first...\n\n"
+ cd $EMACSGITREPO
+ make clean
+ printf "...pulling some fresh source code...\n\n"
+ git pull
+}
+
+build_emacs() {
+ printf "...checking out tag %s...\n\n" $TAG
+ git checkout $TAG
+ printf "...starting the build...\n\n"
+ cd $EMACSGITREPO
+ $EMACSGITREPO/autogen.sh
+ $EMACSGITREPO/configure --with-x-toolkit=lucid \
+ --with-modules \
+ --with-xwidgets \
+ --with-treesitter \
+ --with-mailutils \
+ --with-libsystemd \
+ --with-imagemagick \
+ --with-xml2 \
+ --with-libsystemd \
+ -with-gif --with-jpeg --with-png --with-tiff \
+ CFLAGS='-O2 -march=native'
+ make -j$(nproc)
+}
+
+if [ -d "$EMACSGITREPO" ]; then
+ printf "\n...one sec. an Emacs repository exists at %s already. Shall I first...\n" $EMACSGITREPO
+ printf "(r)efresh the existing repository with any latest commits, or\n"
+ printf "(c)lobber what's there and grab a fresh copy of the source, or \n"
+ printf "(b)uild what's there?\n\n"
+ read -p "Your choice: (r/c/s): " answer
+ printf "\n\n"
+ case ${answer:0:1} in
+ c|C )
+ nuke_repo
+ clone_repo
+ ;;
+ r|R)
+ pull_latest
+ ;;
+ b|B)
+ printf "...ok, just buildin'...\n\n"
+ ;;
+ * )
+ printf "wake up. you didn't choose a valid option. enjoy your day.\n\n"
+ exit 1
+ ;;
+ esac
+else
+ printf "...everything checks out, so let's get this rolling....\n"
+ clone_repo
+fi
+
+build_emacs
diff --git a/dotfiles/system/.local/bin/calibre-install b/dotfiles/system/.local/bin/calibre-install
new file mode 100755
index 0000000..42b007c
--- /dev/null
+++ b/dotfiles/system/.local/bin/calibre-install
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+# remember location
+export SRCDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+
+# download and install latest calibre
+sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdin
+
+# install current plugins and config
+# tar -xf $SRCDIR/../assets/calibre.tar.gz -C ~/.config/
diff --git a/dotfiles/system/.local/bin/colorpick b/dotfiles/system/.local/bin/colorpick
new file mode 100755
index 0000000..b5e1aff
--- /dev/null
+++ b/dotfiles/system/.local/bin/colorpick
@@ -0,0 +1,6 @@
+#!/bin/sh
+# displays colorpicker app
+# turns cursor into crosshairs, adds preview at bottom left
+# selected color is added to the clipboard
+
+colorpicker --short --one-shot --preview | xsel -b
diff --git a/dotfiles/system/.local/bin/cron/README.md b/dotfiles/system/.local/bin/cron/README.md
new file mode 100644
index 0000000..fa0c354
--- /dev/null
+++ b/dotfiles/system/.local/bin/cron/README.md
@@ -0,0 +1,11 @@
+# Important Note
+
+These cronjobs have components that require information about your current display to display notifications correctly.
+
+When you add them as cronjobs, I recommend you precede the command with commands as those below:
+
+```
+export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u $USER)/bus; export DISPLAY=:0; . $HOME/.zprofile; then_command_goes_here
+```
+
+This ensures that notifications will display, xdotool commands will function and environmental variables will work as well.
diff --git a/dotfiles/system/.local/bin/cron/checkup b/dotfiles/system/.local/bin/cron/checkup
new file mode 100755
index 0000000..bd3c634
--- /dev/null
+++ b/dotfiles/system/.local/bin/cron/checkup
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Syncs repositories and downloads updates, meant to be run as a cronjob.
+
+notify-send "📦 Repository Sync" "Checking for package updates..."
+
+sudo pacman -Syyuw --noconfirm || notify-send "Error downloading updates.
+
+Check your internet connection, if pacman is already running, or run update manually to see errors."
+pkill -RTMIN+8 "${STATUSBAR:-dwmblocks}"
+
+if pacman -Qu | grep -v "\[ignored\]"
+then
+ notify-send "🎁 Repository Sync" "Updates available. Click statusbar icon (📦) for update."
+else
+ notify-send "📦 Repository Sync" "Sync complete. No new packages for update."
+fi
diff --git a/dotfiles/system/.local/bin/cron/crontog b/dotfiles/system/.local/bin/cron/crontog
new file mode 100755
index 0000000..5aba5e6
--- /dev/null
+++ b/dotfiles/system/.local/bin/cron/crontog
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Toggles all cronjobs off/on.
+# Stores disabled crontabs in ~/.consaved until restored.
+
+([ -f "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved ] && crontab - < "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved && rm "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved && notify-send "🕓 Cronjobs re-enabled.") || ( crontab -l > "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved && crontab -r && notify-send "🕓 Cronjobs saved and disabled.")
diff --git a/dotfiles/system/.local/bin/debugemacs b/dotfiles/system/.local/bin/debugemacs
new file mode 100755
index 0000000..4585be1
--- /dev/null
+++ b/dotfiles/system/.local/bin/debugemacs
@@ -0,0 +1,4 @@
+ #!/bin/sh
+ EMACS_PID=`pgrep emacs`
+ cd /home/cjennings/Projects/emacs/src
+ exec -a debug-emacs $TERM -e gdb /usr/local/bin/emacs $EMACS_PID
diff --git a/dotfiles/system/.local/bin/displayselect b/dotfiles/system/.local/bin/displayselect
new file mode 100755
index 0000000..f9e8062
--- /dev/null
+++ b/dotfiles/system/.local/bin/displayselect
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+# A UI for detecting and selecting all displays. Probes xrandr for connected
+# displays and lets user select one to use. User may also select "manual
+# selection" which opens arandr.
+
+twoscreen() { # If multi-monitor is selected and there are two screens.
+
+ mirror=$(printf "no\\nyes" | dmenu -i -p "Mirror displays?")
+ # Mirror displays using native resolution of external display and a scaled
+ # version for the internal display
+ if [ "$mirror" = "yes" ]; then
+ external=$(echo "$screens" | dmenu -i -p "Optimize resolution for:")
+ internal=$(echo "$screens" | grep -v "$external")
+
+ res_external=$(xrandr --query | sed -n "/^$external/,/\+/p" | \
+ tail -n 1 | awk '{print $1}')
+ res_internal=$(xrandr --query | sed -n "/^$internal/,/\+/p" | \
+ tail -n 1 | awk '{print $1}')
+
+ res_ext_x=$(echo "$res_external" | sed 's/x.*//')
+ res_ext_y=$(echo "$res_external" | sed 's/.*x//')
+ res_int_x=$(echo "$res_internal" | sed 's/x.*//')
+ res_int_y=$(echo "$res_internal" | sed 's/.*x//')
+
+ scale_x=$(echo "$res_ext_x / $res_int_x" | bc -l)
+ scale_y=$(echo "$res_ext_y / $res_int_y" | bc -l)
+
+ xrandr --output "$external" --auto --scale 1.0x1.0 \
+ --output "$internal" --auto --same-as "$external" \
+ --scale "$scale_x"x"$scale_y"
+ else
+
+ primary=$(echo "$screens" | dmenu -i -p "Select primary display:")
+ secondary=$(echo "$screens" | grep -v "$primary")
+ direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?")
+ xrandr --output "$primary" --auto --scale 1.0x1.0 --output "$secondary" --"$direction"-of "$primary" --auto --scale 1.0x1.0
+ fi
+ }
+
+morescreen() { # If multi-monitor is selected and there are more than two screens.
+ primary=$(echo "$screens" | dmenu -i -p "Select primary display:")
+ secondary=$(echo "$screens" | grep -v "$primary" | dmenu -i -p "Select secondary display:")
+ direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?")
+ tertiary=$(echo "$screens" | grep -v "$primary" | grep -v "$secondary" | dmenu -i -p "Select third display:")
+ xrandr --output "$primary" --auto --output "$secondary" --"$direction"-of "$primary" --auto --output "$tertiary" --"$(printf "left\\nright" | grep -v "$direction")"-of "$primary" --auto
+ }
+
+multimon() { # Multi-monitor handler.
+ case "$(echo "$screens" | wc -l)" in
+ 2) twoscreen ;;
+ *) morescreen ;;
+ esac ;}
+
+onescreen() { # If only one output available or chosen.
+ xrandr --output "$1" --auto --scale 1.0x1.0 $(echo "$allposs" | grep -v "\b$1" | awk '{print "--output", $1, "--off"}' | paste -sd ' ' -)
+ }
+
+postrun() { # Stuff to run to clean up.
+ setbg # Fix background if screen size/arangement has changed.
+ remaps # Re-remap keys if keyboard added (for laptop bases)
+ { killall dunst ; setsid -f dunst ;} >/dev/null 2>&1 # Restart dunst to ensure proper location on screen
+ }
+
+# Get all possible displays
+allposs=$(xrandr -q | grep "connected")
+
+# Get all connected screens.
+screens=$(echo "$allposs" | awk '/ connected/ {print $1}')
+
+# If there's only one screen
+[ "$(echo "$screens" | wc -l)" -lt 2 ] &&
+ { onescreen "$screens"; postrun; notify-send "💻 Only one screen detected." "Using it in its optimal settings..."; exit ;}
+
+# Get user choice including multi-monitor and manual selection:
+chosen=$(printf "%s\\nmulti-monitor\\nmanual selection" "$screens" | dmenu -i -p "Select display arangement:") &&
+case "$chosen" in
+ "manual selection") arandr ; exit ;;
+ "multi-monitor") multimon ;;
+ *) onescreen "$chosen" ;;
+esac
+
+postrun
diff --git a/dotfiles/system/.local/bin/dmenuexitmenu b/dotfiles/system/.local/bin/dmenuexitmenu
new file mode 100755
index 0000000..5570364
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenuexitmenu
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+menuitems=("Lock  \nSuspend 󰤄 \nLogout 󰩈 \nReboot 󰁪 \nShutdown  \nCancel 󰜺")
+choice=$(echo -e $menuitems | dmenu -nb "#DAA520" -nf "#2E3440" -sb "#2E3440" -sf "#DAA520")
+
+case "$choice" in
+ "Logout 󰩈 ") loginctl terminate-user $(whoami) ;;
+ "Lock  ") slock ;;
+ "Suspend 󰤄 ") systemctl suspend;;
+ "Shutdown  ") systemctl poweroff;;
+ "Reboot 󰁪 ") systemctl reboot ;;
+esac
diff --git a/dotfiles/system/.local/bin/dmenuhandler b/dotfiles/system/.local/bin/dmenuhandler
new file mode 100755
index 0000000..1c48f3a
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenuhandler
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Feed this script a link and it will give dmenu
+# some choice programs to use to open it.
+feed="${1:-$(printf "%s" | dmenu -p 'Paste URL or file path')}"
+
+case "$(printf "Copy URL\\nsxiv\\nsetbg\\nPDF\\nbrowser\\nlynx\\nvim\\nmpv\\nmpv loop\\nmpv float\\nqueue download\\nqueue yt-dlp\\nqueue yt-dlp audio" | dmenu -i -p "Open it with?")" in
+ "Copy URL") echo "$feed" | xclip -selection clipboard ;;
+ mpv) setsid -f mpv -quiet "$feed" >/dev/null 2>&1 ;;
+ "mpv loop") setsid -f mpv -quiet --loop "$feed" >/dev/null 2>&1 ;;
+ "mpv float") setsid -f "$TERMINAL" -e mpv --geometry=+0-0 --autofit=30% --title="mpvfloat" "$feed" >/dev/null 2>&1 ;;
+ "queue yt-dlp") qndl "$feed" >/dev/null 2>&1 ;;
+ "queue yt-dlp audio") qndl "$feed" 'yt-dlp --embed-metadata -icx -f bestaudio/best' >/dev/null 2>&1 ;;
+ "queue download") qndl "$feed" 'curl -LO' >/dev/null 2>&1 ;;
+ PDF) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && zathura "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" >/dev/null 2>&1 ;;
+ sxiv) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && sxiv -a "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" >/dev/null 2>&1 ;;
+ vim) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && setsid -f "$TERMINAL" -e "$EDITOR" "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" >/dev/null 2>&1 ;;
+ setbg) curl -L "$feed" > $XDG_CACHE_HOME/pic ; xwallpaper --zoom $XDG_CACHE_HOME/pic >/dev/null 2>&1 ;;
+ browser) setsid -f "$BROWSER" "$feed" >/dev/null 2>&1 ;;
+ lynx) lynx "$feed" >/dev/null 2>&1 ;;
+esac
diff --git a/dotfiles/system/.local/bin/dmenumount b/dotfiles/system/.local/bin/dmenumount
new file mode 100755
index 0000000..3cb1f81
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenumount
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+# Gives a dmenu prompt to mount unmounted drives and Android phones. If
+# they're in /etc/fstab, they'll be mounted automatically. Otherwise, you'll
+# be prompted to give a mountpoint from already existsing directories. If you
+# input a novel directory, it will prompt you to create that directory.
+
+getmount() { \
+ [ -z "$chosen" ] && exit 1
+ # shellcheck disable=SC2086
+ mp="$(find $1 2>/dev/null | dmenu -i -p "Type in mount point.")" || exit 1
+ test -z "$mp" && exit 1
+ if [ ! -d "$mp" ]; then
+ mkdiryn=$(printf "No\\nYes" | dmenu -i -p "$mp does not exist. Create it?") || exit 1
+ [ "$mkdiryn" = "Yes" ] && (mkdir -p "$mp" || sudo -A mkdir -p "$mp")
+ fi
+ }
+
+mountusb() { \
+ chosen="$(echo "$usbdrives" | dmenu -i -p "Mount which drive?")" || exit 1
+ chosen="$(echo "$chosen" | awk '{print $1}')"
+ sudo -A mount "$chosen" 2>/dev/null && notify-send "💻 USB mounting" "$chosen mounted." && exit 0
+ alreadymounted=$(lsblk -nrpo "name,type,mountpoint" | awk '$3!~/\/boot|\/home$|SWAP/&&length($3)>1{printf "-not ( -path *%s -prune ) ",$3}')
+ getmount "/mnt /media /mount /home -maxdepth 5 -type d $alreadymounted"
+ partitiontype="$(lsblk -no "fstype" "$chosen")"
+ case "$partitiontype" in
+ "vfat") sudo -A mount -t vfat "$chosen" "$mp" -o rw,umask=0000;;
+ "exfat") sudo -A mount "$chosen" "$mp" -o uid="$(id -u)",gid="$(id -g)";;
+ *) sudo -A mount "$chosen" "$mp"; user="$(whoami)"; ug="$(groups | awk '{print $1}')"; sudo -A chown "$user":"$ug" "$mp";;
+ esac
+ notify-send "💻 USB mounting" "$chosen mounted to $mp."
+ }
+
+mountandroid() { \
+ chosen="$(echo "$anddrives" | dmenu -i -p "Which Android device?")" || exit 1
+ chosen="$(echo "$chosen" | cut -d : -f 1)"
+ getmount "$HOME -maxdepth 3 -type d"
+ simple-mtpfs --device "$chosen" "$mp"
+ echo "OK" | dmenu -i -p "Tap Allow on your phone if it asks for permission and then press enter" || exit 1
+ simple-mtpfs --device "$chosen" "$mp"
+ notify-send "🤖 Android Mounting" "Android device mounted to $mp."
+ }
+
+asktype() { \
+ choice="$(printf "USB\\nAndroid" | dmenu -i -p "Mount a USB drive or Android device?")" || exit 1
+ case $choice in
+ USB) mountusb ;;
+ Android) mountandroid ;;
+ esac
+ }
+
+anddrives=$(simple-mtpfs -l 2>/dev/null)
+usbdrives="$(lsblk -rpo "name,type,size,mountpoint" | grep 'part\|rom' | awk '$4==""{printf "%s (%s)\n",$1,$3}')"
+
+if [ -z "$usbdrives" ]; then
+ [ -z "$anddrives" ] && echo "No USB drive or Android device detected" && exit
+ echo "Android device(s) detected."
+ mountandroid
+else
+ if [ -z "$anddrives" ]; then
+ echo "USB drive(s) detected."
+ mountusb
+ else
+ echo "Mountable USB drive(s) and Android device(s) detected."
+ asktype
+ fi
+fi
diff --git a/dotfiles/system/.local/bin/dmenumountcifs b/dotfiles/system/.local/bin/dmenumountcifs
new file mode 100755
index 0000000..46c2b57
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenumountcifs
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Gives a dmenu prompt to mount unmounted local NAS shares for read/write.
+# Requirements - "%wheel ALL=(ALL) NOPASSWD: ALL"
+#
+# Browse for mDNS/DNS-SD services using the Avahi daemon...
+srvname=$(avahi-browse _smb._tcp -t | awk '{print $4}' | dmenu -i -p "Which NAS?") || exit 1
+notify-send "Searching for network shares..." "Please wait..."
+# Choose share disk...
+share=$(smbclient -L "$srvname" -N | grep Disk | awk '{print $1}' | dmenu -i -p "Mount which share?") || exit 1
+# Format URL...
+share2mnt=//"$srvname".local/"$share"
+
+sharemount() {
+ mounted=$(mount -v | grep "$share2mnt") || ([ ! -d /mnt/"$share" ] && sudo mkdir /mnt/"$share")
+ [ -z "$mounted" ] && sudo mount -t cifs "$share2mnt" -o user=nobody,password="",noperm /mnt/"$share" && notify-send "Netshare $share mounted" && exit 0
+ notify-send "Netshare $share already mounted"; exit 1
+}
+
+sharemount
diff --git a/dotfiles/system/.local/bin/dmenurecord b/dotfiles/system/.local/bin/dmenurecord
new file mode 100755
index 0000000..b83a7c5
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenurecord
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+# Usage:
+# `$0`: Ask for recording type via dmenu
+# `$0 screencast`: Record both audio and screen
+# `$0 video`: Record only screen
+# `$0 audio`: Record only audio
+# `$0 kill`: Kill existing recording
+#
+# If there is already a running instance, user will be prompted to end it.
+
+updateicon() { \
+ echo "$1" > /tmp/recordingicon
+ pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
+ }
+
+killrecording() {
+ recpid="$(cat /tmp/recordingpid)"
+ # kill with SIGTERM, allowing finishing touches.
+ kill -15 "$recpid"
+ rm -f /tmp/recordingpid
+ updateicon ""
+ pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
+ # even after SIGTERM, ffmpeg may still run, so SIGKILL it.
+ sleep 3
+ kill -9 "$recpid"
+ exit
+ }
+
+screencast() { \
+ ffmpeg -y \
+ -f x11grab \
+ -framerate 60 \
+ -s "$(xdpyinfo | awk '/dimensions/ {print $2;}')" \
+ -i "$DISPLAY" \
+ -f alsa -i default \
+ -r 30 \
+ -c:v h264 -crf 0 -preset ultrafast -c:a aac \
+ "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" &
+ echo $! > /tmp/recordingpid
+ updateicon "⏺️🎙️"
+ }
+
+video() { ffmpeg \
+ -f x11grab \
+ -s "$(xdpyinfo | awk '/dimensions/ {print $2;}')" \
+ -i "$DISPLAY" \
+ -c:v libx264 -qp 0 -r 30 \
+ "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "⏺️"
+ }
+
+webcamhidef() { ffmpeg \
+ -f v4l2 \
+ -i /dev/video0 \
+ -video_size 1920x1080 \
+ "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "🎥"
+ }
+
+webcam() { ffmpeg \
+ -f v4l2 \
+ -i /dev/video0 \
+ -video_size 640x480 \
+ "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "🎥"
+ }
+
+
+audio() { \
+ ffmpeg \
+ -f alsa -i default \
+ -c:a flac \
+ "$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" &
+ echo $! > /tmp/recordingpid
+ updateicon "🎙️"
+ }
+
+askrecording() { \
+ choice=$(printf "screencast\\nvideo\\nvideo selected\\naudio\\nwebcam\\nwebcam (hi-def)" | dmenu -i -p "Select recording style:")
+ case "$choice" in
+ screencast) screencast;;
+ audio) audio;;
+ video) video;;
+ *selected) videoselected;;
+ webcam) webcam;;
+ "webcam (hi-def)") webcamhidef;;
+ esac
+ }
+
+asktoend() { \
+ response=$(printf "No\\nYes" | dmenu -i -p "Recording still active. End recording?") &&
+ [ "$response" = "Yes" ] && killrecording
+ }
+
+videoselected()
+{
+ slop -f "%x %y %w %h" > /tmp/slop
+ read -r X Y W H < /tmp/slop
+ rm /tmp/slop
+
+ ffmpeg \
+ -f x11grab \
+ -framerate 60 \
+ -video_size "$W"x"$H" \
+ -i :0.0+"$X,$Y" \
+ -c:v libx264 -qp 0 -r 30 \
+ "$HOME/box-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "⏺️"
+}
+
+case "$1" in
+ screencast) screencast;;
+ audio) audio;;
+ video) video;;
+ *selected) videoselected;;
+ kill) killrecording;;
+ *) ([ -f /tmp/recordingpid ] && asktoend && exit) || askrecording;;
+esac
diff --git a/dotfiles/system/.local/bin/dmenuumount b/dotfiles/system/.local/bin/dmenuumount
new file mode 100755
index 0000000..946d12c
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenuumount
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# A dmenu prompt to unmount drives.
+# Provides you with mounted partitions, select one to unmount.
+# Drives mounted at /, /boot and /home will not be options to unmount.
+
+unmountusb() {
+ [ -z "$drives" ] && exit
+ chosen="$(echo "$drives" | dmenu -i -p "Unmount which drive?")" || exit 1
+ chosen="$(echo "$chosen" | awk '{print $1}')"
+ [ -z "$chosen" ] && exit
+ sudo -A umount "$chosen" && notify-send "💻 USB unmounting" "$chosen unmounted."
+ }
+
+unmountandroid() { \
+ chosen="$(awk '/simple-mtpfs/ {print $2}' /etc/mtab | dmenu -i -p "Unmount which device?")" || exit 1
+ [ -z "$chosen" ] && exit
+ sudo -A umount -l "$chosen" && notify-send "🤖 Android unmounting" "$chosen unmounted."
+ }
+
+asktype() { \
+ choice="$(printf "USB\\nAndroid" | dmenu -i -p "Unmount a USB drive or Android device?")" || exit 1
+ case "$choice" in
+ USB) unmountusb ;;
+ Android) unmountandroid ;;
+ esac
+ }
+
+drives=$(lsblk -nrpo "name,type,size,mountpoint,label" | awk -F':' '{gsub(/ /,":")}$4!~/\/boot|\/efi|\/home$|SWAP/&&length($4)>1{printf "%s (%s) %s\n",$4,$3,$5}')
+
+if ! grep simple-mtpfs /etc/mtab; then
+ [ -z "$drives" ] && echo "No drives to unmount." && exit
+ echo "Unmountable USB drive detected."
+ unmountusb
+else
+ if [ -z "$drives" ]
+ then
+ echo "Unmountable Android device detected."
+ unmountandroid
+ else
+ echo "Unmountable USB drive(s) and Android device(s) detected."
+ asktype
+ fi
+fi
diff --git a/dotfiles/system/.local/bin/dmenuunicode b/dotfiles/system/.local/bin/dmenuunicode
new file mode 100755
index 0000000..b25876f
--- /dev/null
+++ b/dotfiles/system/.local/bin/dmenuunicode
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# The famous "get a menu of emojis to copy" script.
+
+# Get user selection via dmenu from emoji file.
+chosen=$(cut -d ';' -f1 ~/.local/share/emoji | dmenu -i -l 30 | sed "s/ .*//")
+
+# Exit if none chosen.
+[ -z "$chosen" ] && exit
+
+# If you run this command with an argument, it will automatically insert the
+# character. Otherwise, show a message that the emoji has been copied.
+if [ -n "$1" ]; then
+ xdotool type "$chosen"
+else
+ printf "$chosen" | xclip -selection clipboard
+ notify-send "'$chosen' copied to clipboard." &
+fi
diff --git a/dotfiles/system/.local/bin/dotfiles_pushall b/dotfiles/system/.local/bin/dotfiles_pushall
new file mode 100755
index 0000000..3eef2c6
--- /dev/null
+++ b/dotfiles/system/.local/bin/dotfiles_pushall
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Craig Jennings <craigmartinjennings@gmail.com>
+# tired of pushing to multiple locations with multiple commands
+/usr/bin/git --git-dir="$HOME"/.dotfiles/ --work-tree="$HOME" push origin main && \
+/usr/bin/git --git-dir="$HOME"/.dotfiles/ --work-tree="$HOME" push source main && \
+/usr/bin/git --git-dir="$HOME"/.dotfiles/ --work-tree="$HOME" push github main
diff --git a/dotfiles/system/.local/bin/dwmstatus b/dotfiles/system/.local/bin/dwmstatus
new file mode 100755
index 0000000..d0cff02
--- /dev/null
+++ b/dotfiles/system/.local/bin/dwmstatus
@@ -0,0 +1,79 @@
+#!/bin/sh
+# displays status of microphone, camera, wifi, free home disk space, and date/time
+# uses icons found in nerd fonts here: https://github.com/ryanoasis/nerd-fonts.git
+
+export DISPLAY=:0
+unset status
+
+##########################################################################
+# MIC #
+##########################################################################
+
+# micsymbol_on=""
+# micsymbol_off=""
+
+# amixer get Capture | grep '\[off\]' && mic="$micsymbol_off" || mic="$micsymbol_on"
+# status="$mic "
+
+
+##########################################################################
+# VOLUME #
+##########################################################################
+
+speakersymbol=""
+if grep -q "yes" <<< $(pactl get-sink-mute $(pactl get-default-sink)) ; then
+ speakersymbol=""
+ vol=""
+else
+ vol=$(echo $(pactl get-sink-volume $(pactl get-default-sink)) | cut -d"/" -f2 | xargs)
+fi
+status+="$speakersymbol $vol "
+
+
+##########################################################################
+# WIFI #
+##########################################################################
+
+wifisymbol_on=""
+wifisymbol_off=""
+# note: assumes we're using network-manager
+ssid="$(nmcli -t -f active,ssid dev wifi | grep -E '^yes' | cut -d: -f2)"
+wifi="$wifisymbol_off"
+if [ "$ssid" != "" ]; then wifi="$wifisymbol_on $ssid"; fi
+status+="$wifi "
+
+
+##########################################################################
+# BATTERY #
+##########################################################################
+
+# desktops don't typically have batteries. if no batteries are found, skip this section
+if [[ -n $(find /sys/class/power_supply/ -name "BAT?") ]]; then
+
+ # however, laptops may have multiple batteries, so list them individually
+ for battery in /sys/class/power_supply/BAT?; do
+ batstat=$(sed "s/[Dd]ischarging/󱟞/;s/[Nn]ot charging/󰁹/;s/[Cc]harging/󰂄/;s/[Uu]nknown//;s/[Ff]ull//" "$battery"/status)
+ battery_level=$(cat "$battery"/capacity 2>/dev/null)
+ status+="${batstat} ${battery_level}% "
+ done
+fi
+
+
+##########################################################################
+# /HOME DISK #
+##########################################################################
+
+# disksymbol=""
+# disk=$(df -hl | awk '{ if ($6 == "/home") print $4 " free" }')
+# status+="$disksymbol $disk "
+
+
+##########################################################################
+# DATE / TIME #
+##########################################################################
+
+# Format Example: Thu Mar 25 03:37 PM CDT
+calendarsymbol=""
+status+="$calendarsymbol $(/bin/date +'%a %b %d %I:%M %p %Z')"
+
+xsetroot -name "$status"
diff --git a/dotfiles/system/.local/bin/ec b/dotfiles/system/.local/bin/ec
new file mode 100755
index 0000000..b409195
--- /dev/null
+++ b/dotfiles/system/.local/bin/ec
@@ -0,0 +1,2 @@
+#!/bin/sh
+emacsclient -c -a "" $1 $2 $3 $4 &
diff --git a/dotfiles/system/.local/bin/em b/dotfiles/system/.local/bin/em
new file mode 100755
index 0000000..b409195
--- /dev/null
+++ b/dotfiles/system/.local/bin/em
@@ -0,0 +1,2 @@
+#!/bin/sh
+emacsclient -c -a "" $1 $2 $3 $4 &
diff --git a/dotfiles/system/.local/bin/et b/dotfiles/system/.local/bin/et
new file mode 100755
index 0000000..1c3c4a0
--- /dev/null
+++ b/dotfiles/system/.local/bin/et
@@ -0,0 +1,2 @@
+#!/bin/sh
+emacsclient -c -nw --alternate-editor="" $1 $2 $3 $4 &
diff --git a/dotfiles/system/.local/bin/exitmenu b/dotfiles/system/.local/bin/exitmenu
new file mode 100755
index 0000000..2c55b34
--- /dev/null
+++ b/dotfiles/system/.local/bin/exitmenu
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+CHOICES="Shutdown\nReboot\nLock\nHibernate\nSuspend\nToggle Airplane Mode\nToggle Powersave Mode"
+CHOSEN=$(echo -e "$CHOICES" | dmenu -i)
+
+case $CHOSEN in
+ "Shutdown") shutdown now ;;
+ "Reboot") reboot ;;
+ "Lock") xscreensaver-command --lock ;;
+ "Hiberbate") systemctl hibernate ;;
+ "Suspend") systemctl suspend ;;
+ "Toggle Airplane Mode") airplanemodetoggle ;;
+ "Toggle Powersave Mode") lowpowertoggle && notify-send "Battery Status" "$(acpi -b)" ;;
+esac
+
+dwmstatus
diff --git a/dotfiles/system/.local/bin/extractaudio b/dotfiles/system/.local/bin/extractaudio
new file mode 100755
index 0000000..a665451
--- /dev/null
+++ b/dotfiles/system/.local/bin/extractaudio
@@ -0,0 +1,2 @@
+#!/bin/sh
+ffmpeg -i $1 -q:a 0 -map a $1.mp3
diff --git a/dotfiles/system/.local/bin/gitconfig_defaults b/dotfiles/system/.local/bin/gitconfig_defaults
new file mode 100755
index 0000000..c2f18ae
--- /dev/null
+++ b/dotfiles/system/.local/bin/gitconfig_defaults
@@ -0,0 +1,5 @@
+git config --global user.email "craigmartinjennings@gmail.com"
+git config --global user.name "Craig Jennings""
+git config --global merge.tool meld
+git config --global core.editor "emacsclient -c -a''"
+git config --global fetch.prune true
diff --git a/dotfiles/system/.local/bin/gruv b/dotfiles/system/.local/bin/gruv
new file mode 100755
index 0000000..b3e7f35
--- /dev/null
+++ b/dotfiles/system/.local/bin/gruv
@@ -0,0 +1,3 @@
+#!/bin/bash
+dir=$pwd
+for file in $(ls $dir | shuf) ; do mpv --no-video "$file"; done
diff --git a/dotfiles/system/.local/bin/ifinstalled b/dotfiles/system/.local/bin/ifinstalled
new file mode 100755
index 0000000..c192eba
--- /dev/null
+++ b/dotfiles/system/.local/bin/ifinstalled
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Some optional functions in LARBS require programs not installed by default. I
+# use this little script to check to see if a command exists and if it doesn't
+# it informs the user that they need that command to continue. This is used in
+# various other scripts for clarity's sake.
+
+for x in "$@"; do
+ if ! which "$x" >/dev/null 2>&1 && ! pacman -Qq "$x" >/dev/null 2>&1; then
+ notify-send "📦 $x" "must be installed for this function." && exit 1 ;
+ fi
+done
diff --git a/dotfiles/system/.local/bin/lfrun b/dotfiles/system/.local/bin/lfrun
new file mode 100755
index 0000000..5bb0ba3
--- /dev/null
+++ b/dotfiles/system/.local/bin/lfrun
@@ -0,0 +1,19 @@
+#!/bin/sh
+set -e
+
+cleanup() {
+ exec 3>&-
+ rm "$FIFO_UEBERZUG"
+}
+
+if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
+ lf "$@"
+else
+ [ ! -d "$HOME/.cache/lf" ] && mkdir --parents "$HOME/.cache/lf"
+ export FIFO_UEBERZUG="$HOME/.cache/lf/ueberzug-$$"
+ mkfifo "$FIFO_UEBERZUG"
+ ueberzug layer -s <"$FIFO_UEBERZUG" -p json &
+ exec 3>"$FIFO_UEBERZUG"
+ trap cleanup EXIT
+ lf "$@" 3>&-
+fi
diff --git a/dotfiles/system/.local/bin/lfub b/dotfiles/system/.local/bin/lfub
new file mode 100755
index 0000000..9012f50
--- /dev/null
+++ b/dotfiles/system/.local/bin/lfub
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# This is a wrapper script for lb that allows it to create image previews with
+# ueberzug. This works in concert with the lf configuration file and the
+# lf-cleaner script.
+
+set -e
+
+cleanup() {
+ exec 3>&-
+ rm "$FIFO_UEBERZUG"
+}
+
+if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
+ lf "$@"
+else
+ [ ! -d "$HOME/.cache/lf" ] && mkdir -p "$HOME/.cache/lf"
+ export FIFO_UEBERZUG="$HOME/.cache/lf/ueberzug-$$"
+ mkfifo "$FIFO_UEBERZUG"
+ ueberzug layer -s <"$FIFO_UEBERZUG" -p json &
+ exec 3>"$FIFO_UEBERZUG"
+ trap cleanup HUP INT QUIT TERM PWR EXIT
+ lf "$@" 3>&-
+fi
diff --git a/dotfiles/system/.local/bin/linkhandler b/dotfiles/system/.local/bin/linkhandler
new file mode 100755
index 0000000..cc971fc
--- /dev/null
+++ b/dotfiles/system/.local/bin/linkhandler
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Feed script a url or file location.
+# If an image, it will view in sxiv,
+# if a video or gif, it will view in mpv
+# if a music file or pdf, it will download,
+# otherwise it opens link in browser.
+
+if [ -z "$1" ]; then
+ url="$(xclip -o)"
+else
+ url="$1"
+fi
+
+case "$url" in
+ *mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtu.be*|*hooktube.com*|*bitchute.com*|*videos.lukesmith.xyz*|*odysee.com*)
+ setsid -f mpv -quiet "$url" >/dev/null 2>&1 ;;
+ *png|*jpg|*jpe|*jpeg|*gif)
+ curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && sxiv -a "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *pdf|*cbz|*cbr)
+ curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *mp3|*flac|*opus|*mp3?source*)
+ qndl "$url" 'curl -LO' >/dev/null 2>&1 ;;
+ *)
+ [ -f "$url" ] && setsid -f "$TERMINAL" -e "$EDITOR" "$url" >/dev/null 2>&1 || setsid -f "$BROWSER" "$url" >/dev/null 2>&1
+esac
diff --git a/dotfiles/system/.local/bin/lkg b/dotfiles/system/.local/bin/lkg
new file mode 100755
index 0000000..aa9b3f1
--- /dev/null
+++ b/dotfiles/system/.local/bin/lkg
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Craig Jennings <c@cjennings.net>
+
+sudo zfs destroy -rR zroot@lkg && sudo zfs snapshot -r zroot@lkg && echo "lkg snapshot reset" || echo "lkg snapshot failed!"
diff --git a/dotfiles/system/.local/bin/lkg_rollback b/dotfiles/system/.local/bin/lkg_rollback
new file mode 100755
index 0000000..3cf4c59
--- /dev/null
+++ b/dotfiles/system/.local/bin/lkg_rollback
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+sudo zfs rollback -rR zroot/var@lkg
+sudo zfs rollback -rR zroot/var/log@lkg
+sudo zfs rollback -rR zroot/usr@lkg
+sudo zfs rollback -rR zroot/usr/home@lkg
+sudo zfs rollback -rR zroot/ROOT/default@lkg
+sudo zfs rollback -rR zroot/ROOT@lkg
+sudo zfs rollback -rR zroot@lkg
+
+echo ""; echo "rollback complete. rebooting..."
+sudo shutdown -r now
diff --git a/dotfiles/system/.local/bin/lsbak b/dotfiles/system/.local/bin/lsbak
new file mode 100755
index 0000000..7803135
--- /dev/null
+++ b/dotfiles/system/.local/bin/lsbak
@@ -0,0 +1 @@
+ls -laF /media/backup/renovo
diff --git a/dotfiles/system/.local/bin/mkplaylist b/dotfiles/system/.local/bin/mkplaylist
new file mode 100755
index 0000000..66b6e9c
--- /dev/null
+++ b/dotfiles/system/.local/bin/mkplaylist
@@ -0,0 +1,173 @@
+#!/usr/bin/env bash
+# Craig Jennings <c@cjennings.net>
+# Basically just a bash wrapper around a find/grep/awk command pipe
+# to generate m3u playlists from video or audio files in a directory.
+
+# One m3u playlist will be placed in the MUSIC_DIR, and another
+# will be placed inside each playlist directory.
+# It also converts .opus and .ogg files to .m4a for Android playback.
+
+# Note:
+# This script requires the following utilities to be on the path:
+# mid3v2 (aur package: python-mutagen)
+# tageditor (aur package: tageditor)
+# metaflac (aur package: flac)
+
+set -e
+
+MUSIC_DIR="$HOME/music"
+# REQUIRED_TOOLS=("mid3v2" "tageditor")
+REQUIRED_TOOLS=("mid3v2" "metaflac" "tageditor")
+
+# ---------------------------- Functions ----------------------------
+
+usage () {
+ printf "\nUsage: mkplaylist <playlist_name>\n\n"
+ printf "mkplaylist - creates an m3u playlist in the $MUSIC_DIR directory\n"
+ printf "based the music and video files in directory which m3uplaylist is called.\n\n"
+ printf " - this script should be run in the directory containing the music or video files\n"
+ printf " - <playlist_name> is mandatory and shouldn't end with '.m3u' extension\n"
+ printf " - change the destination ($MUSIC_DIR) by editing this script\n\n"
+}
+
+tag_music_file() {
+ while IFS= read -r file; do
+ filename=$(basename "$file")
+ extension="${filename##*.}"
+ artist=$(basename "$file" | cut -d '-' -f 1)
+ title=$(basename "$file" | cut -d '-' -f 2- | cut -d '.' -f 1)
+ outputfile="$(dirname "$file")/$title.flac"
+
+ # If file is not already flac, convert it
+ if [ "$extension" != "flac" ]; then
+
+ # Delete all tags using mid3v2
+ mid3v2 --delete-all "$file"
+ ffmpeg -i "$file" -vn -c:a flac "$outputfile"
+ file="$outputfile" # Now we're working with the new FLAC file
+
+ fi
+
+ # Set artist and song title tags using metaflac
+ metaflac --set-tag="ARTIST=$artist" --set-tag="TITLE=$title" "$file"
+
+ done
+}
+
+# tag_music_file() {
+# while IFS= read -r file; do
+# filename=$(basename "$file")
+# extension="${filename##*.}"
+# artist=$(basename "$file" | cut -d '-' -f 1)
+# title=$(basename "$file" | cut -d '-' -f 2- | cut -d '.' -f 1)
+# outputfile="$(dirname "$file")/$title.flac"
+
+# # Delete all tags using mid3v2
+# mid3v2 --delete-all "$file"
+
+# # If file is not already flac, convert it
+# if [ "$extension" != "flac" ]; then
+# ffmpeg -i "$file" -vn -c:a flac "$outputfile"
+# file="$outputfile" # Now we're working with the new FLAC file
+# fi
+
+# # Set artist and song title tags using metaflac
+# metaflac --set-tag="ARTIST=$artist" --set-tag="TITLE=$title" "$file"
+# done
+# }
+
+# tag_music_file() {
+# while IFS= read -r file; do
+# # Extract artist and song title from filename
+# artist=$(basename "$file" | cut -d '-' -f 1)
+# title=$(basename "$file" | cut -d '-' -f 2- | cut -d '.' -f 1)
+# outputfile="$(dirname "$file")/$title.flac"
+
+# # Delete all tags using mid3v2
+# mid3v2 --delete-all "$file"
+
+# # Convert to flac and save to new file
+# ffmpeg -i "$file" -vn -c:a flac "$outputfile"
+
+# # Set artist and song title tags using metaflac
+# metaflac --set-tag="ARTIST=$artist" --set-tag="TITLE=$title" "$outputfile"
+# done
+# }
+
+# tag_music_file() {
+# while IFS= read -r file; do
+# # Extract artist and song title from filename
+# artist=$(basename "$file" | cut -d '-' -f 1)
+# title=$(basename "$file" | cut -d '-' -f 2 | cut -d '.' -f 1)
+# outputfile="$(dirname "$file")/$title.flac"
+
+# # Delete all tags using mid3v2
+# mid3v2 --delete-all "$file"
+
+# # Set artist and song title tags using mid3v2
+# mid3v2 --artist="$artist" --song="$title" "$file"
+# # Convert to flac and save to new file
+# ffmpeg -i "$file" -vn -c:a flac "$outputfile"
+# done
+# }
+
+# tag_music_file() {
+# while IFS= read -r file; do
+# # Extract artist and song title from filename
+# artist=$(basename "$file" | cut -d '-' -f 1)
+# title=$(basename "$file" | cut -d '-' -f 2 | cut -d '.' -f 1)
+
+# # Delete all tags using mid3v2
+# mid3v2 --delete-all "$file"
+
+# # Set artist and song title tags using mid3v2
+# mid3v2 --artist="$artist" --song="$title" "$file"
+# done
+# }
+
+ generate_music_m3u() {
+ printf "retagging music files....\n"
+ find "$(pwd)" -print | file -if - | grep -E '(audio)' | awk -F: '{print $1}' | tag_music_file
+
+ printf "generating playlist.'%s'...\n" "$LOCAL_PLAYLIST"
+ find "$(pwd)" -print | file -if - | grep -E '(video|audio)' |
+ awk -F: '{print $1}' | while read -r line; do basename "$line"; done > "$LOCAL_PLAYLIST"
+ printf "generating playlist '%s'....\n" "$MUSIC_PLAYLIST"
+ find "$(pwd)" -print | file -if - | grep -E '(video|audio)' | awk -F: '{print $1}' > "$MUSIC_PLAYLIST"
+ printf "Done.\n\n"
+ }
+
+ # ----------------------------- Script ----------------------------
+
+ # display usage if user specifically requests it
+ TYPE=$(tr '[a-z]' '[A-Z]' <<< "$@");
+ [ "$TYPE" = "HELP" ] && usage && exit 1
+ [ "$TYPE" = "-H" ] && usage&& exit 1
+
+ # check that all necessary tools are installed
+ for tool in ${REQUIRED_TOOLS[@]}; do
+ if ! type "$tool" >/dev/null 2>&1; then
+ printf "ERROR: The script requires '%s' but it is not installed or not in PATH.\n" "$tool"
+ exit 1
+ fi
+ done
+
+ # use directory name for playlist name when parameter doesn't exist
+ if [ $# -eq 0 ]
+ then
+ set -- "$(basename "$PWD")"
+ echo "no playlist name entered, so using directory name: '$(basename "$PWD")'"
+ fi
+
+ # ask to overwrite if the playlist already exists
+ MUSIC_PLAYLIST="$MUSIC_DIR/$@.m3u"
+ LOCAL_PLAYLIST="./$@.m3u"
+
+ if [ -f "$MUSIC_PLAYLIST" ]; then
+ read -p "$MUSIC_PLAYLIST exists. Overwrite (y/n) " yn
+ if [ "$yn" != "y" ] && [ "$yn" != "Y" ]; then
+ exit 0
+ fi
+ fi
+
+ generate_music_m3u
diff --git a/dotfiles/system/.local/bin/monitor b/dotfiles/system/.local/bin/monitor
new file mode 100755
index 0000000..480e1bd
--- /dev/null
+++ b/dotfiles/system/.local/bin/monitor
@@ -0,0 +1,50 @@
+#!/bin/sh
+# Craig Jennings
+# convenience script to switch monitors
+
+# this script assumes there are at most two monitors attached and we want to switch between then
+CHOICES="Laptop\nLaptop-Scaled\nHome-Display\nExternal-Auto\nExternal-Scaled\nVirtualbox"
+
+# laptops always have a monitor connected when running the script.
+LAPTOP=$(xrandr -q | grep primary | awk '$2 == "connected" {print $1}')
+echo "primary monitor is $LAPTOP"
+
+# an external monitor will always be a connected monitor that isn't primary
+EXTERNAL=$(xrandr -q | grep -v primary | awk '$2 == "connected" {print $1}')
+
+# start by resetting
+xrandr -s 0
+
+# disable if called automatically, otherwise you'll want the menu
+# if there's only one monitor connected, setup laptop monitor
+# if [ -z "$EXTERNAL" ]; then
+# xrandr -s 0
+# xrandr --output "$LAPTOP" --auto --dpi 144 --scale 0.6
+# exit 0
+# fi
+
+CHOSEN=$(echo -e "$CHOICES" | dmenu -i)
+
+case "$CHOSEN" in
+"Laptop")
+ xrandr --output "$LAPTOP" --auto --output "$EXTERNAL" --off
+ ;;
+"Laptop-Scaled")
+ xrandr --output "$LAPTOP" --auto --dpi 144 --scale 0.6 --output "$EXTERNAL" --off
+ ;;
+"External")
+ xrandr --output "$EXTERNAL" --auto --dpi 96 --mode 3440x1440 --scale 1.0 --output "$LAPTOP" --off
+ ;;
+"External-Auto")
+ xrandr --output "$EXTERNAL" --auto --output "$LAPTOP" --off
+ ;;
+"External-Scaled")
+ xrandr --output "$EXTERNAL" --auto --scale 0.6 --output "$LAPTOP" --off
+ ;;
+"Virtualbox")
+ xrandr --output "$LAPTOP" --auto --mode 1920x1080
+ ;;
+esac
+
+# restore the wallpaper after resolution change
+nitrogen --restore
diff --git a/dotfiles/system/.local/bin/mpd_play_yt_stream b/dotfiles/system/.local/bin/mpd_play_yt_stream
new file mode 100755
index 0000000..b53f298
--- /dev/null
+++ b/dotfiles/system/.local/bin/mpd_play_yt_stream
@@ -0,0 +1,14 @@
+#!/bin/bash
+#
+MYHOST='127.0.0.1' # or your MPD host
+
+mpduri="$(yt-dlp -f best -g $1)#"
+# mpduri="$(yt-dlp -g $1)#"
+# TAG=$(yt-dlp -i --get-filename $1)
+# cadena="{\"title\":\"$TAG\"}"
+# echo "$cadena"
+# mpduri="$mpduri$cadena"
+# echo "$mpduri"
+mpc insert "$mpduri"
+mpc next
+mpc play
diff --git a/dotfiles/system/.local/bin/msmtp-enqueue.sh b/dotfiles/system/.local/bin/msmtp-enqueue.sh
new file mode 100755
index 0000000..c9beaca
--- /dev/null
+++ b/dotfiles/system/.local/bin/msmtp-enqueue.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env sh
+
+QUEUEDIR=$HOME/.msmtpqueue
+
+# Set secure permissions on created directories and files
+umask 077
+
+# Change to queue directory (create it if necessary)
+if [ ! -d "$QUEUEDIR" ]; then
+ mkdir -p "$QUEUEDIR" || exit 1
+fi
+cd "$QUEUEDIR" || exit 1
+
+# Create new unique filenames of the form
+# MAILFILE: ccyy-mm-dd-hh.mm.ss[-x].mail
+# MSMTPFILE: ccyy-mm-dd-hh.mm.ss[-x].msmtp
+# where x is a consecutive number only appended if you send more than one
+# mail per second.
+BASE="$(date +%Y-%m-%d-%H.%M.%S)"
+if [ -f "$BASE.mail" ] || [ -f "$BASE.msmtp" ]; then
+ TMP="$BASE"
+ i=1
+ while [ -f "$TMP-$i.mail" ] || [ -f "$TMP-$i.msmtp" ]; do
+ i=$((i + 1))
+ done
+ BASE="$BASE-$i"
+fi
+MAILFILE="$BASE.mail"
+MSMTPFILE="$BASE.msmtp"
+
+# Write command line to $MSMTPFILE
+echo "$@" > "$MSMTPFILE" || exit 1
+
+# Write the mail to $MAILFILE
+cat > "$MAILFILE" || exit 1
+
+# If we are online, run the queue immediately.
+# Replace the test with something suitable for your site.
+#ping -c 1 -w 2 SOME-IP-ADDRESS > /dev/null
+#if [ $? -eq 0 ]; then
+# msmtp-runqueue.sh > /dev/null &
+#fi
+
+exit 0
diff --git a/dotfiles/system/.local/bin/msmtp-listqueue.sh b/dotfiles/system/.local/bin/msmtp-listqueue.sh
new file mode 100755
index 0000000..cc97c58
--- /dev/null
+++ b/dotfiles/system/.local/bin/msmtp-listqueue.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+
+QUEUEDIR=$HOME/.msmtpqueue
+
+for i in $QUEUEDIR/*.mail; do
+ grep -E -s --colour -h '(^From:|^To:|^Subject:)' "$i" || echo "No mail in queue";
+ echo " "
+done
diff --git a/dotfiles/system/.local/bin/msmtp-runqueue.sh b/dotfiles/system/.local/bin/msmtp-runqueue.sh
new file mode 100755
index 0000000..1200610
--- /dev/null
+++ b/dotfiles/system/.local/bin/msmtp-runqueue.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env sh
+
+QUEUEDIR="$HOME/.msmtpqueue"
+LOCKFILE="$QUEUEDIR/.lock"
+MAXWAIT=120
+
+OPTIONS=$*
+
+# eat some options that would cause msmtp to return 0 without sendmail mail
+case "$OPTIONS" in
+ *--help*)
+ echo "$0: send mails in $QUEUEDIR"
+ echo "Options are passed to msmtp"
+ exit 0
+ ;;
+ *--version*)
+ echo "$0: unknown version"
+ exit 0
+ ;;
+esac
+
+# wait for a lock that another instance has set
+WAIT=0
+while [ -e "$LOCKFILE" ] && [ "$WAIT" -lt "$MAXWAIT" ]; do
+ sleep 1
+ WAIT="$((WAIT + 1))"
+done
+if [ -e "$LOCKFILE" ]; then
+ echo "Cannot use $QUEUEDIR: waited $MAXWAIT seconds for"
+ echo "lockfile $LOCKFILE to vanish, giving up."
+ echo "If you are sure that no other instance of this script is"
+ echo "running, then delete the lock file."
+ exit 1
+fi
+
+# change into $QUEUEDIR
+cd "$QUEUEDIR" || exit 1
+
+# check for empty queuedir
+if [ "$(echo ./*.mail)" = './*.mail' ]; then
+ echo "No mails in $QUEUEDIR"
+ exit 0
+fi
+
+# lock the $QUEUEDIR
+touch "$LOCKFILE" || exit 1
+
+# process all mails
+for MAILFILE in *.mail; do
+ MSMTPFILE="$(echo $MAILFILE | sed -e 's/mail/msmtp/')"
+ echo "*** Sending $MAILFILE to $(sed -e 's/^.*-- \(.*$\)/\1/' $MSMTPFILE) ..."
+ if [ ! -f "$MSMTPFILE" ]; then
+ echo "No corresponding file $MSMTPFILE found"
+ echo "FAILURE"
+ continue
+ fi
+ msmtp $OPTIONS $(cat "$MSMTPFILE") < "$MAILFILE"
+ if [ $? -eq 0 ]; then
+ rm "$MAILFILE" "$MSMTPFILE"
+ echo "$MAILFILE sent successfully"
+ else
+ echo "FAILURE"
+ fi
+done
+
+# remove the lock
+rm -f "$LOCKFILE"
+
+exit 0
diff --git a/dotfiles/system/.local/bin/open-file-in-eww b/dotfiles/system/.local/bin/open-file-in-eww
new file mode 100755
index 0000000..e77899e
--- /dev/null
+++ b/dotfiles/system/.local/bin/open-file-in-eww
@@ -0,0 +1,2 @@
+#!/bin/sh
+emacsclient --eval "(eww-open-file \"$1\")"
diff --git a/dotfiles/system/.local/bin/opus2mp3 b/dotfiles/system/.local/bin/opus2mp3
new file mode 100755
index 0000000..eef37ed
--- /dev/null
+++ b/dotfiles/system/.local/bin/opus2mp3
@@ -0,0 +1,3 @@
+#!/bin/sh
+# Craig Jennings Monday, April 25, 2022
+for f in *.opus; do ffmpeg -i "$f" -codec:v copy -codec:a libmp3lame -q:a 2 "${f%.opus}.mp3"; done
diff --git a/dotfiles/system/.local/bin/project b/dotfiles/system/.local/bin/project
new file mode 100755
index 0000000..cf5918d
--- /dev/null
+++ b/dotfiles/system/.local/bin/project
@@ -0,0 +1,100 @@
+#!/usr/bin/env bash
+
+echo ""
+
+# Check parameter
+if [ "$#" -ne 1 ] || [ "$1" != "start" ] && [ "$1" != "end" ]; then
+ echo "This script must be called with either 'start' or 'end' as a parameter."
+ exit 1
+fi
+
+CHECK_MARK="\033[0;32m\xE2\x9C\x94\033[0m"
+CLEAR_LINE="\033[1K"
+
+# Define directories to process
+project_dirs="$HOME/projects"
+code_dirs="$HOME/code"
+sync_dirs="$HOME/sync"
+
+
+# Git pull quietly unless there's an error
+git_maybe_pull() {
+ git fetch --quiet
+ if ! git diff --quiet HEAD FETCH_HEAD; then
+ git pull --quiet
+
+ # clear line and message
+ echo -ne "\033[1K"
+ echo -e "\\rpulled remote changes into $1"
+ fi
+}
+
+# Git stash quietly unless there's an error
+git_stash () {
+ git stash > /dev/null 2>&1 || \
+ echo "git stash error in $1: $? "
+}
+
+# Git stash pop quietly unless there's an error
+git_stash_pop () {
+ git stash pop > /dev/null 2>&1 || \
+ echo "git stash error in $1: $? "
+}
+
+# Function to process a directory
+process_directory() {
+ if [ -d "$1/.git" ]; then
+ # Check remote repository
+ cd "$1"
+
+ # skip URLs with http/s URLS as they're directories cloned for reference only
+ # skip git directories with no remote repository associated as well
+ remote_url=$(git config --get remote.origin.url)
+ if [ -n "$remote_url" ]; then
+ # if remote URL is http or https or empty, skip the directory
+ if [ -z "$remote_url" ] || echo "$remote_url" | grep -E -q "^(http|https)://"; then
+ return
+ fi
+
+ # clear line and update directory
+ echo -ne "$CLEAR_LINE"
+ echo -ne "\\rchecking: $1 "
+
+ if [ "$2" = "start" ]; then
+ if [ -n "$(git status --porcelain)" ]; then
+ # notify user of uncommitted work
+ echo ""; echo ">>>> uncommitted work found in $1";
+
+ # git stash, pull latest files, then pop uncommitted work
+ git_stash "$1"
+ git_maybe_pull "$1"
+ git_stash_pop "$1"
+ else
+ # retrieve any latest changes
+ git_maybe_pull "$1"
+ fi
+ elif [ "$2" = "end" ]; then
+ # Check for uncommitted work
+ if [ -n "$(git status --porcelain)" ]; then
+ echo ""; echo ">>>> Uncommitted work found in $1. <<<<"; echo ""
+ fi
+ return # Skip pulling changes
+ fi
+ fi
+ fi
+}
+
+# Process directories
+for directory in "$project_dirs"/*; do
+ process_directory "$directory" "$1"
+done
+for directory in "$sync_dirs"/*; do
+ process_directory "$directory" "$1"
+done
+for directory in "$code_dirs"/*; do
+ process_directory "$directory" "$1"
+done
+
+# clear line and message finished
+echo -ne "\033[1K"
+echo -ne "\\rfinished.\n"
diff --git a/dotfiles/system/.local/bin/prompt b/dotfiles/system/.local/bin/prompt
new file mode 100755
index 0000000..666434f
--- /dev/null
+++ b/dotfiles/system/.local/bin/prompt
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# A dmenu binary prompt script.
+# Gives a dmenu prompt labeled with $1 to perform command $2.
+# For example:
+# `./prompt "Do you want to shutdown?" "shutdown -h now"`
+
+[ "$(printf "No\\nYes" | dmenu -i -p "$1" -nb darkred -sb red -sf white -nf gray )" = "Yes" ] && $2
diff --git a/dotfiles/system/.local/bin/protonvpn b/dotfiles/system/.local/bin/protonvpn
new file mode 100755
index 0000000..0f24068
--- /dev/null
+++ b/dotfiles/system/.local/bin/protonvpn
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+flatpak run com.protonvpn.www \ No newline at end of file
diff --git a/dotfiles/system/.local/bin/ps-mem b/dotfiles/system/.local/bin/ps-mem
new file mode 100755
index 0000000..b24b003
--- /dev/null
+++ b/dotfiles/system/.local/bin/ps-mem
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Craig Jennings <c@cjennings.net>
+# Outputs a process's memory usage in multiple size units.
+
+# Get a list of all processes
+procs=$(ps aux --sort=-%mem | awk '{print $2, $4, $11}' | fzf)
+
+# Check if a process was selected
+if [ -z "$procs" ]; then
+ echo "No process selected."
+ exit 1
+fi
+
+# Get the PID of the selected process (first field)
+PID=$(echo $procs | awk '{print $1}')
+
+# Get the process name
+PROCNAME=$(ps -p $PID -o comm=)
+
+# Get the memory usage
+KB=$(pmap -x $PID | grep total | awk '{print $4}')
+
+# Convert to MB and GB
+MB=$(echo "scale=2; $KB / 1024" | bc)
+GB=$(echo "scale=2; $MB / 1024" | bc)
+
+# Print the memory usage
+printf "$PROCNAME (pid $PID) mem usage: $KB KB | $MB MB | $GB GB\n\n"
diff --git a/dotfiles/system/.local/bin/recordnow b/dotfiles/system/.local/bin/recordnow
new file mode 100755
index 0000000..4e2d04a
--- /dev/null
+++ b/dotfiles/system/.local/bin/recordnow
@@ -0,0 +1,26 @@
+#!/usr/bin/env sh
+# Craig Jennings <c@cjennings.net>
+
+# Start a screen recording using ffmpeg to capture the entire
+# screen along with all audio and the microphone.
+
+# Make sure that ffmpeg is in the path and the destination directory
+# exists.
+
+LOCATION="$HOME/videos/recordings"
+NAME=$(date +'%Y-%m-%d-%H-%M-%S')
+echo $NAME
+
+# create the directory if it doesn't exist
+if [ ! -d "$LOCATION" ]; then
+ mkdir -p "$LOCATION"
+fi
+
+# error out if ffmpeg isn't installed
+if ! command -v ffmpeg &> /dev/null
+then
+ echo "ERROR: ffmpeg couldn't be found. Please ensure it's installed and added to your PATH."
+ exit
+fi
+
+ffmpeg -framerate 30 -f x11grab -i :0.0+ -f pulse -i alsa_input.pci-0000_00_1b.0.analog-stereo -ac 1 -f pulse -i alsa_output.pci-0000_00_1b.0.analog-stereo.monitor -ac 2 "$LOCATION/$NAME".mkv
diff --git a/dotfiles/system/.local/bin/refresharchkeys b/dotfiles/system/.local/bin/refresharchkeys
new file mode 100755
index 0000000..db1e755
--- /dev/null
+++ b/dotfiles/system/.local/bin/refresharchkeys
@@ -0,0 +1,6 @@
+#!/bin/sh
+sudo rm -R /etc/pacman.d/gnupg
+sudo pacman-key --init
+sudo pacman-key --populate archlinux
+sudo pacman -Sy archlinux-keyring
+sudo pacman -Syu
diff --git a/dotfiles/system/.local/bin/remaps b/dotfiles/system/.local/bin/remaps
new file mode 100755
index 0000000..c95ac84
--- /dev/null
+++ b/dotfiles/system/.local/bin/remaps
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# This script is called on startup to remap keys.
+# Decrease key repeat delay to 300ms and increase key repeat rate to 50 per second.
+xset r rate 300 50
+# Map the caps lock key to super, and map the menu key to right super.
+setxkbmap -option caps:super,altwin:menu_win
+# When caps lock is pressed only once, treat it as escape.
+killall xcape 2>/dev/null ; xcape -e 'Super_L=Escape'
+# Turn off caps lock if on since there is no longer a key for it.
+xset -q | grep "Caps Lock:\s*on" && xdotool key Caps_Lock
diff --git a/dotfiles/system/.local/bin/resetmimetypes b/dotfiles/system/.local/bin/resetmimetypes
new file mode 100755
index 0000000..b744c24
--- /dev/null
+++ b/dotfiles/system/.local/bin/resetmimetypes
@@ -0,0 +1,273 @@
+# Remove Old Databases
+rm ~/.config/mimeapps.list >> /dev/null 2>&1
+rm ~/.local/share/applications/mimeinfo.cache >> /dev/null 2>&1
+rm ~/.local/share/applications/mimeinfo.list >> /dev/null 2>&1
+
+# Directory Node: thunar
+# Open directory nodes in thunar
+xdg-mime default thunar.desktop inode/directory
+
+# Audio Files: audacious
+xdg-mime default audacious.desktop audio/basic
+xdg-mime default audacious.desktop audio/flac.wav
+xdg-mime default audacious.desktop audio/mp4
+xdg-mime default audacious.desktop audio/mpeg
+xdg-mime default audacious.desktop audio/ogg
+xdg-mime default audacious.desktop audio/opus
+xdg-mime default audacious.desktop audio/vnd.rn-realaudio
+xdg-mime default audacious.desktop audio/vnd.wav
+xdg-mime default audacious.desktop audio/vorbis
+xdg-mime default audacious.desktop audio/x-aiff
+xdg-mime default audacious.desktop audio/x-mpegurl
+
+# Video Files: mpv
+# xdg-mime default mpv.desktop application/mpeg4-iod
+# xdg-mime default mpv.desktop application/mpeg4-muxcodetable
+# xdg-mime default mpv.desktop application/ogg
+# xdg-mime default mpv.desktop application/vnd.apple.mpegurl
+# xdg-mime default mpv.desktop application/x-quicktime-media-link
+# xdg-mime default mpv.desktop application/x-quicktimeplayer
+# xdg-mime default mpv.desktop application/x-shockwave-flash
+# xdg-mime default mpv.desktop video/avi
+# xdg-mime default mpv.desktop video/divx
+# xdg-mime default mpv.desktop video/flv
+# xdg-mime default mpv.desktop video/mp4
+# xdg-mime default mpv.desktop video/mp4
+# xdg-mime default mpv.desktop video/mp4v-es
+# xdg-mime default mpv.desktop video/mpeg
+# xdg-mime default mpv.desktop video/mpeg-system
+# xdg-mime default mpv.desktop video/msvideo
+# xdg-mime default mpv.desktop video/ogg
+# xdg-mime default mpv.desktop video/quicktime
+# xdg-mime default mpv.desktop video/vnd.divx
+# xdg-mime default mpv.desktop video/vnd.mpegurl
+# xdg-mime default mpv.desktop video/vnd.rn-realvideo
+# xdg-mime default mpv.desktop video/webm
+# xdg-mime default mpv.desktop video/x-avi
+# xdg-mime default mpv.desktop video/x-flv
+# xdg-mime default mpv.desktop video/x-m4v
+# xdg-mime default mpv.desktop video/x-matroska
+# xdg-mime default mpv.desktop video/x-mpeg
+# xdg-mime default mpv.desktop video/x-mpeg-system
+# xdg-mime default mpv.desktop video/x-mpeg2
+# xdg-mime default mpv.desktop video/x-ms-wmv
+# xdg-mime default mpv.desktop video/x-msvideo
+# xdg-mime default mpv.desktop video/x-theora
+# xdg-mime default mpv.desktop video/x-theora+ogg
+# xdg-mime default mpv.desktop x-content/video-dvd
+# xdg-mime default mpv.desktop x-content/video-svcd
+# xdg-mime default mpv.desktop x-content/video-vcd
+
+# Video Files: vlc
+xdg-mime default vlc.desktop application/mpeg4-iod
+xdg-mime default vlc.desktop application/mpeg4-muxcodetable
+xdg-mime default vlc.desktop application/ogg
+xdg-mime default vlc.desktop application/vnd.apple.mpegurl
+xdg-mime default vlc.desktop application/x-quicktime-media-link
+xdg-mime default vlc.desktop application/x-quicktimeplayer
+xdg-mime default vlc.desktop application/x-shockwave-flash
+xdg-mime default vlc.desktop video/avi
+xdg-mime default vlc.desktop video/divx
+xdg-mime default vlc.desktop video/flv
+xdg-mime default vlc.desktop video/mp4
+xdg-mime default vlc.desktop video/mp4
+xdg-mime default vlc.desktop video/mp4v-es
+xdg-mime default vlc.desktop video/mpeg
+xdg-mime default vlc.desktop video/mpeg-system
+xdg-mime default vlc.desktop video/msvideo
+xdg-mime default vlc.desktop video/ogg
+xdg-mime default vlc.desktop video/quicktime
+xdg-mime default vlc.desktop video/vnd.divx
+xdg-mime default vlc.desktop video/vnd.mpegurl
+xdg-mime default vlc.desktop video/vnd.rn-realvideo
+xdg-mime default vlc.desktop video/webm
+xdg-mime default vlc.desktop video/x-avi
+xdg-mime default vlc.desktop video/x-flv
+xdg-mime default vlc.desktop video/x-m4v
+xdg-mime default vlc.desktop video/x-matroska
+xdg-mime default vlc.desktop video/x-mpeg
+xdg-mime default vlc.desktop video/x-mpeg-system
+xdg-mime default vlc.desktop video/x-mpeg2
+xdg-mime default vlc.desktop video/x-ms-wmv
+xdg-mime default vlc.desktop video/x-msvideo
+xdg-mime default vlc.desktop video/x-theora
+xdg-mime default vlc.desktop video/x-theora+ogg
+xdg-mime default vlc.desktop x-content/video-dvd
+xdg-mime default vlc.desktop x-content/video-svcd
+xdg-mime default vlc.desktop x-content/video-vcd
+
+
+# Images: NSXIV
+xdg-mime default nsxiv.desktop image/bmp
+xdg-mime default nsxiv.desktop image/gif
+xdg-mime default nsxiv.desktop image/jpegmix.desktop;
+xdg-mime default nsxiv.desktop image/jpg
+xdg-mime default nsxiv.desktop image/png
+xdg-mime default nsxiv.desktop image/tiff
+xdg-mime default nsxiv.desktop image/x-bmp
+xdg-mime default nsxiv.desktop image/x-eps
+xdg-mime default nsxiv.desktop image/x-ico
+xdg-mime default nsxiv.desktop image/x-icon
+xdg-mime default nsxiv.desktop image/x-xbitmap
+xdg-mime default nsxiv.desktop image/x-xpixmapq
+
+# Torrent Files: Transmission Remote
+xdg-mime default io.github.TransmissionRemoteGtk-gtk.desktop application/x-bittorrent
+xdg-mime default io.github.TransmissionRemoteGtk.desktop x-scheme-handler/magnet
+
+# Web Browser: Chromium Browser
+# xdg-mime default chromium.desktop application/rdf+xml
+# xdg-mime default chromium.desktop application/rss+xml
+# xdg-mime default chromium.desktop application/xhtml+xml
+# xdg-mime default chromium.desktop application/xhtml_xml
+# xdg-mime default chromium.desktop application/xml
+# # xdg-mime default chromium.desktop image/gif
+# # xdg-mime default chromium.desktop image/jpeg
+# # xdg-mime default chromoum.desktop image/png
+# # xdg-mime default chromium.desktop image/webp
+# xdg-mime default chromium.desktop text/html
+# xdg-mime default chromium.desktop text/xml
+# xdg-mime default chromium.desktop x-scheme-handler/http
+# xdg-mime default chromium.desktop x-scheme-handler/https
+
+# Web Browser: Google-Chrome Browser
+# xdg-mime default google-chrome.desktop application/rdf+xml
+# xdg-mime default google-chrome.desktop application/rss+xml
+# xdg-mime default google-chrome.desktop application/xhtml+xml
+# xdg-mime default google-chrome.desktop application/xhtml_xml
+# xdg-mime default google-chrome.desktop application/xml
+# # xdg-mime default google-chrome.desktop image/gif
+# # xdg-mime default google-chrome.desktop image/jpeg
+# # xdg-mime default chromoum.desktop image/png
+# # xdg-mime default google-chrome.desktop image/webp
+# xdg-mime default google-chrome.desktop text/html
+# xdg-mime default google-chrome.desktop text/xml
+# xdg-mime default google-chrome.desktop x-scheme-handler/http
+# xdg-mime default google-chrome.desktop x-scheme-handler/https
+
+
+# Web Browser: Firefox
+xdg-mime default firefox.desktop application/rdf+xml
+xdg-mime default firefox.desktop application/rss+xml
+xdg-mime default firefox.desktop application/xhtml+xml
+xdg-mime default firefox.desktop application/xhtml_xml
+xdg-mime default firefox.desktop application/xml
+# xdg-mime default firefox.desktop image/gif
+# xdg-mime default firefox.desktop image/jpeg
+# xdg-mime default firefox.desktop image/png
+# xdg-mime default firefox.desktop image/webp
+xdg-mime default firefox.desktop text/html
+xdg-mime default firefox.desktop text/xml
+xdg-mime default firefox.desktop x-scheme-handler/http
+xdg-mime default firefox.desktop x-scheme-handler/https
+
+# Mobi Ebooks: calibre-ebook-reader
+xdg-mime default calibre-ebook-viewer.desktop application/x-mobi8-ebook
+xdg-mime default calibre-ebook-viewer.desktop application/x-mobipocket-ebook
+
+# Text and Source Code: Emacsclient
+xdg-mime default emacsclient.desktop application/x-shellscript
+xdg-mime default emacsclient.desktop text/english
+xdg-mime default emacsclient.desktop text/markdown
+xdg-mime default emacsclient.desktop text/plain
+xdg-mime default emacsclient.desktop text/x-c
+xdg-mime default emacsclient.desktop text/x-c++
+xdg-mime default emacsclient.desktop text/x-c++hdr
+xdg-mime default emacsclient.desktop text/x-c++src
+xdg-mime default emacsclient.desktop text/x-chdr
+xdg-mime default emacsclient.desktop text/x-csrc
+xdg-mime default emacsclient.desktop text/x-java
+xdg-mime default emacsclient.desktop text/x-makefile
+xdg-mime default emacsclient.desktop text/x-moc
+xdg-mime default emacsclient.desktop text/x-pascal
+xdg-mime default emacsclient.desktop text/x-tcl
+xdg-mime default emacsclient.desktop text/x-tex
+
+# PDF/EPUB: Emacsclient
+# xdg-mime default emacsclient.desktop application/eps
+# xdg-mime default emacsclient.desktop application/epub+zip
+# xdg-mime default emacsclient.desktop application/oxps
+# xdg-mime default emacsclient.desktop application/pdf
+# xdg-mime default emacsclient.desktop application/postscript
+# xdg-mime default emacsclient.desktop application/ps
+# xdg-mime default emacsclient.desktop application/x-fictionbook;
+# xdg-mime default emacsclient.desktop image/eps
+# xdg-mime default emacsclient.desktop image/vnd.djvu
+# xdg-mime default emacsclient.desktop image/vnd.djvu+multipage
+
+# ePUB: Foliate
+# xdg-mime default com.github.johnfactotum.Foliate.desktop application/epub+zip
+
+# PDF ePUB: Zathura
+xdg-mime default org.pwmt.zathura.desktop application/eps
+xdg-mime default org.pwmt.zathura.desktop application/epub+zip
+xdg-mime default org.pwmt.zathura.desktop application/oxps
+xdg-mime default org.pwmt.zathura.desktop application/pdf
+xdg-mime default org.pwmt.zathura.desktop application/postscript
+xdg-mime default org.pwmt.zathura.desktop application/ps
+xdg-mime default org.pwmt.zathura.desktop application/x-fictionbook;
+xdg-mime default org.pwmt.zathura.desktop image/eps
+xdg-mime default org.pwmt.zathura.desktop image/vnd.djvu
+xdg-mime default org.pwmt.zathura.desktop image/vnd.djvu+multipage
+
+# PDF ePUB: Evince
+# xdg-mime default org.gnome.Evince.desktop application/eps
+# # xdg-mime default org.gnome.Evince.desktop application/epub+zip
+# xdg-mime default org.gnome.Evince.desktop application/oxps
+# xdg-mime default org.gnome.Evince.desktop application/pdf
+# xdg-mime default org.gnome.Evince.desktop application/postscript
+# xdg-mime default org.gnome.Evince.desktop application/ps
+# # xdg-mime default org.gnome.Evince.desktop application/x-fictionbook;
+# # xdg-mime default org.gnome.Evince.desktop image/eps
+# xdg-mime default org.gnome.Evince.desktop image/vnd.djvu
+# xdg-mime default org.gnome.Evince.desktop image/vnd.djvu+multipage
+
+# Comics Files: Zathura
+xdg-mime default org.pwmt.zathura.desktop application/vnd.comicbook+zip
+xdg-mime default org.pwmt.zathura.desktop application/vnd.comicbook-rar
+
+# Libreoffice Writer
+xdg-mime default libreoffice-writer.desktop application/clarisworks
+xdg-mime default libreoffice-writer.desktop application/macwriteii
+xdg-mime default libreoffice-writer.desktop application/msword
+xdg-mime default libreoffice-writer.desktop application/prs.plucker
+xdg-mime default libreoffice-writer.desktop application/rtf
+xdg-mime default libreoffice-writer.desktop application/vnd.lotus-wordpro
+xdg-mime default libreoffice-writer.desktop application/vnd.ms-word
+xdg-mime default libreoffice-writer.desktop application/vnd.ms-word.template.macroEnabled.12
+xdg-mime default libreoffice-writer.desktop application/vnd.ms-works
+xdg-mime default libreoffice-writer.desktop application/vnd.oasis.opendocument.text
+xdg-mime default libreoffice-writer.desktop application/vnd.oasis.opendocument.text-flat-xml
+xdg-mime default libreoffice-writer.desktop application/vnd.oasis.opendocument.text-master
+xdg-mime default libreoffice-writer.desktop application/vnd.oasis.opendocument.text-master-template
+xdg-mime default libreoffice-writer.desktop application/vnd.oasis.opendocument.text-template
+xdg-mime default libreoffice-writer.desktop application/vnd.oasis.opendocument.text-web
+xdg-mime default libreoffice-writer.desktop application/vnd.openxmlformats-officedocument
+xdg-mime default libreoffice-writer.desktop application/vnd.openxmlformats-officedocument.wordprocessingml.document
+xdg-mime default libreoffice-writer.desktop application/vnd.palm
+xdg-mime default libreoffice-writer.desktop application/vnd.stardivision.writer-global
+xdg-mime default libreoffice-writer.desktop application/vnd.sun.xml.writer
+xdg-mime default libreoffice-writer.desktop application/vnd.sun.xml.writer.global
+xdg-mime default libreoffice-writer.desktop application/vnd.sun.xml.writer.template
+xdg-mime default libreoffice-writer.desktop application/vnd.wordperfect
+xdg-mime default libreoffice-writer.desktop application/wordperfect
+xdg-mime default libreoffice-writer.desktop application/x-abiword
+xdg-mime default libreoffice-writer.desktop application/x-aportisdoc
+xdg-mime default libreoffice-writer.desktop application/x-doc
+xdg-mime default libreoffice-writer.desktop application/x-extension-txt
+xdg-mime default libreoffice-writer.desktop application/x-fictionbook+xml
+xdg-mime default libreoffice-writer.desktop application/x-hwp
+xdg-mime default libreoffice-writer.desktop application/x-iwork-pages-sffpages
+xdg-mime default libreoffice-writer.desktop application/x-mswrite
+xdg-mime default libreoffice-writer.desktop application/x-sony-bbeb
+xdg-mime default libreoffice-writer.desktop application/x-starwriter
+xdg-mime default libreoffice-writer.desktop application/x-t602
+xdg-mime default libreoffice-writer.desktop text/rtf
+
+# FTP Scheme-Handler: Filezilla
+xdg-mime default filezilla.desktop x-scheme-handler/ftp
+
+# Org-Protocol Scheme-Handler: emacsclient
+xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
+
+update-desktop-database ~/.local/share/applications/
diff --git a/dotfiles/system/.local/bin/samedir b/dotfiles/system/.local/bin/samedir
new file mode 100755
index 0000000..371ec64
--- /dev/null
+++ b/dotfiles/system/.local/bin/samedir
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Open a terminal window in the same directory as the currently active window.
+
+PID=$(xprop -id "$(xprop -root | xprop -root | sed -n "/_NET_ACTIVE_WINDOW/ s/^.*# // p")" | sed -n "/PID/ s/^.*= // p")
+PID="$(pstree -lpA "$PID")"
+PID="${PID##*"${SHELL##*/}"(}"
+PID="${PID%%)*}"
+cd "$(readlink /proc/"$PID"/cwd)" || return 1
+"$TERMINAL"
diff --git a/dotfiles/system/.local/bin/screenshotmenu b/dotfiles/system/.local/bin/screenshotmenu
new file mode 100755
index 0000000..c899dfc
--- /dev/null
+++ b/dotfiles/system/.local/bin/screenshotmenu
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Requires maim, xdotool, and dmenu
+# Uses dmenu to choose the type of screenshot to take,
+
+case "$(printf "full screen\\nselected area\\ncurrent window\\nselected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | dmenu -l 6 -i -p "Screenshot which area?")" in
+ "full screen") file="$(date +%Y.%m.%d-%M%S).png" && maim ~/pictures/screenshots/$file && notify-send "Image selection saved to ~/pictures/screenshots/$file" ;;
+ "full screen (5 sec delay)") file="$(date +%Y.%m.%d-%M%S).png" && sleep 5 && maim ~/pictures/screenshots/$file && notify-send "Image selection saved to ~/pictures/screenshots/$file" ;;
+ "selected area") file="$(date +%Y.%m.%d-%M%S).png" && maim -s ~/pictures/screenshots/$file && notify-send "Image selection saved to ~/pictures/screenshots/$file" ;;
+ "current window") maim -i "$(xdotool getactivewindow)" '~/pictures/screenshots/$(date +%Y.%m.%d-%M%S).png' && notify-send "Image selection saved to ~/pictures/screenshots/" ;;
+ "selected area (copy)") maim -s | xclip -selection clipboard -t image/png && notify-send "Image selection copied to clipboard." ;;
+ "current window (copy)") maim -i "$(xdotool getactivewindow)" | xclip -selection clipboard -t image/png && notify-send "Image selection copied to clipboard." ;;
+ "full screen (copy)") maim | xclip -selection clipboard -t image/png && notify-send "Image copied to clipboard." ;;
+esac
diff --git a/dotfiles/system/.local/bin/setbg b/dotfiles/system/.local/bin/setbg
new file mode 100755
index 0000000..b72dc7d
--- /dev/null
+++ b/dotfiles/system/.local/bin/setbg
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# This script does the following:
+# Run by itself, set the wallpaper (at X start).
+# If given a file, set that as the new wallpaper.
+# If given a directory, choose random file in it.
+# If wal is installed, also generates a colorscheme.
+
+# Location of link to wallpaper link.
+bgloc="${XDG_DATA_HOME:-$HOME/.local/share}/bg"
+
+# Configuration files of applications that have their themes changed by pywal.
+dunstconf="${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc"
+zathuraconf="${XDG_CONFIG_HOME:-$HOME/.config}/zathura/zathurarc"
+
+trueloc="$(readlink -f "$1")" &&
+case "$(file --mime-type -b "$trueloc")" in
+ image/* ) ln -sf "$(readlink -f "$1")" "$bgloc" && notify-send -i "$bgloc" "Changing wallpaper..." ;;
+ inode/directory ) ln -sf "$(find "$trueloc" -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" "$bgloc" && notify-send -i "$bgloc" "Random Wallpaper chosen." ;;
+ *) notify-send "🖼️ Error" "Not a valid image or directory." ; exit 1;;
+esac
+
+# If pywal is installed, use it.
+if command -v wal >/dev/null 2>&1 ; then
+ wal -n -i "$(readlink -f $bgloc)" -o "${XDG_CONFIG_HOME:-$HOME/.config}/wal/postrun" >/dev/null 2>&1
+# If pywal is removed, return config files to normal.
+else
+ [ -f "$dunstconf.bak" ] && unlink "$dunstconf" && mv "$dunstconf.bak" "$dunstconf"
+ [ -f "$zathuraconf.bak" ] && unlink "$zathuraconf" && mv "$zathuraconf.bak" "$zathuraconf"
+fi
+
+xwallpaper --zoom "$bgloc"
+# If running, dwm hit the key to refresh the color scheme.
+pidof dwm >/dev/null && xdotool key super+F5
diff --git a/dotfiles/system/.local/bin/ssh-createkeys b/dotfiles/system/.local/bin/ssh-createkeys
new file mode 100755
index 0000000..a1c14b6
--- /dev/null
+++ b/dotfiles/system/.local/bin/ssh-createkeys
@@ -0,0 +1,3 @@
+#!/bin/sh
+# use strong passwords
+ssh-keygen -t ed25519 -a 100
diff --git a/dotfiles/system/.local/bin/startdwm b/dotfiles/system/.local/bin/startdwm
new file mode 100755
index 0000000..2f2628d
--- /dev/null
+++ b/dotfiles/system/.local/bin/startdwm
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# Craig Jennings <c@cjennings.net>
+# starts the dwm process for a login manager
+# saves the logfile of any output to a logfile
+
+dbus-update-activation-environment &
+
+logdir="$HOME/.local/var/logs"
+logfile="$logdir/$(date +%Y-%m-%d_%H.dwm.log)"
+
+if ! [ -d "$logdir" ]; then
+ mkdir -p "$logdir"
+fi
+
+# allow sudo use of display
+xhost si:localuser:root
+
+# merge local configuration for X client aplications
+[ -f ~/.Xresources ] && xrdb -merge -I $HOME ~/.Xresources
+
+# merge xmodmap configuration
+[[ -f ~/.Xmodmap ]] && xmodmap ~/.Xmodmap
+
+# start desktop environment applications
+(conky | while read LINE; do xsetroot -name "$LINE"; done) &
+xscreensaver --no-splash &
+xautolock -time 5 -locker "xscreensaver-command -activate" &
+picom &
+sxhkd &
+emacs --daemon &
+nitrogen --restore &
+nm-applet &
+blueman-applet &
+battery_monitor &
+mpd &
+caffeine &
+protonmail-bridge --no-window &
+dunst &
+signal-desktop --start-in-tray &
+sudo powertop --auto-tune &
+flameshot &
+# dropbox &
+touchpad-app &
+
+# start dwm
+echo "$(date): Starting dwm" >> "$logfile" 2>&1
+exec dwm > $logfile 2>&1
diff --git a/dotfiles/system/.local/bin/starth b/dotfiles/system/.local/bin/starth
new file mode 100755
index 0000000..98513d6
--- /dev/null
+++ b/dotfiles/system/.local/bin/starth
@@ -0,0 +1,9 @@
+#!/bin/sh
+# startup file for Hyprland
+
+export WLR_EGL_NO_MODIFIERS=1
+export XDG_CURRENT_DESKTOP=Hyprland
+export XDG_SESSION_TYPE=wayland
+export XDG_SESSION_DESKTOP=Hyprland
+
+exec Hyprland
diff --git a/dotfiles/system/.local/bin/statusbar/sb-battery b/dotfiles/system/.local/bin/statusbar/sb-battery
new file mode 100755
index 0000000..93cbe08
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-battery
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Prints all batteries, their percentage remaining and an emoji corresponding
+# to charge status (🔌 for plugged up, 🔋 for discharging on battery, etc.).
+
+case $BLOCK_BUTTON in
+ 3) notify-send "🔋 Battery module" "🔋: discharging
+🛑: not charging
+♻: stagnant charge
+🔌: charging
+⚡: charged
+❗: battery very low!
+- Scroll to change adjust xbacklight." ;;
+ 4) xbacklight -inc 10 ;;
+ 5) xbacklight -dec 10 ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# Loop through all attached batteries and format the info
+for battery in /sys/class/power_supply/BAT?*; do
+ # If non-first battery, print a space separator.
+ [ -n "${capacity+x}" ] && printf " "
+ # Sets up the status and capacity
+ case "$(cat "$battery/status" 2>&1)" in
+ "Full") status="⚡" ;;
+ "Discharging") status="🔋" ;;
+ "Charging") status="🔌" ;;
+ "Not charging") status="🛑" ;;
+ "Unknown") status="♻️" ;;
+ *) exit 1 ;;
+ esac
+ capacity="$(cat "$battery/capacity" 2>&1)"
+ # Will make a warn variable if discharging and low
+ [ "$status" = "🔋" ] && [ "$capacity" -le 25 ] && warn="❗"
+ # Prints the info
+ printf "%s%s%d%%" "$status" "$warn" "$capacity"; unset warn
+done && printf "\\n"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-clock b/dotfiles/system/.local/bin/statusbar/sb-clock
new file mode 100755
index 0000000..e1ca8c7
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-clock
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+clock=$(date '+%I')
+
+case "$clock" in
+ "00") icon="🕛" ;;
+ "01") icon="🕐" ;;
+ "02") icon="🕑" ;;
+ "03") icon="🕒" ;;
+ "04") icon="🕓" ;;
+ "05") icon="🕔" ;;
+ "06") icon="🕕" ;;
+ "07") icon="🕖" ;;
+ "08") icon="🕗" ;;
+ "09") icon="🕘" ;;
+ "10") icon="🕙" ;;
+ "11") icon="🕚" ;;
+ "12") icon="🕛" ;;
+esac
+
+case $BLOCK_BUTTON in
+ 1) notify-send "This Month" "$(cal --color=always | sed "s/..7m/<b><span color=\"red\">/;s|..27m|</span></b>|")" && notify-send "Appointments" "$(calcurse -d3)" ;;
+ 2) setsid -f "$TERMINAL" -e calcurse ;;
+ 3) notify-send "📅 Time/date module" "\- Left click to show upcoming appointments for the next three days via \`calcurse -d3\` and show the month via \`cal\`
+- Middle click opens calcurse if installed" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+date "+%Y %b %d (%a) $icon%I:%M%p"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-cpu b/dotfiles/system/.local/bin/statusbar/sb-cpu
new file mode 100755
index 0000000..1572b52
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-cpu
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+case $BLOCK_BUTTON in
+ 1) notify-send "🖥 CPU hogs" "$(ps axch -o cmd:15,%cpu --sort=-%cpu | head)\\n(100% per core)" ;;
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🖥 CPU module " "\- Shows CPU temperature.
+- Click to show intensive processes.
+- Middle click to open htop." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+sensors | awk '/Core 0/ {print "🌡" $3}'
diff --git a/dotfiles/system/.local/bin/statusbar/sb-cpubars b/dotfiles/system/.local/bin/statusbar/sb-cpubars
new file mode 100755
index 0000000..297424e
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-cpubars
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# Module showing CPU load as a changing bars.
+# Just like in polybar.
+# Each bar represents amount of load on one core since
+# last run.
+
+# Cache in tmpfs to improve speed and reduce SSD load
+cache=/tmp/cpubarscache
+
+case $BLOCK_BUTTON in
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🪨 CPU load module" "Each bar represents
+one CPU core";;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# id total idle
+stats=$(awk '/cpu[0-9]+/ {printf "%d %d %d\n", substr($1,4), ($2 + $3 + $4 + $5), $5 }' /proc/stat)
+[ ! -f $cache ] && echo "$stats" > "$cache"
+old=$(cat "$cache")
+printf "🪨"
+echo "$stats" | while read -r row; do
+ id=${row%% *}
+ rest=${row#* }
+ total=${rest%% *}
+ idle=${rest##* }
+
+ case "$(echo "$old" | awk '{if ($1 == id)
+ printf "%d\n", (1 - (idle - $3) / (total - $2))*100 /12.5}' \
+ id="$id" total="$total" idle="$idle")" in
+
+ "0") printf "▁";;
+ "1") printf "▂";;
+ "2") printf "▃";;
+ "3") printf "▄";;
+ "4") printf "▅";;
+ "5") printf "▆";;
+ "6") printf "▇";;
+ "7") printf "█";;
+ "8") printf "█";;
+ esac
+done; printf "\\n"
+echo "$stats" > "$cache"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-disk b/dotfiles/system/.local/bin/statusbar/sb-disk
new file mode 100755
index 0000000..e947509
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-disk
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Status bar module for disk space
+# $1 should be drive mountpoint, otherwise assumed /.
+
+location=${1:-/}
+
+[ -d "$location" ] || exit
+
+case $BLOCK_BUTTON in
+ 1) notify-send "💽 Disk space" "$(df -h --output=target,used,size)" ;;
+ 3) notify-send "💽 Disk module" "\- Shows used hard drive space.
+- Click to show all disk info." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+case "$location" in
+ "/home"* ) icon="🏠" ;;
+ "/mnt"* ) icon="💾" ;;
+ *) icon="🖥";;
+esac
+
+printf "%s: %s\n" "$icon" "$(df -h "$location" | awk ' /[0-9]/ {print $3 "/" $2}')"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-doppler b/dotfiles/system/.local/bin/statusbar/sb-doppler
new file mode 100755
index 0000000..b5833a7
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-doppler
@@ -0,0 +1,279 @@
+#!/bin/sh
+
+# Show a Doppler RADAR of a user's preferred location.
+
+secs=600 # Download a new doppler radar if one hasn't been downloaded in $secs seconds.
+radarloc="${XDG_CACHE_HOME:-$HOME/.cache}/radar"
+doppler="${XDG_CACHE_HOME:-$HOME/.cache}/doppler.gif"
+
+pickloc() { chosen="$(echo "US: Northeast
+US: Southeast
+US: PacNorthWest
+US: PacSouthWest
+US: UpperMissVly
+US: SouthMissVly
+US: SouthPlains
+US: NorthRockies
+US: SouthRockies
+US: Alaska
+US: Carib
+US: Hawaii
+US: CentGrLakes
+US: Conus-Large
+US: KABR: Aberdeen, SD
+US: KBIS: Bismarck, ND
+US: KFTG: Denver/Boulder, CO
+US: KDMX: Des Moines, IA
+US: KDTX: Detroit, MI
+US: KDDC: Dodge City, KS
+US: KDLH: Duluth, MN
+US: KCYS: Cheyenne, WY
+US: KLOT: Chicago, IL
+US: KGLD: Goodland, KS
+US: KUEX: Hastings, NE
+US: KGJX: Grand Junction, CO
+US: KGRR: Grand Rapids, MI
+US: KMVX: Fargo/Grand Forks, ND
+US: KGRB: Green Bay, WI
+US: KIND: Indianapolis, IN
+US: KJKL: Jackson, KY
+US: KARX: La Crosse, WI
+US: KILX: Lincoln/Central Illinois, IL
+US: KLVX: Louisville, KY
+US: KMQT: Marquette
+US: KMKX: Milwaukee, WI
+US: KMPX: Minneapolis, MN
+US: KAPX: Gaylord/Alpena, MI
+US: KLNX: North Platte, NE
+US: KIWX: N. Webster/Northern, IN
+US: KOAX: Omaha, NE
+US: KPAH: Paducah, KY
+US: KEAX: Pleasant Hill, MO
+US: KPUX: Pueblo, CO
+US: KDVN: Quad Cities, IA
+US: KUDX: Rapid City, SD
+US: KRIW: Riverton, WY
+US: KSGF: Springfield, MO
+US: KLSX: St. LOUIS, MO
+US: KFSD: Sioux Falls, IA
+US: KTWX: Topeka, KS
+US: KICT: Wichita, KS
+US: KVWX: Paducah, KY
+US: ICAO: Responsible Wfo
+US: KLTX: WILMINGTON, NC
+US: KCCX: State College/Central, PA
+US: KLWX: Sterling, VA
+US: KFCX: Blacksburg/Roanoke, VA
+US: KRAX: Raleigh/Durham, NC
+US: KGYX: Portland, ME
+US: KDIX: Mt Holly/Philadelphia, PA
+US: KPBZ: Pittsburgh, PA
+US: KAKQ: Wakefield, VA
+US: KMHX: Morehead City, NC
+US: KGSP: Greer/Greenville/Sprtbg, SC
+US: KILN: Wilmington/Cincinnati, OH
+US: KCLE: Cleveland, OH
+US: KCAE: Columbia, SC
+US: KBGM: Binghamton, NY
+US: KENX: Albany, NY
+US: KBUF: Buffalo, NY
+US: KCXX: Burlington, VT
+US: KCBW: Caribou, ME
+US: KBOX: Boston /Taunton, MA
+US: KOKX: New York City, NY
+US: KCLX: Charleston, SC
+US: KRLX: Charleston, WV
+US: ICAO: Responsible WFO
+US: KBRO: Brownsville, TX
+US: KABX: Albuquerque, NM
+US: KAMA: Amarillo, TX
+US: KFFC: Peachtree City/Atlanta, GA
+US: KEWX: Austin/Sanantonio, TX
+US: KBMX: Birmingham, AL
+US: KCRP: Corpus Christi, TX
+US: KFWS: Dallas / Ft. Worth, TX
+US: KEPZ: El Paso, TX
+US: KHGX: Houston/ Galveston, TX
+US: KJAX: Jacksonville, FL
+US: KBYX: Key West, FL
+US: KMRX: Morristown/knoxville, TN
+US: KLBB: Lubbock, TX
+US: KLZK: Little Rock, AR
+US: KLCH: Lake Charles, LA
+US: KOHX: Nashville, TN
+US: KMLB: Melbourne, FL
+US: KNQA: Memphis, TN
+US: KAMX: Miami, FL
+US: KMAF: Midland/odessa, TX
+US: KTLX: Norman, OK
+US: KHTX: Huntsville, AL
+US: KMOB: Mobile, AL
+US: KTLH: Tallahassee, FL
+US: KTBW: Tampa Bay Area, FL
+US: KSJT: San Angelo, TX
+US: KINX: Tulsa, OK
+US: KSRX: Tulsa, OK
+US: KLIX: New Orleans/slidell, LA
+US: KDGX: Jackson, MS
+US: KSHV: Shreveport, LA
+US: ICAO: Responsible WFO
+US: KLGX: Seattle / Tacoma, WA
+US: KOTX: Spokane, WA
+US: KEMX: Tucson, AZ
+US: KYUX: Phoenix, AZ
+US: KNKX: San Diego, CA
+US: KMUX: Monterey/san Francisco, CA
+US: KHNX: San Joaquin/hanford, CA
+US: KSOX: San Diego, CA
+US: KATX: Seattle / Tacoma, WA
+US: KIWA: Phoenix, AZ
+US: KRTX: Portland, OR
+US: KSFX: Pocatello, ID
+US: KRGX: Reno, NV
+US: KDAX: Sacramento, CA
+US: KMTX: Salt Lake City, UT
+US: KPDT: Pendleton, OR
+US: KMSX: Missoula, MT
+US: KESX: Las Vegas, NV
+US: KVTX: Los Angeles, CA
+US: KMAX: Medford, OR
+US: KFSX: Flagstaff, AZ
+US: KGGW: Glasgow, MT
+US: KLRX: Elko, NV
+US: KBHX: Eureka, CA
+US: KTFX: Great Falls, MT
+US: KCBX: Boise, ID
+US: KBLX: Billings, MT
+US: KICX: Salt Lake City, UT
+US: ICAO: Responsible Wfo W/ MSCF
+US: PABC: Anchorage, AK
+US: PAPD: Fairbanks, AK
+US: PHKM: Honolulu, HI
+US: PAHG: Anchorage, AK
+US: PAKC: Anchorage, AK
+US: PAIH: Anchorage, AK
+US: PHMO: Honolulu, HI
+US: PAEC: Fairbanks, AK
+US: TJUA: San Juan, PR
+US: PACG: Juneau, AK
+US: PHKI: Honolulu, HI
+US: PHWA: Honolulu, HI
+US: ICAO: Responsible Wfo W/ MSCF
+US: KFDR: Norman, OK
+US: PGUA: Guam
+US: KBBX: Sacramento, CA
+US: KFDX: Albuquerque, NM
+US: KGWX: Jackson, MS
+US: KDOX: Wakefield, VA
+US: KDYX: San Angelo, TX
+US: KEYX: Las Vegas, NV
+US: KEVX: Mobile, AL
+US: KHPX: Paducah, KY
+US: KTYX: Burlington, VT
+US: KGRK: Dallas / Ft. Worth, TX
+US: KPOE: Lake Charles, LA
+US: KEOX: Tallahassee, FL
+US: KHDX: El Paso, TX
+US: KDFX: San Antonio, TX
+US: KMXX: Birmingham, AL
+US: KMBX: Bismarck, ND
+US: KVAX: Jacksonville, FL
+US: KJGX: Peachtree City/atlanta, GA
+US: KVNX: Norman, OK
+US: KVBX: Vandenberg Afb: Orcutt, CA
+EU: Europe
+EU: GB: Great Brittain
+EU: SCAN: Scandinavia
+EU: ALPS: The Alps
+EU: NL: The Netherlands
+EU: DE: Germany
+EU: SP: Spain
+EU: FR: France
+EU: IT: Italy
+EU: PL: Poland
+EU: GR: Greece
+EU: TU: Turkey
+EU: RU: Russia
+EU: BA: Bahrain
+EU: BC: Botswana
+EU: SE: Republic of Seychelles
+EU: HU: Hungary
+EU: UK: Ukraine
+AF: AF: Africa
+AF: WA: West Africa
+AF: ZA: South Africa
+AF: DZ: Algeria
+AF: CE: Canary Islands
+AF: NG: Nigeria
+AF: TD: Chad
+AF: CG: Democratic Republic of Congo
+AF: EG: Egypt
+AF: ET: Ethiopia
+AF: CM: Cameroon
+AF: IS: Israel
+AF: LY: Libya
+AF: MG: Madagascar
+AF: MO: Morocco
+AF: BW: Namibia
+AF: SA: Saudi Arabia
+AF: SO: Somalia
+AF: SD: Sudan
+AF: TZ: Tanzania
+AF: TN: Tunisia
+AF: ZM: Zambia
+AF: KE: Kenya
+AF: AO: Angola
+DE: BAW: Baden-Württemberg
+DE: BAY: Bavaria
+DE: BBB: Berlin
+DE: BBB: Brandenburg
+DE: HES: Hesse
+DE: MVP: Mecklenburg-Western Pomerania
+DE: NIB: Lower Saxony
+DE: NIB: Bremen
+DE: NRW: North Rhine-Westphalia
+DE: RPS: Rhineland-Palatinate
+DE: RPS: Saarland
+DE: SAC: Saxony
+DE: SAA: Saxony-Anhalt
+DE: SHH: Schleswig-Holstein
+DE: SHH: Hamburg
+DE: THU: Thuringia" | dmenu -r -i -l 50 -p "Select a radar to use as default:" | tr "[:lower:]" "[:upper:]")"
+
+# Ensure user did not escape.
+[ -z "$chosen" ] && exit 1
+
+# Set continent code and radar code.
+continentcode=${chosen%%:*}
+radarcode=${chosen#* } radarcode=${radarcode%:*}
+
+# Print codes to $radarloc file.
+ printf "%s,%s\\n" "$continentcode" "$radarcode" > "$radarloc" ;}
+
+getdoppler() {
+ cont=$(cut -c -2 "$radarloc")
+ loc=$(cut -c 4- "$radarloc")
+ notify-send "🌦️ Doppler RADAR" "Pulling most recent Doppler RADAR for $loc."
+ case "$cont" in
+ "US") curl -sL "https://radar.weather.gov/ridge/lite/${loc}_loop.gif" > "$doppler" ;;
+ "EU") curl -sL "https://api.sat24.com/animated/${loc}/rainTMC/2/" > "$doppler" ;;
+ "AF") curl -sL "https://api.sat24.com/animated/${loc}/rain/2/" > "$doppler" ;;
+ "DE") loc="$(echo "$loc" | tr "[:upper:]" "[:lower:]")"
+ curl -sL "https://www.dwd.de/DWD/wetter/radar/radfilm_${loc}_akt.gif" > "$doppler" ;;
+ esac
+}
+
+showdoppler() { setsid -f mpv --no-osc --loop=inf --no-terminal "$doppler" ;}
+
+case $BLOCK_BUTTON in
+ 1) [ ! -f "$radarloc" ] && pickloc && getdoppler
+ [ $(($(date '+%s') - $(stat -c %Y "$doppler"))) -gt "$secs" ] && getdoppler
+ showdoppler ;;
+ 2) pickloc && getdoppler && showdoppler ;;
+ 3) notify-send "🗺️ Doppler RADAR module" "\- Left click for local Doppler RADAR.
+- Middle click to update RADAR location.
+After $secs seconds, new clicks will also automatically update the doppler RADAR." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+echo 🗺️
diff --git a/dotfiles/system/.local/bin/statusbar/sb-forecast b/dotfiles/system/.local/bin/statusbar/sb-forecast
new file mode 100755
index 0000000..45584c5
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-forecast
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Displays todays precipication chance (☔) and daily low (🥶) and high (🌞).
+# Usually intended for the statusbar.
+
+# If we have internet, get a weather report from wttr.in and store it locally.
+# You could set up a shell alias to view the full file in a pager in the
+# terminal if desired. This function will only be run once a day when needed.
+weatherreport="${XDG_CACHE_HOME:-$HOME/.cache}/weatherreport"
+getforecast() { curl -sf "wttr.in/$LOCATION" > "$weatherreport" || exit 1 ;}
+
+# Some very particular and terse stream manipulation. We get the maximum
+# precipitation chance and the daily high and low from the downloaded file and
+# display them with coresponding emojis.
+showweather() { printf "%s" "$(sed '16q;d' "$weatherreport" |
+ grep -wo "[0-9]*%" | sort -rn | sed "s/^/☔/g;1q" | tr -d '\n')"
+sed '13q;d' "$weatherreport" | grep -o "m\\([-+]\\)*[0-9]\\+" | sed 's/+//g' | sort -n -t 'm' -k 2n | sed -e 1b -e '$!d' | tr '\n|m' ' ' | awk '{print " 🥶" $1 "°","🌞" $2 "°"}' ;}
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e less -Srf "$weatherreport" ;;
+ 2) getforecast && showweather ;;
+ 3) notify-send "🌈 Weather module" "\- Left click for full forecast.
+- Middle click to update forecast.
+☔: Chance of rain/snow
+🥶: Daily low
+🌞: Daily high" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# The test if our forcecast is updated to the day. If it isn't download a new
+# weather report from wttr.in with the above function.
+[ "$(stat -c %y "$weatherreport" 2>/dev/null | cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ] ||
+ getforecast
+
+showweather
diff --git a/dotfiles/system/.local/bin/statusbar/sb-help-icon b/dotfiles/system/.local/bin/statusbar/sb-help-icon
new file mode 100755
index 0000000..8fa4a52
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-help-icon
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# The clickable help menu. Middle click to restart wm.
+
+# If dwm is running, use dwm's readme and restart.
+pidof dwm >/dev/null &&
+ READMEFILE=/usr/local/share/dwm/larbs.mom
+ restartwm() { pkill -HUP dwm ;} ||
+ restartwm() { i3 restart ;}
+
+case $BLOCK_BUTTON in
+ 1) groff -mom "${READMEFILE:-${XDG_DATA_HOME:-$HOME/.local/share}/larbs/readme.mom}" -Tpdf | zathura - ;;
+ 2) restartwm ;;
+ 3) notify-send "❓ Help module" "\- Left click to open LARBS guide.
+- Middle click to refresh window manager." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac; echo "❓"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-internet b/dotfiles/system/.local/bin/statusbar/sb-internet
new file mode 100755
index 0000000..94b7da2
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-internet
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Show wifi 📶 and percent strength or 📡 if none.
+# Show 🌐 if connected to ethernet or ❎ if none.
+# Show 🔒 if a vpn connection is active
+
+case $BLOCK_BUTTON in
+ 1) "$TERMINAL" -e nmtui; pkill -RTMIN+4 dwmblocks ;;
+ 3) notify-send "🌐 Internet module" "\- Click to connect
+❌: wifi disabled
+📡: no wifi connection
+📶: wifi connection with quality
+❎: no ethernet
+🌐: ethernet working
+🔒: vpn is active
+" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+if grep -xq 'up' /sys/class/net/w*/operstate 2>/dev/null ; then
+ wifiicon="$(awk '/^\s*w/ { print "📶", int($3 * 100 / 70) "% " }' /proc/net/wireless)"
+elif grep -xq 'down' /sys/class/net/w*/operstate 2>/dev/null ; then
+ grep -xq '0x1003' /sys/class/net/w*/flags && wifiicon="📡 " || wifiicon="❌ "
+fi
+
+printf "%s%s%s\n" "$wifiicon" "$(sed "s/down/❎/;s/up/🌐/" /sys/class/net/e*/operstate 2>/dev/null)" "$(sed "s/.*/🔒/" /sys/class/net/tun*/operstate 2>/dev/null)"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-iplocate b/dotfiles/system/.local/bin/statusbar/sb-iplocate
new file mode 100755
index 0000000..02adab8
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-iplocate
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Gets your public ip address checks which country you are in and
+# displays that information in the statusbar
+#
+# https://www.maketecheasier.com/ip-address-geolocation-lookups-linux/
+
+ifinstalled "geoip" || exit
+addr="$(curl ifconfig.me 2>/dev/null)" || exit
+grep "flag: " "${XDG_DATA_HOME:-$HOME/.local/share}/larbs/emoji" | grep "$(geoiplookup "$addr" | sed 's/.*, //')" | sed "s/flag: //;s/;.*//"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-kbselect b/dotfiles/system/.local/bin/statusbar/sb-kbselect
new file mode 100755
index 0000000..f0c923f
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-kbselect
@@ -0,0 +1,16 @@
+#!/bin/sh
+# works on any init system
+# requirements: dmenu, xorg-setxkbmap
+kb="$(setxkbmap -query | grep -oP 'layout:\s*\K\w+')" || exit 1
+
+case $BLOCK_BUTTON in
+ 1) kb_choice="$(awk '/! layout/{flag=1; next} /! variant/{flag=0} flag {print $2, "- " $1}' /usr/share/X11/xkb/rules/base.lst | dmenu -l 15)"
+ kb="$(echo "$kb_choice" | awk '{print $3}')"
+ setxkbmap "$kb"
+ pkill -RTMIN+30 "${STATUSBAR:-dwmblocks}";;
+ 3) notify-send "⌨ Keyboard/language module" "$(printf "%s" "\- Current layout: $(setxkbmap -query | grep -oP 'layout:\s*\K\w+')")
+- Left click to change keyboard.";;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+echo "$kb"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-mailbox b/dotfiles/system/.local/bin/statusbar/sb-mailbox
new file mode 100755
index 0000000..2132184
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-mailbox
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Displays number of unread mail and an loading icon if updating.
+# When clicked, brings up `neomutt`.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e neomutt ;;
+ 2) setsid -f mw -Y >/dev/null ;;
+ 3) notify-send "📬 Mail module" "\- Shows unread mail
+- Shows 🔃 if syncing mail
+- Left click opens neomutt
+- Middle click syncs mail" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+unread="$(find "${XDG_DATA_HOME:-$HOME/.local/share}"/mail/*/[Ii][Nn][Bb][Oo][Xx]/new/* -type f | wc -l 2>/dev/null)"
+
+pidof mbsync >/dev/null 2>&1 && icon="🔃"
+
+[ "$unread" = "0" ] && [ "$icon" = "" ] || echo "📬$unread$icon"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-memory b/dotfiles/system/.local/bin/statusbar/sb-memory
new file mode 100755
index 0000000..01d3daf
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-memory
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+case $BLOCK_BUTTON in
+ 1) notify-send "🧠 Memory hogs" "$(ps axch -o cmd:15,%mem --sort=-%mem | head)" ;;
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🧠 Memory module" "\- Shows Memory Used/Total.
+- Click to show memory hogs.
+- Middle click to open htop." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+free --mebi | sed -n '2{p;q}' | awk '{printf ("🧠%2.2fGiB/%2.2fGiB\n", ( $3 / 1024), ($2 / 1024))}'
diff --git a/dotfiles/system/.local/bin/statusbar/sb-moonphase b/dotfiles/system/.local/bin/statusbar/sb-moonphase
new file mode 100755
index 0000000..fab8b4d
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-moonphase
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Shows the current moon phase.
+
+moonfile="${XDG_DATA_HOME:-$HOME/.local/share}/moonphase"
+
+[ "$(stat -c %y "$moonfile" 2>/dev/null | cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ] ||
+ { curl -sf "wttr.in/?format=%m" > "$moonfile" || exit 1 ;}
+
+icon="$(cat "$moonfile")"
+
+case "$icon" in
+ 🌑) name="New" ;;
+ 🌒) name="Waxing Crescent" ;;
+ 🌓) name="First Quarter" ;;
+ 🌔) name="Waxing Gibbous" ;;
+ 🌕) name="Full" ;;
+ 🌖) name="Waning Gibbous" ;;
+ 🌗) name="Last Quarter" ;;
+ 🌘) name="Waning Crescent" ;;
+ *) exit 1 ;;
+esac
+
+echo "${icon-?}"
+
+case $BLOCK_BUTTON in
+ 3) notify-send "🌜 Moon phase module" "Displays current moon phase.
+- 🌑: New
+- 🌒: Waxing Crescent
+- 🌓: First Quarter
+- 🌔: Waxing Gibbous
+- 🌕: Full
+- 🌖: Waning Gibbous
+- 🌗: Last Quarter
+- 🌘: Waning Crescent" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
diff --git a/dotfiles/system/.local/bin/statusbar/sb-mpdup b/dotfiles/system/.local/bin/statusbar/sb-mpdup
new file mode 100755
index 0000000..af81a7d
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-mpdup
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# This loop will update the mpd statusbar module whenever a command changes the
+# music player's status. mpd must be running on X's start for this to work.
+
+while : ; do
+ mpc idle >/dev/null && kill -45 "$(pidof "${STATUSBAR:-dwmblocks}")" || break
+done
diff --git a/dotfiles/system/.local/bin/statusbar/sb-music b/dotfiles/system/.local/bin/statusbar/sb-music
new file mode 100755
index 0000000..7ea7032
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-music
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+filter() { mpc | sed "/^volume:/d;s/\\&/&amp;/g;s/\\[paused\\].*/⏸/g;/\\[playing\\].*/d;/^ERROR/Q" | paste -sd ' ' -;}
+
+pidof -x sb-mpdup >/dev/null 2>&1 || sb-mpdup >/dev/null 2>&1 &
+
+case $BLOCK_BUTTON in
+ 1) mpc status | filter ; setsid -f "$TERMINAL" -e ncmpcpp ;; # right click, pause/unpause
+ 2) mpc toggle | filter ;; # right click, pause/unpause
+ 3) mpc status | filter ; notify-send "🎵 Music module" "\- Shows mpd song playing.
+- ⏸ when paused.
+- Left click opens ncmpcpp.
+- Middle click pauses.
+- Scroll changes track.";; # right click, pause/unpause
+ 4) mpc prev | filter ;; # scroll up, previous
+ 5) mpc next | filter ;; # scroll down, next
+ 6) mpc status | filter ; "$TERMINAL" -e "$EDITOR" "$0" ;;
+ *) mpc status | filter ;;
+esac
diff --git a/dotfiles/system/.local/bin/statusbar/sb-nettraf b/dotfiles/system/.local/bin/statusbar/sb-nettraf
new file mode 100755
index 0000000..178f677
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-nettraf
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Module showing network traffic. Shows how much data has been received (RX) or
+# transmitted (TX) since the previous time this script ran. So if run every
+# second, gives network traffic per second.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e bmon ;;
+ 3) notify-send "🌐 Network traffic module" "🔻: Traffic received
+🔺: Traffic transmitted" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+update() {
+ sum=0
+ for arg; do
+ read -r i < "$arg"
+ sum=$(( sum + i ))
+ done
+ cache=/tmp/${1##*/}
+ [ -f "$cache" ] && read -r old < "$cache" || old=0
+ printf %d\\n "$sum" > "$cache"
+ printf %d\\n $(( sum - old ))
+}
+
+rx=$(update /sys/class/net/[ew]*/statistics/rx_bytes)
+tx=$(update /sys/class/net/[ew]*/statistics/tx_bytes)
+
+printf "🔻%4sB 🔺%4sB\\n" $(numfmt --to=iec $rx $tx)
diff --git a/dotfiles/system/.local/bin/statusbar/sb-news b/dotfiles/system/.local/bin/statusbar/sb-news
new file mode 100755
index 0000000..fe701db
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-news
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Displays number of unread news items and an loading icon if updating.
+# When clicked, brings up `newsboat`.
+
+case $BLOCK_BUTTON in
+ 1) setsid "$TERMINAL" -e newsboat ;;
+ 2) setsid -f newsup >/dev/null exit ;;
+ 3) notify-send "📰 News module" "\- Shows unread news items
+- Shows 🔃 if updating with \`newsup\`
+- Left click opens newsboat
+- Middle click syncs RSS feeds
+<b>Note:</b> Only one instance of newsboat (including updates) may be running at a time." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+ cat /tmp/newsupdate 2>/dev/null || echo "$(newsboat -x print-unread | awk '{ if($1>0) print "📰" $1}')$(cat "${XDG_CONFIG_HOME:-$HOME/.config}"/newsboat/.update 2>/dev/null)"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-pacpackages b/dotfiles/system/.local/bin/statusbar/sb-pacpackages
new file mode 100755
index 0000000..37ebed3
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-pacpackages
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Displays number of upgradeable packages.
+# For this to work, have a `pacman -Sy` command run in the background as a
+# cronjob every so often as root. This script will then read those packages.
+# When clicked, it will run an upgrade via pacman.
+#
+# Add the following text as a file in /usr/share/libalpm/hooks/statusbar.hook:
+#
+# [Trigger]
+# Operation = Upgrade
+# Type = Package
+# Target = *
+#
+# [Action]
+# Description = Updating statusbar...
+# When = PostTransaction
+# Exec = /usr/bin/pkill -RTMIN+8 dwmblocks # Or i3blocks if using i3.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e sb-popupgrade ;;
+ 2) notify-send "$(/usr/bin/pacman -Qu)" ;;
+ 3) notify-send "🎁 Upgrade module" "📦: number of upgradable packages
+- Left click to upgrade packages
+- Middle click to show upgradable packages" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+pacman -Qu | grep -Fcv "[ignored]" | sed "s/^/📦/;s/^📦0$//g"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-popupgrade b/dotfiles/system/.local/bin/statusbar/sb-popupgrade
new file mode 100755
index 0000000..29d6230
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-popupgrade
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+printf "Beginning upgrade.\\n"
+
+yay -Syu
+pkill -RTMIN+8 "${STATUSBAR:-dwmblocks}"
+
+printf "\\nUpgrade complete.\\nPress <Enter> to exit window.\\n\\n"
+read -r _
diff --git a/dotfiles/system/.local/bin/statusbar/sb-price b/dotfiles/system/.local/bin/statusbar/sb-price
new file mode 100755
index 0000000..42c84c1
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-price
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Usage:
+# price <url> <Name of currency> <icon> <Price to show in>
+# price bat "Basic Attention Token" 🦁
+# When the name of the currency is multi-word, put it in quotes.
+
+[ -z "$3" ] && exit 1
+
+# use $4 as currency, if not passed in use "usd" as default
+currency="${4:-usd}"
+interval="@14d" # History contained in chart preceded by '@' (7d = 7 days)
+dir="${XDG_DATA_HOME:-$HOME/.local/share}/crypto-prices"
+pricefile="$dir/$1-$currency"
+chartfile="$dir/$1-$currency-chart"
+
+updateprice() { temp="$(mktemp)"
+ curl -s "$currency.rate.sx/1$1" > "$temp" &&
+ mv -f "$temp" "$pricefile" &&
+ curl -s "$currency.rate.sx/$1$interval" > "$temp" &&
+ mv -f "$temp" "$chartfile" ;}
+
+[ -d "$dir" ] || mkdir -p "$dir"
+
+[ "$(stat -c %x "$pricefile" 2>/dev/null | cut -d' ' -f1)" != "$(date '+%Y-%m-%d')" ] &&
+ updateprice "$1"
+
+case $BLOCK_BUTTON in
+ 1) setsid "$TERMINAL" -e less -Srf "$chartfile" ;;
+ 2) notify-send -u low "$3 Updating..." "Updating $2 price..."
+ updateprice "$1" && notify-send "$3 Update complete." "$2 price is now
+\$$(cat "$pricefile")" ;;
+ 3) uptime="$(date -d "$(stat -c %x "$pricefile")" '+%D at %T' | sed "s|$(date '+%D')|Today|")"
+ notify-send "$3 $2 module" "\- <b>Exact price: \$$(cat "$pricefile")</b>
+- Left click for chart of changes.
+- Middle click to update.
+- Shows 🔃 if updating prices.
+- <b>Last updated:
+ $uptime</b>" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+case "$currency" in
+ usd) symb="$" ;;
+ gbp) symb="£" ;;
+ eur) symb="€" ;;
+ btc) symb="₿" ;;
+esac
+
+printf "$3$symb%0.2f$after" "$(cat "$pricefile")"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-tasks b/dotfiles/system/.local/bin/statusbar/sb-tasks
new file mode 100755
index 0000000..586300e
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-tasks
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Originally by Andr3as07 <https://github.com/Andr3as07>
+# Some changes by Luke
+# Rebuild by Tenyun
+
+# This block displays the number running background tasks. Requires tsp.
+
+num=$(tsp -l | awk -v numr=0 -v numq=0 '{if (/running/)numr++; if (/queued/)numq++} END{print numr+numq"("numq")"}')
+
+# Handle mouse clicks
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e tsp -l ;;
+ 3) notify-send "Tasks module" "🤖: number of running/queued background tasks
+- Left click opens tsp" ;; # Right click
+ 2) $EDITOR "$0" ;; # Middle click
+esac
+
+[ "$num" != "0(0)" ] &&
+ echo "🤖$num"
diff --git a/dotfiles/system/.local/bin/statusbar/sb-torrent b/dotfiles/system/.local/bin/statusbar/sb-torrent
new file mode 100755
index 0000000..6527005
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-torrent
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+transmission-remote -l | grep % |
+ sed " # The letters are for sorting and will not appear.
+ s/.*Stopped.*/A 🛑/;
+ s/.*Seeding.*/Z 🌱/;
+ s/.*100%.*/N ✅/;
+ s/.*Idle.*/B 🕰️/;
+ s/.*Uploading.*/L ⬆️/;
+ s/.*%.*/M ⬇️/" |
+ sort -h | uniq -c | awk '{print $3 $1}' | paste -sd ' ' -
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e tremc ;;
+ 2) td-toggle ;;
+ 3) notify-send "🌱 Torrent module" "\- Left click to open tremc.
+- Middle click to toggle transmission.
+- Shift click to edit script.
+Module shows number of torrents:
+🛑: paused
+🕰: idle (seeds needed)
+🔼: uploading (unfinished)
+🔽: downloading
+✅: done
+🌱: done and seeding" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
diff --git a/dotfiles/system/.local/bin/statusbar/sb-volume b/dotfiles/system/.local/bin/statusbar/sb-volume
new file mode 100755
index 0000000..3cfdc45
--- /dev/null
+++ b/dotfiles/system/.local/bin/statusbar/sb-volume
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Prints the current volume or 🔇 if muted.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e pulsemixer ;;
+ 2) pamixer -t ;;
+ 4) pamixer --allow-boost -i 1 ;;
+ 5) pamixer --allow-boost -d 1 ;;
+ 3) notify-send "📢 Volume module" "\- Shows volume 🔊, 🔇 if muted.
+- Middle click to mute.
+- Scroll to change." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+[ $(pamixer --get-mute) = true ] && echo 🔇 && exit
+
+vol="$(pamixer --get-volume)"
+
+if [ "$vol" -gt "70" ]; then
+ icon="🔊"
+elif [ "$vol" -gt "30" ]; then
+ icon="🔉"
+elif [ "$vol" -gt "0" ]; then
+ icon="🔈"
+else
+ echo 🔇 && exit
+fi
+
+echo "$icon$vol%"
diff --git a/dotfiles/system/.local/bin/steam b/dotfiles/system/.local/bin/steam
new file mode 100755
index 0000000..3d30238
--- /dev/null
+++ b/dotfiles/system/.local/bin/steam
@@ -0,0 +1,2 @@
+#!/bin/sh
+flatpak run com.valvesoftware.Steam >> "$HOME/.local/var/logs/steam.log" 2>&1
diff --git a/dotfiles/system/.local/bin/sudo-update-grub b/dotfiles/system/.local/bin/sudo-update-grub
new file mode 100755
index 0000000..5d67823
--- /dev/null
+++ b/dotfiles/system/.local/bin/sudo-update-grub
@@ -0,0 +1 @@
+sudo grub-mkconfig -o /boot/grub/grub.cfg
diff --git a/dotfiles/system/.local/bin/sysupdate b/dotfiles/system/.local/bin/sysupdate
new file mode 100755
index 0000000..357348d
--- /dev/null
+++ b/dotfiles/system/.local/bin/sysupdate
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Craig Jennings <c@cjennings.net>
+
+
+yay -Syu --noconfirm \ No newline at end of file
diff --git a/dotfiles/system/.local/bin/td-toggle b/dotfiles/system/.local/bin/td-toggle
new file mode 100755
index 0000000..de1a0e6
--- /dev/null
+++ b/dotfiles/system/.local/bin/td-toggle
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# If transmission-daemon is running, will ask to kill, else will ask to start.
+
+if pidof transmission-daemon >/dev/null ;
+then
+ [ "$(printf "No\\nYes" | dmenu -i -p "Turn off transmission-daemon?")" = "Yes" ] && killall transmission-daemon && notify-send "transmission-daemon disabled."
+else
+ ifinstalled transmission-cli || exit
+ [ "$(printf "No\\nYes" | dmenu -i -p "Turn on transmission daemon?")" = "Yes" ] && transmission-daemon && notify-send "transmission-daemon enabled."
+fi
+sleep 3 && pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}"
diff --git a/dotfiles/system/.local/bin/timezone-change b/dotfiles/system/.local/bin/timezone-change
new file mode 100755
index 0000000..c5a4e5a
--- /dev/null
+++ b/dotfiles/system/.local/bin/timezone-change
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+# Craig Jennings <c@cjennings.net>
+
+# Convenience script since I can't ever remember the two part TZ identifier to
+# change timezones.
+
+case $1 in
+ "eastern"|"ny"|"nyc"|"boston"|"dc")
+ sudo timedatectl set-timezone "US/Eastern"
+ ;;
+ "central"|"nola"|"home"|"chicago")
+ sudo timedatectl set-timezone "US/Central"
+ ;;
+ "mountain")
+ sudo timedatectl set-timezone "US/Mountain"
+ ;;
+ "pacific"|"sf"|"oakland"|"berkeley"|"hb"|"california")
+ sudo timedatectl set-timezone "US/Pacific"
+ ;;
+ "london"|"england"|"britain"|"gb")
+ sudo timedatectl set-timezone "Europe/London"
+ ;;
+ "hawaii")
+ sudo timedatectl set-timezone "US/Hawaii"
+ ;;
+ "armenia"|"yerevan")
+ sudo timedatectl set-timezone "Asia/Yerevan"
+ ;;
+ "greece"|"athens")
+ sudo timedatectl set-timezone "Europe/Athens"
+ ;;
+ "germany"|"berlin")
+ sudo timedatectl set-timezone "Europe/Berlin"
+ ;;
+ "turkey"|"istanbul")
+ sudo timedatectl set-timezone "Europe/Istanbul"
+ ;;
+ "portugal"|"lisbon")
+ sudo timedatectl set-timezone "Europe/Portugal"
+ ;;
+ "spain"|"madrid")
+ sudo timedatectl set-timezone "Europe/Madrid"
+ ;;
+ "france"|"paris")
+ sudo timedatectl set-timezone "Europe/Paris"
+ ;;
+ "italy"|"rome"|"naples"|"ischia")
+ sudo timedatectl set-timezone "Europe/Rome"
+ ;;
+ "austria"|"vienna")
+ sudo timedatectl set-timezone "Europe/Vienna"
+ ;;
+ "japan"|"tokyo")
+ sudo timedatectl set-timezone "Asia/Tokyo"
+ ;;
+ "jamaica")
+ sudo timedatectl set-timezone "America/Jamaica"
+ ;;
+ "st_lucia"|"grenadines"|"st_vincent"|"nevis"|"st_kitts"|"puerto_rico")
+ sudo timedatectl set-timezone "America/Puerto_Rico"
+ ;;
+ *)
+ echo
+ "Invalid option chosen."
+ echo
+ "Some valid options are: eastern, central, pacific, rome, london, st_lucia, italy, france, spain ."
+ ;;
+esac
diff --git a/dotfiles/system/.local/bin/timezone-set b/dotfiles/system/.local/bin/timezone-set
new file mode 100755
index 0000000..8f48729
--- /dev/null
+++ b/dotfiles/system/.local/bin/timezone-set
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Craig Jennings <c@cjennings.net>
+
+# sets timezone based on the ip-address when there's network connectivity
+
+# Check network status
+if ping -q -c 1 -W 1 google.com >/dev/null; then
+ NEW_TIMEZONE="$(curl --fail --silent https://ipapi.co/timezone)"
+ if sudo timedatectl set-timezone "$NEW_TIMEZONE"; then
+ notify-send "Setting timezone to $NEW_TIMEZONE successul."
+ else
+ notify-send "Attempt to set timezone failed."
+ fi
+else
+ notify-send "No network connection detected. Cannot set timezone automatically."
+fi
+dwmstatus
diff --git a/dotfiles/system/.local/bin/toggle-touchpad b/dotfiles/system/.local/bin/toggle-touchpad
new file mode 100755
index 0000000..9dde99b
--- /dev/null
+++ b/dotfiles/system/.local/bin/toggle-touchpad
@@ -0,0 +1,16 @@
+#!/bin/sh
+# Toggle touchpad status
+# Using libinput and xinput
+
+# Use xinput list and do a search for touchpads. Then get the first one and get its name.
+device="$(xinput list | grep -P '(?<= )[\w\s:]*(?i)(touchpad|synaptics)(?-i).*?(?=\s*id)' -o | head -n1)"
+
+# If it was activated disable it and if it wasn't disable it
+if [[ "$(xinput list-props "$device" | grep -P ".*Device Enabled.*\K.(?=$)" -o)" == "1" ]]
+then
+ xinput disable "$device"
+ notify-send "Touchpad" "Touchpad disabled"
+else
+ xinput enable "$device"
+ notify-send "Touchpad" "Touchpad enabled"
+fi
diff --git a/dotfiles/system/.local/bin/torwrap b/dotfiles/system/.local/bin/torwrap
new file mode 100755
index 0000000..8b20ad4
--- /dev/null
+++ b/dotfiles/system/.local/bin/torwrap
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+ifinstalled tremc transmission-cli || exit
+
+! pidof transmission-daemon >/dev/null && transmission-daemon && notify-send "Starting torrent daemon..."
+
+$TERMINAL -e tremc; pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}"
diff --git a/dotfiles/system/.local/bin/touchpad-app b/dotfiles/system/.local/bin/touchpad-app
new file mode 100755
index 0000000..6310c6d
--- /dev/null
+++ b/dotfiles/system/.local/bin/touchpad-app
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+/usr/bin/touchpad-indicator & \ No newline at end of file
diff --git a/dotfiles/system/.local/bin/transadd b/dotfiles/system/.local/bin/transadd
new file mode 100755
index 0000000..a598fad
--- /dev/null
+++ b/dotfiles/system/.local/bin/transadd
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Mimeapp script for adding torrent to transmission-daemon, but will also start the daemon first if not running.
+
+# transmission-daemon sometimes fails to take remote requests in its first moments, hence the sleep.
+
+pidof transmission-daemon >/dev/null || (transmission-daemon && notify-send "Starting transmission daemon..." && sleep 3 && pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}")
+
+transmission-remote -a "$@" && notify-send "🔽 Torrent added."
diff --git a/dotfiles/system/.local/bin/update-backup-repositories b/dotfiles/system/.local/bin/update-backup-repositories
new file mode 100755
index 0000000..a91b438
--- /dev/null
+++ b/dotfiles/system/.local/bin/update-backup-repositories
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Craig Jennings <c@cjennings.net>
+# updates or clones repositories for backup
+
+REPOS_HOME="/media/backup/repositories/"
+
+# Create REPOS_HOME dir if not exists
+if [ ! -d "$REPOS_HOME" ]; then
+ mkdir -p "$REPOS_HOME"
+fi
+
+# Make sure REPOS_HOME dir is writable
+if [ ! -w "$REPOS_HOME" ]; then
+ echo "Directory $REPOS_HOME is not writable."
+ exit 1
+fi
+
+# Make sure git is available
+if ! command -v git >/dev/null 2>&1; then
+ echo "Git command does not exist. Please install git."
+ exit 1
+fi
+
+cd "$REPOS_HOME"
+
+repos="
+git@cjennings.net:archsetup.git
+git@cjennings.net:dmenu.git
+git@cjennings.net:dotemacs.git
+git@cjennings.net:dotfiles.git
+git@cjennings.net:dwm.git
+git@cjennings.net:pinentry-dmenu.git
+git@cjennings.net:rsyncshot.git
+git@cjennings.net:st.git
+git@github.com:cjennings/emacs-wttrin.git
+https://github.com/d12frosted/elpa-mirror.git
+https://github.com/mirrors/emacs.git
+"
+
+for repo in $repos; do
+ dir=$(echo "$repo" | awk -F'[/:]' '{gsub(/.git/, "", $NF); print $NF}')
+ # Note on the above awk command:
+ # awk -F'[/:]': uses awk with a regex field delimiter that matches both : and /
+ # which will work with both ssh and http style URLs.
+ # '{gsub(/.git/, "", $NF); print $NF}: This removes the ".git" postfixes from the last field ($NF)
+ # which leaves only the repo name.
+
+ fullpath="$REPOS_HOME$dir"
+ if [ -d "$fullpath" ]; then
+ echo "Repository $dir exists at $fullpath, pulling..."
+ (cd "$fullpath" && git pull)
+ else
+ echo "Repository $dir doesn't exist at $fullpath, cloning..."
+ cd "$REPOS_HOME" && git clone --depth 1 "$repo" "$fullpath"
+ fi
+done
diff --git a/dotfiles/system/.local/bin/updatemirrors b/dotfiles/system/.local/bin/updatemirrors
new file mode 100755
index 0000000..3ba4f7f
--- /dev/null
+++ b/dotfiles/system/.local/bin/updatemirrors
@@ -0,0 +1,20 @@
+#!/bin/sh
+# cjennings generates arch linux mirror list
+echo "Updating mirrorlist. Please be patient. This may take a few minutes...."
+echo " "
+
+sudo reflector \
+ --connection-timeout 3 \
+ --download-timeout 3 \
+ --protocol https \
+ --country US \
+ --age 18 \
+ --latest 20 \
+ --score 10 \
+ --fastest 5 \
+ --sort score \
+ --save /etc/pacman.d/mirrorlist > /dev/null 2>&1
+
+cat /etc/pacman.d/mirrorlist
+echo " "
+echo "Done."
diff --git a/dotfiles/system/.local/bin/virtstart b/dotfiles/system/.local/bin/virtstart
new file mode 100755
index 0000000..f9a326f
--- /dev/null
+++ b/dotfiles/system/.local/bin/virtstart
@@ -0,0 +1,8 @@
+#!/bin/bash
+# launch a virtual machine in fullscreen.
+# the argument is the machine name
+
+export LIBVIRT_DEFAULT_URI="qemu:///system"
+
+/usr/bin/virsh start $1
+/usr/bin/virt-viewer -f -w -a $1
diff --git a/dotfiles/system/.local/bin/wallsearch b/dotfiles/system/.local/bin/wallsearch
new file mode 100755
index 0000000..f71d150
--- /dev/null
+++ b/dotfiles/system/.local/bin/wallsearch
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+walldir="$HOME/Pictures/wallpaper/incoming"
+tmpdir="$HOME/.wallsearch"
+maxpage=5
+tagoptions="CANCEL\n#minimalism\n#digital art\n#4K\n#nature\n#abstract\n#landscape\n#cityscape\n#surf\n#technology"
+sortoptions="CANCEL\ndate_added\nrelevance\nrandom\nfavorites\ntoplist"
+
+if [ -d $tmpdir ]; then
+ rm -rf $tmpdir
+fi
+mkdir -p $tmpdir
+
+if [ -z $1 ]; then
+ query=$(echo -e $tagoptions | dmenu -p "Search Wallhaven: " -i)
+else
+ query=$1
+fi
+
+[ $query == "CANCEL" ] && notify-send "Cancelled wallpaper search." && exit 0;
+
+sorting=$(echo -e $sortoptions | dmenu -p "Sort Order: " -i)
+
+[ $sorting == "CANCEL" ] && notify-send "Cancelled wallpaper search." && exit 0;
+
+query="$(sed 's/#//g' <<<$query)"
+query="$(sed 's/ /+/g' <<<$query)"
+echo #query
+
+notify-send "wallsearch" "Searching wallpapers..."
+
+for i in $(seq 1 10);
+do
+ curl -s https://wallhaven.cc/api/v1/search\?atleast\=1920x1080\&sorting\=$sorting\&q\=$query\&purity=111\&page\=$i > tmp.txt
+ page=$(cat tmp.txt | jq '.' | grep -Eoh "https:\/\/w\.wallhaven.cc\/full\/.*(jpg|png)\b")
+ wget -nc -P $tmpdir $page
+ notify-send "wallsearch" "Searching wallpapers..."
+done
+
+rm tmp.txt
+notify-send "wallsearch" "Done searching wallpaper."
+sxiv -to $tmpdir/* | xargs -I % mv % $walldir
+#rm -rf $tmpdir
diff --git a/dotfiles/system/.local/bin/ytp b/dotfiles/system/.local/bin/ytp
new file mode 100755
index 0000000..93ca9fc
--- /dev/null
+++ b/dotfiles/system/.local/bin/ytp
@@ -0,0 +1 @@
+yt-dlp --ignore-config --yes-playlist --add-metadata -i -o '%(channel)s-%(playlist_title)s-%(playlist_index)s-%(title)s.%(ext)s' $1 $2 $3 $4
diff --git a/dotfiles/system/.local/share/applications/dwm.desktop b/dotfiles/system/.local/share/applications/dwm.desktop
new file mode 100644
index 0000000..ba3bd00
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/dwm.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=dwm
+Comment=It's fucking DWM, asshole.
+Exec=startdwm
+Icon=dwm
+Type=XSession \ No newline at end of file
diff --git a/dotfiles/system/.local/share/applications/emacsclient-mail.desktop b/dotfiles/system/.local/share/applications/emacsclient-mail.desktop
new file mode 100644
index 0000000..6efcf61
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/emacsclient-mail.desktop
@@ -0,0 +1,20 @@
+[Desktop Entry]
+Categories=Network;Email;
+Comment=Emacs is my mail client
+Exec=sh -c "exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\\\(message-mailto\\\\ \\\\\\"%u\\\\\\"\\\\)"
+Icon=emacs
+Name=Emacs (Mail, Client)
+MimeType=x-scheme-handler/mailto;
+NoDisplay=true
+Terminal=false
+Type=Application
+Keywords=emacsclient;
+Actions=new-window;new-instance;
+
+[Desktop Action new-window]
+Name=New Window
+Exec=/usr/bin/emacsclient --alternate-editor= --create-frame --eval "(message-mailto \\"%u\\")"
+
+[Desktop Action new-instance]
+Name=New Instance
+Exec=emacs -f message-mailto %u
diff --git a/dotfiles/system/.local/share/applications/file.desktop b/dotfiles/system/.local/share/applications/file.desktop
new file mode 100644
index 0000000..5df1633
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/file.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=File Manager
+Exec=/usr/local/bin/st -e lfub %u
diff --git a/dotfiles/system/.local/share/applications/img.desktop b/dotfiles/system/.local/share/applications/img.desktop
new file mode 100644
index 0000000..42aa81e
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/img.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=Image viewer
+Exec=/usr/bin/sxiv -a %f
diff --git a/dotfiles/system/.local/share/applications/mail.desktop b/dotfiles/system/.local/share/applications/mail.desktop
new file mode 100644
index 0000000..d24aea2
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/mail.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=Mail
+Exec=/usr/local/bin/st -e neomutt %u
diff --git a/dotfiles/system/.local/share/applications/mimeapps.list b/dotfiles/system/.local/share/applications/mimeapps.list
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/mimeapps.list
diff --git a/dotfiles/system/.local/share/applications/org-protocol.desktop b/dotfiles/system/.local/share/applications/org-protocol.desktop
new file mode 100644
index 0000000..acdb8ad
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/org-protocol.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Name=org-protocol
+Comment=Intercept calls from emacsclient to trigger custom actions
+Categories=Other;
+Keywords=org-protocol;
+Icon=emacs
+Type=Application
+Exec=emacsclient -- %u
+Terminal=false
+StartupWMClass=Emacs
+MimeType=x-scheme-handler/org-protocol;
diff --git a/dotfiles/system/.local/share/applications/pdf.desktop b/dotfiles/system/.local/share/applications/pdf.desktop
new file mode 100644
index 0000000..8c38677
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/pdf.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=PDF reader
+Exec=/usr/bin/zathura %u
diff --git a/dotfiles/system/.local/share/applications/text.desktop b/dotfiles/system/.local/share/applications/text.desktop
new file mode 100644
index 0000000..41ee05f
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/text.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=Text editor
+Exec=/usr/local/bin/st -e nvim %u
diff --git a/dotfiles/system/.local/share/applications/torrent.desktop b/dotfiles/system/.local/share/applications/torrent.desktop
new file mode 100644
index 0000000..f6d28d9
--- /dev/null
+++ b/dotfiles/system/.local/share/applications/torrent.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=Torrent
+Exec=/usr/bin/env transadd %U
diff --git a/dotfiles/system/.local/share/audacious/Skins/2a03.wsz b/dotfiles/system/.local/share/audacious/Skins/2a03.wsz
new file mode 100644
index 0000000..551a492
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/2a03.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Adidas2-3.zip b/dotfiles/system/.local/share/audacious/Skins/Adidas2-3.zip
new file mode 100644
index 0000000..4d7bb1a
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Adidas2-3.zip
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Blac.wsz b/dotfiles/system/.local/share/audacious/Skins/Blac.wsz
new file mode 100644
index 0000000..8585b33
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Blac.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Classic_70's_Marshall_Stack.wsz b/dotfiles/system/.local/share/audacious/Skins/Classic_70's_Marshall_Stack.wsz
new file mode 100644
index 0000000..23b0f11
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Classic_70's_Marshall_Stack.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Digital_Stereo_73.wsz b/dotfiles/system/.local/share/audacious/Skins/Digital_Stereo_73.wsz
new file mode 100644
index 0000000..b497025
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Digital_Stereo_73.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Expensive_HI_FI_Sony_2005.wsz b/dotfiles/system/.local/share/audacious/Skins/Expensive_HI_FI_Sony_2005.wsz
new file mode 100644
index 0000000..1d9a40b
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Expensive_HI_FI_Sony_2005.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Future_Audio_1.wsz b/dotfiles/system/.local/share/audacious/Skins/Future_Audio_1.wsz
new file mode 100644
index 0000000..7bc48e7
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Future_Audio_1.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Modern_Stereo_Amp_2.wsz b/dotfiles/system/.local/share/audacious/Skins/Modern_Stereo_Amp_2.wsz
new file mode 100644
index 0000000..f89bc9c
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Modern_Stereo_Amp_2.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Modern_Style_Marshall_Stack.wsz b/dotfiles/system/.local/share/audacious/Skins/Modern_Style_Marshall_Stack.wsz
new file mode 100644
index 0000000..dc5135c
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Modern_Style_Marshall_Stack.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Nucleo_NLog_v102_.wsz b/dotfiles/system/.local/share/audacious/Skins/Nucleo_NLog_v102_.wsz
new file mode 100644
index 0000000..19de9af
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Nucleo_NLog_v102_.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/PioneerAmp.wsz b/dotfiles/system/.local/share/audacious/Skins/PioneerAmp.wsz
new file mode 100644
index 0000000..b1fbde1
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/PioneerAmp.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/RAZORIX 50 % Uriel - 50% Kript.wsz b/dotfiles/system/.local/share/audacious/Skins/RAZORIX 50 % Uriel - 50% Kript.wsz
new file mode 100644
index 0000000..6ab3c8f
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/RAZORIX 50 % Uriel - 50% Kript.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/SONY3.WSZ b/dotfiles/system/.local/share/audacious/Skins/SONY3.WSZ
new file mode 100644
index 0000000..8d6871d
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/SONY3.WSZ
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Sony MD.wsz b/dotfiles/system/.local/share/audacious/Skins/Sony MD.wsz
new file mode 100644
index 0000000..3b08b42
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Sony MD.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Spy Amp.zip b/dotfiles/system/.local/share/audacious/Skins/Spy Amp.zip
new file mode 100644
index 0000000..b06da94
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Spy Amp.zip
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Heaven.wsz b/dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Heaven.wsz
new file mode 100644
index 0000000..bb01842
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Heaven.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Zeus.wsz b/dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Zeus.wsz
new file mode 100644
index 0000000..d6a759e
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/SpyAMP Pro Zeus.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/SpyAMP_professional_edition_mV1.wsz b/dotfiles/system/.local/share/audacious/Skins/SpyAMP_professional_edition_mV1.wsz
new file mode 100644
index 0000000..c3a4a26
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/SpyAMP_professional_edition_mV1.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/SpyAmp-Pro-Heaven.wsz b/dotfiles/system/.local/share/audacious/Skins/SpyAmp-Pro-Heaven.wsz
new file mode 100644
index 0000000..8c43f82
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/SpyAmp-Pro-Heaven.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Steel_Stereo.wsz b/dotfiles/system/.local/share/audacious/Skins/Steel_Stereo.wsz
new file mode 100644
index 0000000..e3646b0
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Steel_Stereo.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/Technoia_ver001.wsz b/dotfiles/system/.local/share/audacious/Skins/Technoia_ver001.wsz
new file mode 100644
index 0000000..fc4a0f6
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/Technoia_ver001.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/base-2.91.wsz b/dotfiles/system/.local/share/audacious/Skins/base-2.91.wsz
new file mode 100644
index 0000000..d1e0a67
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/base-2.91.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/deviantamp.zip b/dotfiles/system/.local/share/audacious/Skins/deviantamp.zip
new file mode 100644
index 0000000..35d5964
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/deviantamp.zip
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/iWinamp_V1.wsz b/dotfiles/system/.local/share/audacious/Skins/iWinamp_V1.wsz
new file mode 100644
index 0000000..b3e11aa
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/iWinamp_V1.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/nadamp.zip b/dotfiles/system/.local/share/audacious/Skins/nadamp.zip
new file mode 100644
index 0000000..9e6d5f9
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/nadamp.zip
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/s_Pioneer.wsz b/dotfiles/system/.local/share/audacious/Skins/s_Pioneer.wsz
new file mode 100644
index 0000000..3df6471
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/s_Pioneer.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/satellite.wsz b/dotfiles/system/.local/share/audacious/Skins/satellite.wsz
new file mode 100644
index 0000000..9aaa1e1
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/satellite.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/sonympfx3lcdv111.wsz b/dotfiles/system/.local/share/audacious/Skins/sonympfx3lcdv111.wsz
new file mode 100644
index 0000000..cd60ddf
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/sonympfx3lcdv111.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/spyamp.zip b/dotfiles/system/.local/share/audacious/Skins/spyamp.zip
new file mode 100644
index 0000000..125aedf
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/spyamp.zip
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/spyamp_sepia.wsz b/dotfiles/system/.local/share/audacious/Skins/spyamp_sepia.wsz
new file mode 100644
index 0000000..000d71e
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/spyamp_sepia.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/spyampy2k.wsz b/dotfiles/system/.local/share/audacious/Skins/spyampy2k.wsz
new file mode 100644
index 0000000..ed40599
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/spyampy2k.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/spyampy2k3.wsz b/dotfiles/system/.local/share/audacious/Skins/spyampy2k3.wsz
new file mode 100644
index 0000000..1849707
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/spyampy2k3.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/audacious/Skins/v2_technics_white_resting_by_johnnyg0.wsz b/dotfiles/system/.local/share/audacious/Skins/v2_technics_white_resting_by_johnnyg0.wsz
new file mode 100644
index 0000000..db5443a
--- /dev/null
+++ b/dotfiles/system/.local/share/audacious/Skins/v2_technics_white_resting_by_johnnyg0.wsz
Binary files differ
diff --git a/dotfiles/system/.local/share/emoji b/dotfiles/system/.local/share/emoji
new file mode 100644
index 0000000..2925c82
--- /dev/null
+++ b/dotfiles/system/.local/share/emoji
@@ -0,0 +1,1593 @@
+😀 grinning face; 1F600;
+😃 grinning face with big eyes; 1F603;
+😄 grinning face with smiling eyes; 1F604;
+😁 beaming face with smiling eyes; 1F601;
+😆 grinning squinting face; 1F606;
+😅 grinning face with sweat; 1F605;
+🤣 rolling on the floor laughing; 1F923;
+😂 face with tears of joy; 1F602;
+🙂 slightly smiling face; 1F642;
+🙃 upside-down face; 1F643;
+😉 winking face; 1F609;
+😊 smiling face with smiling eyes; 1F60A;
+😇 smiling face with halo; 1F607;
+🥰 smiling face with hearts; 1F970;
+😍 smiling face with heart-eyes; 1F60D;
+🤩 star-struck; 1F929;
+😘 face blowing a kiss; 1F618;
+😗 kissing face; 1F617;
+☺️ smiling face; 263A FE0F;
+😚 kissing face with closed eyes; 1F61A;
+😙 kissing face with smiling eyes; 1F619;
+🥲 smiling face with tear; 1F972;
+😋 face savoring food; 1F60B;
+😛 face with tongue; 1F61B;
+😜 winking face with tongue; 1F61C;
+🤪 zany face; 1F92A;
+😝 squinting face with tongue; 1F61D;
+🤑 money-mouth face; 1F911;
+🤗 hugging face; 1F917;
+🤭 face with hand over mouth; 1F92D;
+🤫 shushing face; 1F92B;
+🤔 thinking face; 1F914;
+🤐 zipper-mouth face; 1F910;
+🤨 face with raised eyebrow; 1F928;
+😐 neutral face; 1F610;
+😑 expressionless face; 1F611;
+😶 face without mouth; 1F636;
+😏 smirking face; 1F60F;
+😒 unamused face; 1F612;
+🙄 face with rolling eyes; 1F644;
+😬 grimacing face; 1F62C;
+🤥 lying face; 1F925;
+😌 relieved face; 1F60C;
+😔 pensive face; 1F614;
+😪 sleepy face; 1F62A;
+🤤 drooling face; 1F924;
+😴 sleeping face; 1F634;
+😷 face with medical mask; 1F637;
+🤒 face with thermometer; 1F912;
+🤕 face with head-bandage; 1F915;
+🤢 nauseated face; 1F922;
+🤮 face vomiting; 1F92E;
+🤧 sneezing face; 1F927;
+🥵 hot face; 1F975;
+🥶 cold face; 1F976;
+🥴 woozy face; 1F974;
+😵 dizzy face; 1F635;
+🤯 exploding head; 1F92F;
+🤠 cowboy hat face; 1F920;
+🥳 partying face; 1F973;
+🥸 disguised face; 1F978;
+😎 smiling face with sunglasses; 1F60E;
+🤓 nerd face; 1F913;
+🧐 face with monocle; 1F9D0;
+😕 confused face; 1F615;
+😟 worried face; 1F61F;
+🙁 slightly frowning face; 1F641;
+☹️ frowning face; 2639 FE0F;
+😮 face with open mouth; 1F62E;
+😯 hushed face; 1F62F;
+😲 astonished face; 1F632;
+😳 flushed face; 1F633;
+🥺 pleading face; 1F97A;
+😦 frowning face with open mouth; 1F626;
+😧 anguished face; 1F627;
+😨 fearful face; 1F628;
+😰 anxious face with sweat; 1F630;
+😥 sad but relieved face; 1F625;
+😢 crying face; 1F622;
+😭 loudly crying face; 1F62D;
+😱 face screaming in fear; 1F631;
+😖 confounded face; 1F616;
+😣 persevering face; 1F623;
+😞 disappointed face; 1F61E;
+😓 downcast face with sweat; 1F613;
+😩 weary face; 1F629;
+😫 tired face; 1F62B;
+🥱 yawning face; 1F971;
+😤 face with steam from nose; 1F624;
+😡 pouting face; 1F621;
+😠 angry face; 1F620;
+🤬 face with symbols on mouth; 1F92C;
+😈 smiling face with horns; 1F608;
+👿 angry face with horns; 1F47F;
+💀 skull; 1F480;
+☠️ skull and crossbones; 2620 FE0F;
+💩 pile of poo; 1F4A9;
+🤡 clown face; 1F921;
+👹 ogre; 1F479;
+👺 goblin; 1F47A;
+👻 ghost; 1F47B;
+👽 alien; 1F47D;
+👾 alien monster; 1F47E;
+🤖 robot; 1F916;
+😺 grinning cat; 1F63A;
+😸 grinning cat with smiling eyes; 1F638;
+😹 cat with tears of joy; 1F639;
+😻 smiling cat with heart-eyes; 1F63B;
+😼 cat with wry smile; 1F63C;
+😽 kissing cat; 1F63D;
+🙀 weary cat; 1F640;
+😿 crying cat; 1F63F;
+😾 pouting cat; 1F63E;
+🙈 see-no-evil monkey; 1F648;
+🙉 hear-no-evil monkey; 1F649;
+🙊 speak-no-evil monkey; 1F64A;
+💋 kiss mark; 1F48B;
+💌 love letter; 1F48C;
+💘 heart with arrow; 1F498;
+💝 heart with ribbon; 1F49D;
+💖 sparkling heart; 1F496;
+💗 growing heart; 1F497;
+💓 beating heart; 1F493;
+💞 revolving hearts; 1F49E;
+💕 two hearts; 1F495;
+💟 heart decoration; 1F49F;
+❣️ heart exclamation; 2763 FE0F;
+💔 broken heart; 1F494;
+❤️ red heart; 2764 FE0F;
+🧡 orange heart; 1F9E1;
+💛 yellow heart; 1F49B;
+💚 green heart; 1F49A;
+💙 blue heart; 1F499;
+💜 purple heart; 1F49C;
+🤎 brown heart; 1F90E;
+🖤 black heart; 1F5A4;
+🤍 white heart; 1F90D;
+💯 hundred points; 1F4AF;
+💢 anger symbol; 1F4A2;
+💥 collision; 1F4A5;
+💫 dizzy; 1F4AB;
+💦 sweat droplets; 1F4A6;
+💨 dashing away; 1F4A8;
+🕳️ hole; 1F573 FE0F;
+💣 bomb; 1F4A3;
+💬 speech balloon; 1F4AC;
+🗨️ left speech bubble; 1F5E8 FE0F;
+🗯️ right anger bubble; 1F5EF FE0F;
+💭 thought balloon; 1F4AD;
+💤 zzz; 1F4A4;
+👋 waving hand; 1F44B;
+🤚 raised back of hand; 1F91A;
+🖐️ hand with fingers splayed; 1F590 FE0F;
+✋ raised hand; 270B;
+🖖 vulcan salute; 1F596;
+👌 OK hand; 1F44C;
+🤌 pinched fingers; 1F90C;
+🤏 pinching hand; 1F90F;
+✌️ victory hand; 270C FE0F;
+🤞 crossed fingers; 1F91E;
+🤟 love-you gesture; 1F91F;
+🤘 sign of the horns; 1F918;
+🤙 call me hand; 1F919;
+👈 backhand index pointing left; 1F448;
+👉 backhand index pointing right; 1F449;
+👆 backhand index pointing up; 1F446;
+🖕 middle finger; 1F595;
+👇 backhand index pointing down; 1F447;
+☝️ index pointing up; 261D FE0F;
+👍 thumbs up; 1F44D;
+👎 thumbs down; 1F44E;
+✊ raised fist; 270A;
+👊 oncoming fist; 1F44A;
+🤛 left-facing fist; 1F91B;
+🤜 right-facing fist; 1F91C;
+👏 clapping hands; 1F44F;
+🙌 raising hands; 1F64C;
+👐 open hands; 1F450;
+🤲 palms up together; 1F932;
+🤝 handshake; 1F91D;
+🙏 folded hands; 1F64F;
+✍️ writing hand; 270D FE0F;
+💅 nail polish; 1F485;
+🤳 selfie; 1F933;
+💪 flexed biceps; 1F4AA;
+🦾 mechanical arm; 1F9BE;
+🦿 mechanical leg; 1F9BF;
+🦵 leg; 1F9B5;
+🦶 foot; 1F9B6;
+👂 ear; 1F442;
+🦻 ear with hearing aid; 1F9BB;
+👃 nose; 1F443;
+🧠 brain; 1F9E0;
+🫀 anatomical heart; 1FAC0;
+🫁 lungs; 1FAC1;
+🦷 tooth; 1F9B7;
+🦴 bone; 1F9B4;
+👀 eyes; 1F440;
+👁️ eye; 1F441 FE0F;
+👅 tongue; 1F445;
+👄 mouth; 1F444;
+👶 baby; 1F476;
+🧒 child; 1F9D2;
+👦 boy; 1F466;
+👧 girl; 1F467;
+🧑 person; 1F9D1;
+👱 person: blond hair; 1F471;
+👨 man; 1F468;
+🧔 man: beard; 1F9D4;
+👩 woman; 1F469;
+🧓 older person; 1F9D3;
+👴 old man; 1F474;
+👵 old woman; 1F475;
+🙍 person frowning; 1F64D;
+🙎 person pouting; 1F64E;
+🙅 person gesturing NO; 1F645;
+🙆 person gesturing OK; 1F646;
+💁 person tipping hand; 1F481;
+🙋 person raising hand; 1F64B;
+🧏 deaf person; 1F9CF;
+🙇 person bowing; 1F647;
+🤦 person facepalming; 1F926;
+🤷 person shrugging; 1F937;
+👮 police officer; 1F46E;
+🕵️ detective; 1F575 FE0F;
+💂 guard; 1F482;
+🥷 ninja; 1F977;
+👷 construction worker; 1F477;
+🤴 prince; 1F934;
+👸 princess; 1F478;
+👳 person wearing turban; 1F473;
+👲 person with skullcap; 1F472;
+🧕 woman with headscarf; 1F9D5;
+🤵 person in tuxedo; 1F935;
+👰 person with veil; 1F470;
+🤰 pregnant woman; 1F930;
+🤱 breast-feeding; 1F931;
+👼 baby angel; 1F47C;
+🎅 Santa Claus; 1F385;
+🤶 Mrs. Claus; 1F936;
+🦸 superhero; 1F9B8;
+🦹 supervillain; 1F9B9;
+🧙 mage; 1F9D9;
+🧚 fairy; 1F9DA;
+🧛 vampire; 1F9DB;
+🧜 merperson; 1F9DC;
+🧝 elf; 1F9DD;
+🧞 genie; 1F9DE;
+🧟 zombie; 1F9DF;
+💆 person getting massage; 1F486;
+💇 person getting haircut; 1F487;
+🚶 person walking; 1F6B6;
+🧍 person standing; 1F9CD;
+🧎 person kneeling; 1F9CE;
+🏃 person running; 1F3C3;
+💃 woman dancing; 1F483;
+🕺 man dancing; 1F57A;
+🕴️ person in suit levitating; 1F574 FE0F;
+👯 people with bunny ears; 1F46F;
+🧖 person in steamy room; 1F9D6;
+🧗 person climbing; 1F9D7;
+🤺 person fencing; 1F93A;
+🏇 horse racing; 1F3C7;
+⛷️ skier; 26F7 FE0F;
+🏂 snowboarder; 1F3C2;
+🏌️ person golfing; 1F3CC FE0F;
+🏄 person surfing; 1F3C4;
+🚣 person rowing boat; 1F6A3;
+🏊 person swimming; 1F3CA;
+⛹️ person bouncing ball; 26F9 FE0F;
+🏋️ person lifting weights; 1F3CB FE0F;
+🚴 person biking; 1F6B4;
+🚵 person mountain biking; 1F6B5;
+🤸 person cartwheeling; 1F938;
+🤼 people wrestling; 1F93C;
+🤽 person playing water polo; 1F93D;
+🤾 person playing handball; 1F93E;
+🤹 person juggling; 1F939;
+🧘 person in lotus position; 1F9D8;
+🛀 person taking bath; 1F6C0;
+🛌 person in bed; 1F6CC;
+👭 women holding hands; 1F46D;
+👫 woman and man holding hands; 1F46B;
+👬 men holding hands; 1F46C;
+💏 kiss; 1F48F;
+💑 couple with heart; 1F491;
+👪 family; 1F46A;
+🗣️ speaking head; 1F5E3 FE0F;
+👤 bust in silhouette; 1F464;
+👥 busts in silhouette; 1F465;
+🫂 people hugging; 1FAC2;
+👣 footprints; 1F463;
+🐵 monkey face; 1F435;
+🐒 monkey; 1F412;
+🦍 gorilla; 1F98D;
+🦧 orangutan; 1F9A7;
+🐶 dog face; 1F436;
+🐕 dog; 1F415;
+🦮 guide dog; 1F9AE;
+🐩 poodle; 1F429;
+🐺 wolf; 1F43A;
+🦊 fox; 1F98A;
+🦝 raccoon; 1F99D;
+🐱 cat face; 1F431;
+🐈 cat; 1F408;
+🦁 lion; 1F981;
+🐯 tiger face; 1F42F;
+🐅 tiger; 1F405;
+🐆 leopard; 1F406;
+🐴 horse face; 1F434;
+🐎 horse; 1F40E;
+🦄 unicorn; 1F984;
+🦓 zebra; 1F993;
+🦌 deer; 1F98C;
+🦬 bison; 1F9AC;
+🐮 cow face; 1F42E;
+🐂 ox; 1F402;
+🐃 water buffalo; 1F403;
+🐄 cow; 1F404;
+🐷 pig face; 1F437;
+🐖 pig; 1F416;
+🐗 boar; 1F417;
+🐽 pig nose; 1F43D;
+🐏 ram; 1F40F;
+🐑 ewe; 1F411;
+🐐 goat; 1F410;
+🐪 camel; 1F42A;
+🐫 two-hump camel; 1F42B;
+🦙 llama; 1F999;
+🦒 giraffe; 1F992;
+🐘 elephant; 1F418;
+🦣 mammoth; 1F9A3;
+🦏 rhinoceros; 1F98F;
+🦛 hippopotamus; 1F99B;
+🐭 mouse face; 1F42D;
+🐁 mouse; 1F401;
+🐀 rat; 1F400;
+🐹 hamster; 1F439;
+🐰 rabbit face; 1F430;
+🐇 rabbit; 1F407;
+🐿️ chipmunk; 1F43F FE0F;
+🦫 beaver; 1F9AB;
+🦔 hedgehog; 1F994;
+🦇 bat; 1F987;
+🐻 bear; 1F43B;
+🐨 koala; 1F428;
+🐼 panda; 1F43C;
+🦥 sloth; 1F9A5;
+🦦 otter; 1F9A6;
+🦨 skunk; 1F9A8;
+🦘 kangaroo; 1F998;
+🦡 badger; 1F9A1;
+🐾 paw prints; 1F43E;
+🦃 turkey; 1F983;
+🐔 chicken; 1F414;
+🐓 rooster; 1F413;
+🐣 hatching chick; 1F423;
+🐤 baby chick; 1F424;
+🐥 front-facing baby chick; 1F425;
+🐦 bird; 1F426;
+🐧 penguin; 1F427;
+🕊️ dove; 1F54A FE0F;
+🦅 eagle; 1F985;
+🦆 duck; 1F986;
+🦢 swan; 1F9A2;
+🦉 owl; 1F989;
+🦤 dodo; 1F9A4;
+🪶 feather; 1FAB6;
+🦩 flamingo; 1F9A9;
+🦚 peacock; 1F99A;
+🦜 parrot; 1F99C;
+🐸 frog; 1F438;
+🐊 crocodile; 1F40A;
+🐢 turtle; 1F422;
+🦎 lizard; 1F98E;
+🐍 snake; 1F40D;
+🐲 dragon face; 1F432;
+🐉 dragon; 1F409;
+🦕 sauropod; 1F995;
+🦖 T-Rex; 1F996;
+🐳 spouting whale; 1F433;
+🐋 whale; 1F40B;
+🐬 dolphin; 1F42C;
+🦭 seal; 1F9AD;
+🐟 fish; 1F41F;
+🐠 tropical fish; 1F420;
+🐡 blowfish; 1F421;
+🦈 shark; 1F988;
+🐙 octopus; 1F419;
+🐚 spiral shell; 1F41A;
+🐌 snail; 1F40C;
+🦋 butterfly; 1F98B;
+🐛 bug; 1F41B;
+🐜 ant; 1F41C;
+🐝 honeybee; 1F41D;
+🪲 beetle; 1FAB2;
+🐞 lady beetle; 1F41E;
+🦗 cricket; 1F997;
+🪳 cockroach; 1FAB3;
+🕷️ spider; 1F577 FE0F;
+🕸️ spider web; 1F578 FE0F;
+🦂 scorpion; 1F982;
+🦟 mosquito; 1F99F;
+🪰 fly; 1FAB0;
+🪱 worm; 1FAB1;
+🦠 microbe; 1F9A0;
+💐 bouquet; 1F490;
+🌸 cherry blossom; 1F338;
+💮 white flower; 1F4AE;
+🏵️ rosette; 1F3F5 FE0F;
+🌹 rose; 1F339;
+🥀 wilted flower; 1F940;
+🌺 hibiscus; 1F33A;
+🌻 sunflower; 1F33B;
+🌼 blossom; 1F33C;
+🌷 tulip; 1F337;
+🌱 seedling; 1F331;
+🪴 potted plant; 1FAB4;
+🌲 evergreen tree; 1F332;
+🌳 deciduous tree; 1F333;
+🌴 palm tree; 1F334;
+🌵 cactus; 1F335;
+🌾 sheaf of rice; 1F33E;
+🌿 herb; 1F33F;
+☘️ shamrock; 2618 FE0F;
+🍀 four leaf clover; 1F340;
+🍁 maple leaf; 1F341;
+🍂 fallen leaf; 1F342;
+🍃 leaf fluttering in wind; 1F343;
+🍇 grapes; 1F347;
+🍈 melon; 1F348;
+🍉 watermelon; 1F349;
+🍊 tangerine; 1F34A;
+🍋 lemon; 1F34B;
+🍌 banana; 1F34C;
+🍍 pineapple; 1F34D;
+🥭 mango; 1F96D;
+🍎 red apple; 1F34E;
+🍏 green apple; 1F34F;
+🍐 pear; 1F350;
+🍑 peach; 1F351;
+🍒 cherries; 1F352;
+🍓 strawberry; 1F353;
+🫐 blueberries; 1FAD0;
+🥝 kiwi fruit; 1F95D;
+🍅 tomato; 1F345;
+🫒 olive; 1FAD2;
+🥥 coconut; 1F965;
+🥑 avocado; 1F951;
+🍆 eggplant; 1F346;
+🥔 potato; 1F954;
+🥕 carrot; 1F955;
+🌽 ear of corn; 1F33D;
+🌶️ hot pepper; 1F336 FE0F;
+🫑 bell pepper; 1FAD1;
+🥒 cucumber; 1F952;
+🥬 leafy green; 1F96C;
+🥦 broccoli; 1F966;
+🧄 garlic; 1F9C4;
+🧅 onion; 1F9C5;
+🍄 mushroom; 1F344;
+🥜 peanuts; 1F95C;
+🌰 chestnut; 1F330;
+🍞 bread; 1F35E;
+🥐 croissant; 1F950;
+🥖 baguette bread; 1F956;
+🫓 flatbread; 1FAD3;
+🥨 pretzel; 1F968;
+🥯 bagel; 1F96F;
+🥞 pancakes; 1F95E;
+🧇 waffle; 1F9C7;
+🧀 cheese wedge; 1F9C0;
+🍖 meat on bone; 1F356;
+🍗 poultry leg; 1F357;
+🥩 cut of meat; 1F969;
+🥓 bacon; 1F953;
+🍔 hamburger; 1F354;
+🍟 french fries; 1F35F;
+🍕 pizza; 1F355;
+🌭 hot dog; 1F32D;
+🥪 sandwich; 1F96A;
+🌮 taco; 1F32E;
+🌯 burrito; 1F32F;
+🫔 tamale; 1FAD4;
+🥙 stuffed flatbread; 1F959;
+🧆 falafel; 1F9C6;
+🥚 egg; 1F95A;
+🍳 cooking; 1F373;
+🥘 shallow pan of food; 1F958;
+🍲 pot of food; 1F372;
+🫕 fondue; 1FAD5;
+🥣 bowl with spoon; 1F963;
+🥗 green salad; 1F957;
+🍿 popcorn; 1F37F;
+🧈 butter; 1F9C8;
+🧂 salt; 1F9C2;
+🥫 canned food; 1F96B;
+🍱 bento box; 1F371;
+🍘 rice cracker; 1F358;
+🍙 rice ball; 1F359;
+🍚 cooked rice; 1F35A;
+🍛 curry rice; 1F35B;
+🍜 steaming bowl; 1F35C;
+🍝 spaghetti; 1F35D;
+🍠 roasted sweet potato; 1F360;
+🍢 oden; 1F362;
+🍣 sushi; 1F363;
+🍤 fried shrimp; 1F364;
+🍥 fish cake with swirl; 1F365;
+🥮 moon cake; 1F96E;
+🍡 dango; 1F361;
+🥟 dumpling; 1F95F;
+🥠 fortune cookie; 1F960;
+🥡 takeout box; 1F961;
+🦀 crab; 1F980;
+🦞 lobster; 1F99E;
+🦐 shrimp; 1F990;
+🦑 squid; 1F991;
+🦪 oyster; 1F9AA;
+🍦 soft ice cream; 1F366;
+🍧 shaved ice; 1F367;
+🍨 ice cream; 1F368;
+🍩 doughnut; 1F369;
+🍪 cookie; 1F36A;
+🎂 birthday cake; 1F382;
+🍰 shortcake; 1F370;
+🧁 cupcake; 1F9C1;
+🥧 pie; 1F967;
+🍫 chocolate bar; 1F36B;
+🍬 candy; 1F36C;
+🍭 lollipop; 1F36D;
+🍮 custard; 1F36E;
+🍯 honey pot; 1F36F;
+🍼 baby bottle; 1F37C;
+🥛 glass of milk; 1F95B;
+☕ hot beverage; 2615;
+🫖 teapot; 1FAD6;
+🍵 teacup without handle; 1F375;
+🍶 sake; 1F376;
+🍾 bottle with popping cork; 1F37E;
+🍷 wine glass; 1F377;
+🍸 cocktail glass; 1F378;
+🍹 tropical drink; 1F379;
+🍺 beer mug; 1F37A;
+🍻 clinking beer mugs; 1F37B;
+🥂 clinking glasses; 1F942;
+🥃 tumbler glass; 1F943;
+🥤 cup with straw; 1F964;
+🧋 bubble tea; 1F9CB;
+🧃 beverage box; 1F9C3;
+🧉 mate; 1F9C9;
+🧊 ice; 1F9CA;
+🥢 chopsticks; 1F962;
+🍽️ fork and knife with plate; 1F37D FE0F;
+🍴 fork and knife; 1F374;
+🥄 spoon; 1F944;
+🔪 kitchen knife; 1F52A;
+🏺 amphora; 1F3FA;
+🌍 globe showing Europe-Africa; 1F30D;
+🌎 globe showing Americas; 1F30E;
+🌏 globe showing Asia-Australia; 1F30F;
+🌐 globe with meridians; 1F310;
+🗺️ world map; 1F5FA FE0F;
+🗾 map of Japan; 1F5FE;
+🧭 compass; 1F9ED;
+🏔️ snow-capped mountain; 1F3D4 FE0F;
+⛰️ mountain; 26F0 FE0F;
+🌋 volcano; 1F30B;
+🗻 mount fuji; 1F5FB;
+🏕️ camping; 1F3D5 FE0F;
+🏖️ beach with umbrella; 1F3D6 FE0F;
+🏜️ desert; 1F3DC FE0F;
+🏝️ desert island; 1F3DD FE0F;
+🏞️ national park; 1F3DE FE0F;
+🏟️ stadium; 1F3DF FE0F;
+🏛️ classical building; 1F3DB FE0F;
+🏗️ building construction; 1F3D7 FE0F;
+🧱 brick; 1F9F1;
+🪨 rock; 1FAA8;
+🪵 wood; 1FAB5;
+🛖 hut; 1F6D6;
+🏘️ houses; 1F3D8 FE0F;
+🏚️ derelict house; 1F3DA FE0F;
+🏠 house; 1F3E0;
+🏡 house with garden; 1F3E1;
+🏢 office building; 1F3E2;
+🏣 Japanese post office; 1F3E3;
+🏤 post office; 1F3E4;
+🏥 hospital; 1F3E5;
+🏦 bank; 1F3E6;
+🏨 hotel; 1F3E8;
+🏩 love hotel; 1F3E9;
+🏪 convenience store; 1F3EA;
+🏫 school; 1F3EB;
+🏬 department store; 1F3EC;
+🏭 factory; 1F3ED;
+🏯 Japanese castle; 1F3EF;
+🏰 castle; 1F3F0;
+💒 wedding; 1F492;
+🗼 Tokyo tower; 1F5FC;
+🗽 Statue of Liberty; 1F5FD;
+⛪ church; 26EA;
+🕌 mosque; 1F54C;
+🛕 hindu temple; 1F6D5;
+🕍 synagogue; 1F54D;
+⛩️ shinto shrine; 26E9 FE0F;
+🕋 kaaba; 1F54B;
+⛲ fountain; 26F2;
+⛺ tent; 26FA;
+🌁 foggy; 1F301;
+🌃 night with stars; 1F303;
+🏙️ cityscape; 1F3D9 FE0F;
+🌄 sunrise over mountains; 1F304;
+🌅 sunrise; 1F305;
+🌆 cityscape at dusk; 1F306;
+🌇 sunset; 1F307;
+🌉 bridge at night; 1F309;
+♨️ hot springs; 2668 FE0F;
+🎠 carousel horse; 1F3A0;
+🎡 ferris wheel; 1F3A1;
+🎢 roller coaster; 1F3A2;
+💈 barber pole; 1F488;
+🎪 circus tent; 1F3AA;
+🚂 locomotive; 1F682;
+🚃 railway car; 1F683;
+🚄 high-speed train; 1F684;
+🚅 bullet train; 1F685;
+🚆 train; 1F686;
+🚇 metro; 1F687;
+🚈 light rail; 1F688;
+🚉 station; 1F689;
+🚊 tram; 1F68A;
+🚝 monorail; 1F69D;
+🚞 mountain railway; 1F69E;
+🚋 tram car; 1F68B;
+🚌 bus; 1F68C;
+🚍 oncoming bus; 1F68D;
+🚎 trolleybus; 1F68E;
+🚐 minibus; 1F690;
+🚑 ambulance; 1F691;
+🚒 fire engine; 1F692;
+🚓 police car; 1F693;
+🚔 oncoming police car; 1F694;
+🚕 taxi; 1F695;
+🚖 oncoming taxi; 1F696;
+🚗 automobile; 1F697;
+🚘 oncoming automobile; 1F698;
+🚙 sport utility vehicle; 1F699;
+🛻 pickup truck; 1F6FB;
+🚚 delivery truck; 1F69A;
+🚛 articulated lorry; 1F69B;
+🚜 tractor; 1F69C;
+🏎️ racing car; 1F3CE FE0F;
+🏍️ motorcycle; 1F3CD FE0F;
+🛵 motor scooter; 1F6F5;
+🦽 manual wheelchair; 1F9BD;
+🦼 motorized wheelchair; 1F9BC;
+🛺 auto rickshaw; 1F6FA;
+🚲 bicycle; 1F6B2;
+🛴 kick scooter; 1F6F4;
+🛹 skateboard; 1F6F9;
+🛼 roller skate; 1F6FC;
+🚏 bus stop; 1F68F;
+🛣️ motorway; 1F6E3 FE0F;
+🛤️ railway track; 1F6E4 FE0F;
+🛢️ oil drum; 1F6E2 FE0F;
+⛽ fuel pump; 26FD;
+🚨 police car light; 1F6A8;
+🚥 horizontal traffic light; 1F6A5;
+🚦 vertical traffic light; 1F6A6;
+🛑 stop sign; 1F6D1;
+🚧 construction; 1F6A7;
+⚓ anchor; 2693;
+⛵ sailboat; 26F5;
+🛶 canoe; 1F6F6;
+🚤 speedboat; 1F6A4;
+🛳️ passenger ship; 1F6F3 FE0F;
+⛴️ ferry; 26F4 FE0F;
+🛥️ motor boat; 1F6E5 FE0F;
+🚢 ship; 1F6A2;
+✈️ airplane; 2708 FE0F;
+🛩️ small airplane; 1F6E9 FE0F;
+🛫 airplane departure; 1F6EB;
+🛬 airplane arrival; 1F6EC;
+🪂 parachute; 1FA82;
+💺 seat; 1F4BA;
+🚁 helicopter; 1F681;
+🚟 suspension railway; 1F69F;
+🚠 mountain cableway; 1F6A0;
+🚡 aerial tramway; 1F6A1;
+🛰️ satellite; 1F6F0 FE0F;
+🚀 rocket; 1F680;
+🛸 flying saucer; 1F6F8;
+🛎️ bellhop bell; 1F6CE FE0F;
+🧳 luggage; 1F9F3;
+⌛ hourglass done; 231B;
+⏳ hourglass not done; 23F3;
+⌚ watch; 231A;
+⏰ alarm clock; 23F0;
+⏱️ stopwatch; 23F1 FE0F;
+⏲️ timer clock; 23F2 FE0F;
+🕰️ mantelpiece clock; 1F570 FE0F;
+🕛 twelve o’clock; 1F55B;
+🕧 twelve-thirty; 1F567;
+🕐 one o’clock; 1F550;
+🕜 one-thirty; 1F55C;
+🕑 two o’clock; 1F551;
+🕝 two-thirty; 1F55D;
+🕒 three o’clock; 1F552;
+🕞 three-thirty; 1F55E;
+🕓 four o’clock; 1F553;
+🕟 four-thirty; 1F55F;
+🕔 five o’clock; 1F554;
+🕠 five-thirty; 1F560;
+🕕 six o’clock; 1F555;
+🕡 six-thirty; 1F561;
+🕖 seven o’clock; 1F556;
+🕢 seven-thirty; 1F562;
+🕗 eight o’clock; 1F557;
+🕣 eight-thirty; 1F563;
+🕘 nine o’clock; 1F558;
+🕤 nine-thirty; 1F564;
+🕙 ten o’clock; 1F559;
+🕥 ten-thirty; 1F565;
+🕚 eleven o’clock; 1F55A;
+🕦 eleven-thirty; 1F566;
+🌑 new moon; 1F311;
+🌒 waxing crescent moon; 1F312;
+🌓 first quarter moon; 1F313;
+🌔 waxing gibbous moon; 1F314;
+🌕 full moon; 1F315;
+🌖 waning gibbous moon; 1F316;
+🌗 last quarter moon; 1F317;
+🌘 waning crescent moon; 1F318;
+🌙 crescent moon; 1F319;
+🌚 new moon face; 1F31A;
+🌛 first quarter moon face; 1F31B;
+🌜 last quarter moon face; 1F31C;
+🌡️ thermometer; 1F321 FE0F;
+☀️ sun; 2600 FE0F;
+🌝 full moon face; 1F31D;
+🌞 sun with face; 1F31E;
+🪐 ringed planet; 1FA90;
+⭐ star; 2B50;
+🌟 glowing star; 1F31F;
+🌠 shooting star; 1F320;
+🌌 milky way; 1F30C;
+☁️ cloud; 2601 FE0F;
+⛅ sun behind cloud; 26C5;
+⛈️ cloud with lightning and rain; 26C8 FE0F;
+🌤️ sun behind small cloud; 1F324 FE0F;
+🌥️ sun behind large cloud; 1F325 FE0F;
+🌦️ sun behind rain cloud; 1F326 FE0F;
+🌧️ cloud with rain; 1F327 FE0F;
+🌨️ cloud with snow; 1F328 FE0F;
+🌩️ cloud with lightning; 1F329 FE0F;
+🌪️ tornado; 1F32A FE0F;
+🌫️ fog; 1F32B FE0F;
+🌬️ wind face; 1F32C FE0F;
+🌀 cyclone; 1F300;
+🌈 rainbow; 1F308;
+🌂 closed umbrella; 1F302;
+☂️ umbrella; 2602 FE0F;
+☔ umbrella with rain drops; 2614;
+⛱️ umbrella on ground; 26F1 FE0F;
+⚡ high voltage; 26A1;
+❄️ snowflake; 2744 FE0F;
+☃️ snowman; 2603 FE0F;
+⛄ snowman without snow; 26C4;
+☄️ comet; 2604 FE0F;
+🔥 fire; 1F525;
+💧 droplet; 1F4A7;
+🌊 water wave; 1F30A;
+🎃 jack-o-lantern; 1F383;
+🎄 Christmas tree; 1F384;
+🎆 fireworks; 1F386;
+🎇 sparkler; 1F387;
+🧨 firecracker; 1F9E8;
+✨ sparkles; 2728;
+🎈 balloon; 1F388;
+🎉 party popper; 1F389;
+🎊 confetti ball; 1F38A;
+🎋 tanabata tree; 1F38B;
+🎍 pine decoration; 1F38D;
+🎎 Japanese dolls; 1F38E;
+🎏 carp streamer; 1F38F;
+🎐 wind chime; 1F390;
+🎑 moon viewing ceremony; 1F391;
+🧧 red envelope; 1F9E7;
+🎀 ribbon; 1F380;
+🎁 wrapped gift; 1F381;
+🎗️ reminder ribbon; 1F397 FE0F;
+🎟️ admission tickets; 1F39F FE0F;
+🎫 ticket; 1F3AB;
+🎖️ military medal; 1F396 FE0F;
+🏆 trophy; 1F3C6;
+🏅 sports medal; 1F3C5;
+🥇 1st place medal; 1F947;
+🥈 2nd place medal; 1F948;
+🥉 3rd place medal; 1F949;
+⚽ soccer ball; 26BD;
+⚾ baseball; 26BE;
+🥎 softball; 1F94E;
+🏀 basketball; 1F3C0;
+🏐 volleyball; 1F3D0;
+🏈 american football; 1F3C8;
+🏉 rugby football; 1F3C9;
+🎾 tennis; 1F3BE;
+🥏 flying disc; 1F94F;
+🎳 bowling; 1F3B3;
+🏏 cricket game; 1F3CF;
+🏑 field hockey; 1F3D1;
+🏒 ice hockey; 1F3D2;
+🥍 lacrosse; 1F94D;
+🏓 ping pong; 1F3D3;
+🏸 badminton; 1F3F8;
+🥊 boxing glove; 1F94A;
+🥋 martial arts uniform; 1F94B;
+🥅 goal net; 1F945;
+⛳ flag in hole; 26F3;
+⛸️ ice skate; 26F8 FE0F;
+🎣 fishing pole; 1F3A3;
+🤿 diving mask; 1F93F;
+🎽 running shirt; 1F3BD;
+🎿 skis; 1F3BF;
+🛷 sled; 1F6F7;
+🥌 curling stone; 1F94C;
+🎯 direct hit; 1F3AF;
+🪀 yo-yo; 1FA80;
+🪁 kite; 1FA81;
+🎱 pool 8 ball; 1F3B1;
+🔮 crystal ball; 1F52E;
+🪄 magic wand; 1FA84;
+🧿 nazar amulet; 1F9FF;
+🎮 video game; 1F3AE;
+🕹️ joystick; 1F579 FE0F;
+🎰 slot machine; 1F3B0;
+🎲 game die; 1F3B2;
+🧩 puzzle piece; 1F9E9;
+🧸 teddy bear; 1F9F8;
+🪅 piñata; 1FA85;
+🪆 nesting dolls; 1FA86;
+♠️ spade suit; 2660 FE0F;
+♥️ heart suit; 2665 FE0F;
+♦️ diamond suit; 2666 FE0F;
+♣️ club suit; 2663 FE0F;
+♟️ chess pawn; 265F FE0F;
+🃏 joker; 1F0CF;
+🀄 mahjong red dragon; 1F004;
+🎴 flower playing cards; 1F3B4;
+🎭 performing arts; 1F3AD;
+🖼️ framed picture; 1F5BC FE0F;
+🎨 artist palette; 1F3A8;
+🧵 thread; 1F9F5;
+🪡 sewing needle; 1FAA1;
+🧶 yarn; 1F9F6;
+🪢 knot; 1FAA2;
+👓 glasses; 1F453;
+🕶️ sunglasses; 1F576 FE0F;
+🥽 goggles; 1F97D;
+🥼 lab coat; 1F97C;
+🦺 safety vest; 1F9BA;
+👔 necktie; 1F454;
+👕 t-shirt; 1F455;
+👖 jeans; 1F456;
+🧣 scarf; 1F9E3;
+🧤 gloves; 1F9E4;
+🧥 coat; 1F9E5;
+🧦 socks; 1F9E6;
+👗 dress; 1F457;
+👘 kimono; 1F458;
+🥻 sari; 1F97B;
+🩱 one-piece swimsuit; 1FA71;
+🩲 briefs; 1FA72;
+🩳 shorts; 1FA73;
+👙 bikini; 1F459;
+👚 woman’s clothes; 1F45A;
+👛 purse; 1F45B;
+👜 handbag; 1F45C;
+👝 clutch bag; 1F45D;
+🛍️ shopping bags; 1F6CD FE0F;
+🎒 backpack; 1F392;
+🩴 thong sandal; 1FA74;
+👞 man’s shoe; 1F45E;
+👟 running shoe; 1F45F;
+🥾 hiking boot; 1F97E;
+🥿 flat shoe; 1F97F;
+👠 high-heeled shoe; 1F460;
+👡 woman’s sandal; 1F461;
+🩰 ballet shoes; 1FA70;
+👢 woman’s boot; 1F462;
+👑 crown; 1F451;
+👒 woman’s hat; 1F452;
+🎩 top hat; 1F3A9;
+🎓 graduation cap; 1F393;
+🧢 billed cap; 1F9E2;
+🪖 military helmet; 1FA96;
+⛑️ rescue worker’s helmet; 26D1 FE0F;
+📿 prayer beads; 1F4FF;
+💄 lipstick; 1F484;
+💍 ring; 1F48D;
+💎 gem stone; 1F48E;
+🔇 muted speaker; 1F507;
+🔈 speaker low volume; 1F508;
+🔉 speaker medium volume; 1F509;
+🔊 speaker high volume; 1F50A;
+📢 loudspeaker; 1F4E2;
+📣 megaphone; 1F4E3;
+📯 postal horn; 1F4EF;
+🔔 bell; 1F514;
+🔕 bell with slash; 1F515;
+🎼 musical score; 1F3BC;
+🎵 musical note; 1F3B5;
+🎶 musical notes; 1F3B6;
+🎙️ studio microphone; 1F399 FE0F;
+🎚️ level slider; 1F39A FE0F;
+🎛️ control knobs; 1F39B FE0F;
+🎤 microphone; 1F3A4;
+🎧 headphone; 1F3A7;
+📻 radio; 1F4FB;
+🎷 saxophone; 1F3B7;
+🪗 accordion; 1FA97;
+🎸 guitar; 1F3B8;
+🎹 musical keyboard; 1F3B9;
+🎺 trumpet; 1F3BA;
+🎻 violin; 1F3BB;
+🪕 banjo; 1FA95;
+🥁 drum; 1F941;
+🪘 long drum; 1FA98;
+📱 mobile phone; 1F4F1;
+📲 mobile phone with arrow; 1F4F2;
+☎️ telephone; 260E FE0F;
+📞 telephone receiver; 1F4DE;
+📟 pager; 1F4DF;
+📠 fax machine; 1F4E0;
+🔋 battery; 1F50B;
+🔌 electric plug; 1F50C;
+💻 laptop; 1F4BB;
+🖥️ desktop computer; 1F5A5 FE0F;
+🖨️ printer; 1F5A8 FE0F;
+⌨️ keyboard; 2328 FE0F;
+🖱️ computer mouse; 1F5B1 FE0F;
+🖲️ trackball; 1F5B2 FE0F;
+💽 computer disk; 1F4BD;
+💾 floppy disk; 1F4BE;
+💿 optical disk; 1F4BF;
+📀 dvd; 1F4C0;
+🧮 abacus; 1F9EE;
+🎥 movie camera; 1F3A5;
+🎞️ film frames; 1F39E FE0F;
+📽️ film projector; 1F4FD FE0F;
+🎬 clapper board; 1F3AC;
+📺 television; 1F4FA;
+📷 camera; 1F4F7;
+📸 camera with flash; 1F4F8;
+📹 video camera; 1F4F9;
+📼 videocassette; 1F4FC;
+🔍 magnifying glass tilted left; 1F50D;
+🔎 magnifying glass tilted right; 1F50E;
+🕯️ candle; 1F56F FE0F;
+💡 light bulb; 1F4A1;
+🔦 flashlight; 1F526;
+🏮 red paper lantern; 1F3EE;
+🪔 diya lamp; 1FA94;
+📔 notebook with decorative cover; 1F4D4;
+📕 closed book; 1F4D5;
+📖 open book; 1F4D6;
+📗 green book; 1F4D7;
+📘 blue book; 1F4D8;
+📙 orange book; 1F4D9;
+📚 books; 1F4DA;
+📓 notebook; 1F4D3;
+📒 ledger; 1F4D2;
+📃 page with curl; 1F4C3;
+📜 scroll; 1F4DC;
+📄 page facing up; 1F4C4;
+📰 newspaper; 1F4F0;
+🗞️ rolled-up newspaper; 1F5DE FE0F;
+📑 bookmark tabs; 1F4D1;
+🔖 bookmark; 1F516;
+🏷️ label; 1F3F7 FE0F;
+💰 money bag; 1F4B0;
+🪙 coin; 1FA99;
+💴 yen banknote; 1F4B4;
+💵 dollar banknote; 1F4B5;
+💶 euro banknote; 1F4B6;
+💷 pound banknote; 1F4B7;
+💸 money with wings; 1F4B8;
+💳 credit card; 1F4B3;
+🧾 receipt; 1F9FE;
+💹 chart increasing with yen; 1F4B9;
+✉️ envelope; 2709 FE0F;
+📧 e-mail; 1F4E7;
+📨 incoming envelope; 1F4E8;
+📩 envelope with arrow; 1F4E9;
+📤 outbox tray; 1F4E4;
+📥 inbox tray; 1F4E5;
+📦 package; 1F4E6;
+📫 closed mailbox with raised flag; 1F4EB;
+📪 closed mailbox with lowered flag; 1F4EA;
+📬 open mailbox with raised flag; 1F4EC;
+📭 open mailbox with lowered flag; 1F4ED;
+📮 postbox; 1F4EE;
+🗳️ ballot box with ballot; 1F5F3 FE0F;
+✏️ pencil; 270F FE0F;
+✒️ black nib; 2712 FE0F;
+🖋️ fountain pen; 1F58B FE0F;
+🖊️ pen; 1F58A FE0F;
+🖌️ paintbrush; 1F58C FE0F;
+🖍️ crayon; 1F58D FE0F;
+📝 memo; 1F4DD;
+💼 briefcase; 1F4BC;
+📁 file folder; 1F4C1;
+📂 open file folder; 1F4C2;
+🗂️ card index dividers; 1F5C2 FE0F;
+📅 calendar; 1F4C5;
+📆 tear-off calendar; 1F4C6;
+🗒️ spiral notepad; 1F5D2 FE0F;
+🗓️ spiral calendar; 1F5D3 FE0F;
+📇 card index; 1F4C7;
+📈 chart increasing; 1F4C8;
+📉 chart decreasing; 1F4C9;
+📊 bar chart; 1F4CA;
+📋 clipboard; 1F4CB;
+📌 pushpin; 1F4CC;
+📍 round pushpin; 1F4CD;
+📎 paperclip; 1F4CE;
+🖇️ linked paperclips; 1F587 FE0F;
+📏 straight ruler; 1F4CF;
+📐 triangular ruler; 1F4D0;
+✂️ scissors; 2702 FE0F;
+🗃️ card file box; 1F5C3 FE0F;
+🗄️ file cabinet; 1F5C4 FE0F;
+🗑️ wastebasket; 1F5D1 FE0F;
+🔒 locked; 1F512;
+🔓 unlocked; 1F513;
+🔏 locked with pen; 1F50F;
+🔐 locked with key; 1F510;
+🔑 key; 1F511;
+🗝️ old key; 1F5DD FE0F;
+🔨 hammer; 1F528;
+🪓 axe; 1FA93;
+⛏️ pick; 26CF FE0F;
+⚒️ hammer and pick; 2692 FE0F;
+🛠️ hammer and wrench; 1F6E0 FE0F;
+🗡️ dagger; 1F5E1 FE0F;
+⚔️ crossed swords; 2694 FE0F;
+🔫 pistol; 1F52B;
+🪃 boomerang; 1FA83;
+🏹 bow and arrow; 1F3F9;
+🛡️ shield; 1F6E1 FE0F;
+🪚 carpentry saw; 1FA9A;
+🔧 wrench; 1F527;
+🪛 screwdriver; 1FA9B;
+🔩 nut and bolt; 1F529;
+⚙️ gear; 2699 FE0F;
+🗜️ clamp; 1F5DC FE0F;
+⚖️ balance scale; 2696 FE0F;
+🦯 white cane; 1F9AF;
+🔗 link; 1F517;
+⛓️ chains; 26D3 FE0F;
+🪝 hook; 1FA9D;
+🧰 toolbox; 1F9F0;
+🧲 magnet; 1F9F2;
+🪜 ladder; 1FA9C;
+⚗️ alembic; 2697 FE0F;
+🧪 test tube; 1F9EA;
+🧫 petri dish; 1F9EB;
+🧬 dna; 1F9EC;
+🔬 microscope; 1F52C;
+🔭 telescope; 1F52D;
+📡 satellite antenna; 1F4E1;
+💉 syringe; 1F489;
+🩸 drop of blood; 1FA78;
+💊 pill; 1F48A;
+🩹 adhesive bandage; 1FA79;
+🩺 stethoscope; 1FA7A;
+🚪 door; 1F6AA;
+🛗 elevator; 1F6D7;
+🪞 mirror; 1FA9E;
+🪟 window; 1FA9F;
+🛏️ bed; 1F6CF FE0F;
+🛋️ couch and lamp; 1F6CB FE0F;
+🪑 chair; 1FA91;
+🚽 toilet; 1F6BD;
+🪠 plunger; 1FAA0;
+🚿 shower; 1F6BF;
+🛁 bathtub; 1F6C1;
+🪤 mouse trap; 1FAA4;
+🪒 razor; 1FA92;
+🧴 lotion bottle; 1F9F4;
+🧷 safety pin; 1F9F7;
+🧹 broom; 1F9F9;
+🧺 basket; 1F9FA;
+🧻 roll of paper; 1F9FB;
+🪣 bucket; 1FAA3;
+🧼 soap; 1F9FC;
+🪥 toothbrush; 1FAA5;
+🧽 sponge; 1F9FD;
+🧯 fire extinguisher; 1F9EF;
+🛒 shopping cart; 1F6D2;
+🚬 cigarette; 1F6AC;
+⚰️ coffin; 26B0 FE0F;
+🪦 headstone; 1FAA6;
+⚱️ funeral urn; 26B1 FE0F;
+🗿 moai; 1F5FF;
+🪧 placard; 1FAA7;
+🏧 ATM sign; 1F3E7;
+🚮 litter in bin sign; 1F6AE;
+🚰 potable water; 1F6B0;
+♿ wheelchair symbol; 267F;
+🚹 men’s room; 1F6B9;
+🚺 women’s room; 1F6BA;
+🚻 restroom; 1F6BB;
+🚼 baby symbol; 1F6BC;
+🚾 water closet; 1F6BE;
+🛂 passport control; 1F6C2;
+🛃 customs; 1F6C3;
+🛄 baggage claim; 1F6C4;
+🛅 left luggage; 1F6C5;
+⚠️ warning; 26A0 FE0F;
+🚸 children crossing; 1F6B8;
+⛔ no entry; 26D4;
+🚫 prohibited; 1F6AB;
+🚳 no bicycles; 1F6B3;
+🚭 no smoking; 1F6AD;
+🚯 no littering; 1F6AF;
+🚱 non-potable water; 1F6B1;
+🚷 no pedestrians; 1F6B7;
+📵 no mobile phones; 1F4F5;
+🔞 no one under eighteen; 1F51E;
+☢️ radioactive; 2622 FE0F;
+☣️ biohazard; 2623 FE0F;
+⬆️ up arrow; 2B06 FE0F;
+↗️ up-right arrow; 2197 FE0F;
+➡️ right arrow; 27A1 FE0F;
+↘️ down-right arrow; 2198 FE0F;
+⬇️ down arrow; 2B07 FE0F;
+↙️ down-left arrow; 2199 FE0F;
+⬅️ left arrow; 2B05 FE0F;
+↖️ up-left arrow; 2196 FE0F;
+↕️ up-down arrow; 2195 FE0F;
+↔️ left-right arrow; 2194 FE0F;
+↩️ right arrow curving left; 21A9 FE0F;
+↪️ left arrow curving right; 21AA FE0F;
+⤴️ right arrow curving up; 2934 FE0F;
+⤵️ right arrow curving down; 2935 FE0F;
+🔃 clockwise vertical arrows; 1F503;
+🔄 counterclockwise arrows button; 1F504;
+🔙 BACK arrow; 1F519;
+🔚 END arrow; 1F51A;
+🔛 ON! arrow; 1F51B;
+🔜 SOON arrow; 1F51C;
+🔝 TOP arrow; 1F51D;
+🛐 place of worship; 1F6D0;
+⚛️ atom symbol; 269B FE0F;
+🕉️ om; 1F549 FE0F;
+✡️ star of David; 2721 FE0F;
+☸️ wheel of dharma; 2638 FE0F;
+☯️ yin yang; 262F FE0F;
+✝️ latin cross; 271D FE0F;
+☦️ orthodox cross; 2626 FE0F;
+☪️ star and crescent; 262A FE0F;
+☮️ peace symbol; 262E FE0F;
+🕎 menorah; 1F54E;
+🔯 dotted six-pointed star; 1F52F;
+♈ Aries; 2648;
+♉ Taurus; 2649;
+♊ Gemini; 264A;
+♋ Cancer; 264B;
+♌ Leo; 264C;
+♍ Virgo; 264D;
+♎ Libra; 264E;
+♏ Scorpio; 264F;
+♐ Sagittarius; 2650;
+♑ Capricorn; 2651;
+♒ Aquarius; 2652;
+♓ Pisces; 2653;
+⛎ Ophiuchus; 26CE;
+🔀 shuffle tracks button; 1F500;
+🔁 repeat button; 1F501;
+🔂 repeat single button; 1F502;
+▶️ play button; 25B6 FE0F;
+⏩ fast-forward button; 23E9;
+⏭️ next track button; 23ED FE0F;
+⏯️ play or pause button; 23EF FE0F;
+◀️ reverse button; 25C0 FE0F;
+⏪ fast reverse button; 23EA;
+⏮️ last track button; 23EE FE0F;
+🔼 upwards button; 1F53C;
+⏫ fast up button; 23EB;
+🔽 downwards button; 1F53D;
+⏬ fast down button; 23EC;
+⏸️ pause button; 23F8 FE0F;
+⏹️ stop button; 23F9 FE0F;
+⏺️ record button; 23FA FE0F;
+⏏️ eject button; 23CF FE0F;
+🎦 cinema; 1F3A6;
+🔅 dim button; 1F505;
+🔆 bright button; 1F506;
+📶 antenna bars; 1F4F6;
+📳 vibration mode; 1F4F3;
+📴 mobile phone off; 1F4F4;
+♀️ female sign; 2640 FE0F;
+♂️ male sign; 2642 FE0F;
+⚧️ transgender symbol; 26A7 FE0F;
+✖️ multiply; 2716 FE0F;
+➕ plus; 2795;
+➖ minus; 2796;
+➗ divide; 2797;
+♾️ infinity; 267E FE0F;
+‼️ double exclamation mark; 203C FE0F;
+⁉️ exclamation question mark; 2049 FE0F;
+❓ question mark; 2753;
+❔ white question mark; 2754;
+❕ white exclamation mark; 2755;
+❗ exclamation mark; 2757;
+〰️ wavy dash; 3030 FE0F;
+💱 currency exchange; 1F4B1;
+💲 heavy dollar sign; 1F4B2;
+⚕️ medical symbol; 2695 FE0F;
+♻️ recycling symbol; 267B FE0F;
+⚜️ fleur-de-lis; 269C FE0F;
+🔱 trident emblem; 1F531;
+📛 name badge; 1F4DB;
+🔰 Japanese symbol for beginner; 1F530;
+⭕ hollow red circle; 2B55;
+✅ check mark button; 2705;
+☑️ check box with check; 2611 FE0F;
+✔️ check mark; 2714 FE0F;
+❌ cross mark; 274C;
+❎ cross mark button; 274E;
+➰ curly loop; 27B0;
+➿ double curly loop; 27BF;
+〽️ part alternation mark; 303D FE0F;
+✳️ eight-spoked asterisk; 2733 FE0F;
+✴️ eight-pointed star; 2734 FE0F;
+❇️ sparkle; 2747 FE0F;
+©️ copyright; 00A9 FE0F;
+®️ registered; 00AE FE0F;
+™️ trade mark; 2122 FE0F;
+#️⃣ keycap: #; 0023 FE0F 20E3;
+*️⃣ keycap: *; 002A FE0F 20E3;
+0️⃣ keycap: 0; 0030 FE0F 20E3;
+1️⃣ keycap: 1; 0031 FE0F 20E3;
+2️⃣ keycap: 2; 0032 FE0F 20E3;
+3️⃣ keycap: 3; 0033 FE0F 20E3;
+4️⃣ keycap: 4; 0034 FE0F 20E3;
+5️⃣ keycap: 5; 0035 FE0F 20E3;
+6️⃣ keycap: 6; 0036 FE0F 20E3;
+7️⃣ keycap: 7; 0037 FE0F 20E3;
+8️⃣ keycap: 8; 0038 FE0F 20E3;
+9️⃣ keycap: 9; 0039 FE0F 20E3;
+🔟 keycap: 10; 1F51F;
+🔠 input latin uppercase; 1F520;
+🔡 input latin lowercase; 1F521;
+🔢 input numbers; 1F522;
+🔣 input symbols; 1F523;
+🔤 input latin letters; 1F524;
+🅰️ A button (blood type); 1F170 FE0F;
+🆎 AB button (blood type); 1F18E;
+🅱️ B button (blood type); 1F171 FE0F;
+🆑 CL button; 1F191;
+🆒 COOL button; 1F192;
+🆓 FREE button; 1F193;
+ℹ️ information; 2139 FE0F;
+🆔 ID button; 1F194;
+Ⓜ️ circled M; 24C2 FE0F;
+🆕 NEW button; 1F195;
+🆖 NG button; 1F196;
+🅾️ O button (blood type); 1F17E FE0F;
+🆗 OK button; 1F197;
+🅿️ P button; 1F17F FE0F;
+🆘 SOS button; 1F198;
+🆙 UP! button; 1F199;
+🆚 VS button; 1F19A;
+🈁 Japanese “here” button; 1F201;
+🈂️ Japanese “service charge” button; 1F202 FE0F;
+🈷️ Japanese “monthly amount” button; 1F237 FE0F;
+🈶 Japanese “not free of charge” button; 1F236;
+🈯 Japanese “reserved” button; 1F22F;
+🉐 Japanese “bargain” button; 1F250;
+🈹 Japanese “discount” button; 1F239;
+🈚 Japanese “free of charge” button; 1F21A;
+🈲 Japanese “prohibited” button; 1F232;
+🉑 Japanese “acceptable” button; 1F251;
+🈸 Japanese “application” button; 1F238;
+🈴 Japanese “passing grade” button; 1F234;
+🈳 Japanese “vacancy” button; 1F233;
+㊗️ Japanese “congratulations” button; 3297 FE0F;
+㊙️ Japanese “secret” button; 3299 FE0F;
+🈺 Japanese “open for business” button; 1F23A;
+🈵 Japanese “no vacancy” button; 1F235;
+🔴 red circle; 1F534;
+🟠 orange circle; 1F7E0;
+🟡 yellow circle; 1F7E1;
+🟢 green circle; 1F7E2;
+🔵 blue circle; 1F535;
+🟣 purple circle; 1F7E3;
+🟤 brown circle; 1F7E4;
+⚫ black circle; 26AB;
+⚪ white circle; 26AA;
+🟥 red square; 1F7E5;
+🟧 orange square; 1F7E7;
+🟨 yellow square; 1F7E8;
+🟩 green square; 1F7E9;
+🟦 blue square; 1F7E6;
+🟪 purple square; 1F7EA;
+🟫 brown square; 1F7EB;
+⬛ black large square; 2B1B;
+⬜ white large square; 2B1C;
+◼️ black medium square; 25FC FE0F;
+◻️ white medium square; 25FB FE0F;
+◾ black medium-small square; 25FE;
+◽ white medium-small square; 25FD;
+▪️ black small square; 25AA FE0F;
+▫️ white small square; 25AB FE0F;
+🔶 large orange diamond; 1F536;
+🔷 large blue diamond; 1F537;
+🔸 small orange diamond; 1F538;
+🔹 small blue diamond; 1F539;
+🔺 red triangle pointed up; 1F53A;
+🔻 red triangle pointed down; 1F53B;
+💠 diamond with a dot; 1F4A0;
+🔘 radio button; 1F518;
+🔳 white square button; 1F533;
+🔲 black square button; 1F532;
+🏁 chequered flag; 1F3C1;
+🚩 triangular flag; 1F6A9;
+🎌 crossed flags; 1F38C;
+🏴 black flag; 1F3F4;
+🏳️ white flag; 1F3F3 FE0F;
+🇦🇨 flag: Ascension Island; 1F1E6 1F1E8;
+🇦🇩 flag: Andorra; 1F1E6 1F1E9;
+🇦🇪 flag: United Arab Emirates; 1F1E6 1F1EA;
+🇦🇫 flag: Afghanistan; 1F1E6 1F1EB;
+🇦🇬 flag: Antigua & Barbuda; 1F1E6 1F1EC;
+🇦🇮 flag: Anguilla; 1F1E6 1F1EE;
+🇦🇱 flag: Albania; 1F1E6 1F1F1;
+🇦🇲 flag: Armenia; 1F1E6 1F1F2;
+🇦🇴 flag: Angola; 1F1E6 1F1F4;
+🇦🇶 flag: Antarctica; 1F1E6 1F1F6;
+🇦🇷 flag: Argentina; 1F1E6 1F1F7;
+🇦🇸 flag: American Samoa; 1F1E6 1F1F8;
+🇦🇹 flag: Austria; 1F1E6 1F1F9;
+🇦🇺 flag: Australia; 1F1E6 1F1FA;
+🇦🇼 flag: Aruba; 1F1E6 1F1FC;
+🇦🇽 flag: Åland Islands; 1F1E6 1F1FD;
+🇦🇿 flag: Azerbaijan; 1F1E6 1F1FF;
+🇧🇦 flag: Bosnia & Herzegovina; 1F1E7 1F1E6;
+🇧🇧 flag: Barbados; 1F1E7 1F1E7;
+🇧🇩 flag: Bangladesh; 1F1E7 1F1E9;
+🇧🇪 flag: Belgium; 1F1E7 1F1EA;
+🇧🇫 flag: Burkina Faso; 1F1E7 1F1EB;
+🇧🇬 flag: Bulgaria; 1F1E7 1F1EC;
+🇧🇭 flag: Bahrain; 1F1E7 1F1ED;
+🇧🇮 flag: Burundi; 1F1E7 1F1EE;
+🇧🇯 flag: Benin; 1F1E7 1F1EF;
+🇧🇱 flag: St. Barthélemy; 1F1E7 1F1F1;
+🇧🇲 flag: Bermuda; 1F1E7 1F1F2;
+🇧🇳 flag: Brunei; 1F1E7 1F1F3;
+🇧🇴 flag: Bolivia; 1F1E7 1F1F4;
+🇧🇶 flag: Caribbean Netherlands; 1F1E7 1F1F6;
+🇧🇷 flag: Brazil; 1F1E7 1F1F7;
+🇧🇸 flag: Bahamas; 1F1E7 1F1F8;
+🇧🇹 flag: Bhutan; 1F1E7 1F1F9;
+🇧🇻 flag: Bouvet Island; 1F1E7 1F1FB;
+🇧🇼 flag: Botswana; 1F1E7 1F1FC;
+🇧🇾 flag: Belarus; 1F1E7 1F1FE;
+🇧🇿 flag: Belize; 1F1E7 1F1FF;
+🇨🇦 flag: Canada; 1F1E8 1F1E6;
+🇨🇨 flag: Cocos (Keeling) Islands; 1F1E8 1F1E8;
+🇨🇩 flag: Congo - Kinshasa; 1F1E8 1F1E9;
+🇨🇫 flag: Central African Republic; 1F1E8 1F1EB;
+🇨🇬 flag: Congo - Brazzaville; 1F1E8 1F1EC;
+🇨🇭 flag: Switzerland; 1F1E8 1F1ED;
+🇨🇮 flag: Côte d’Ivoire; 1F1E8 1F1EE;
+🇨🇰 flag: Cook Islands; 1F1E8 1F1F0;
+🇨🇱 flag: Chile; 1F1E8 1F1F1;
+🇨🇲 flag: Cameroon; 1F1E8 1F1F2;
+🇨🇳 flag: China; 1F1E8 1F1F3;
+🇨🇴 flag: Colombia; 1F1E8 1F1F4;
+🇨🇵 flag: Clipperton Island; 1F1E8 1F1F5;
+🇨🇷 flag: Costa Rica; 1F1E8 1F1F7;
+🇨🇺 flag: Cuba; 1F1E8 1F1FA;
+🇨🇻 flag: Cape Verde; 1F1E8 1F1FB;
+🇨🇼 flag: Curaçao; 1F1E8 1F1FC;
+🇨🇽 flag: Christmas Island; 1F1E8 1F1FD;
+🇨🇾 flag: Cyprus; 1F1E8 1F1FE;
+🇨🇿 flag: Czechia; 1F1E8 1F1FF;
+🇩🇪 flag: Germany; 1F1E9 1F1EA;
+🇩🇬 flag: Diego Garcia; 1F1E9 1F1EC;
+🇩🇯 flag: Djibouti; 1F1E9 1F1EF;
+🇩🇰 flag: Denmark; 1F1E9 1F1F0;
+🇩🇲 flag: Dominica; 1F1E9 1F1F2;
+🇩🇴 flag: Dominican Republic; 1F1E9 1F1F4;
+🇩🇿 flag: Algeria; 1F1E9 1F1FF;
+🇪🇦 flag: Ceuta & Melilla; 1F1EA 1F1E6;
+🇪🇨 flag: Ecuador; 1F1EA 1F1E8;
+🇪🇪 flag: Estonia; 1F1EA 1F1EA;
+🇪🇬 flag: Egypt; 1F1EA 1F1EC;
+🇪🇭 flag: Western Sahara; 1F1EA 1F1ED;
+🇪🇷 flag: Eritrea; 1F1EA 1F1F7;
+🇪🇸 flag: Spain; 1F1EA 1F1F8;
+🇪🇹 flag: Ethiopia; 1F1EA 1F1F9;
+🇪🇺 flag: European Union; 1F1EA 1F1FA;
+🇫🇮 flag: Finland; 1F1EB 1F1EE;
+🇫🇯 flag: Fiji; 1F1EB 1F1EF;
+🇫🇰 flag: Falkland Islands; 1F1EB 1F1F0;
+🇫🇲 flag: Micronesia; 1F1EB 1F1F2;
+🇫🇴 flag: Faroe Islands; 1F1EB 1F1F4;
+🇫🇷 flag: France; 1F1EB 1F1F7;
+🇬🇦 flag: Gabon; 1F1EC 1F1E6;
+🇬🇧 flag: United Kingdom; 1F1EC 1F1E7;
+🇬🇩 flag: Grenada; 1F1EC 1F1E9;
+🇬🇪 flag: Georgia; 1F1EC 1F1EA;
+🇬🇫 flag: French Guiana; 1F1EC 1F1EB;
+🇬🇬 flag: Guernsey; 1F1EC 1F1EC;
+🇬🇭 flag: Ghana; 1F1EC 1F1ED;
+🇬🇮 flag: Gibraltar; 1F1EC 1F1EE;
+🇬🇱 flag: Greenland; 1F1EC 1F1F1;
+🇬🇲 flag: Gambia; 1F1EC 1F1F2;
+🇬🇳 flag: Guinea; 1F1EC 1F1F3;
+🇬🇵 flag: Guadeloupe; 1F1EC 1F1F5;
+🇬🇶 flag: Equatorial Guinea; 1F1EC 1F1F6;
+🇬🇷 flag: Greece; 1F1EC 1F1F7;
+🇬🇸 flag: South Georgia & South Sandwich Islands; 1F1EC 1F1F8;
+🇬🇹 flag: Guatemala; 1F1EC 1F1F9;
+🇬🇺 flag: Guam; 1F1EC 1F1FA;
+🇬🇼 flag: Guinea-Bissau; 1F1EC 1F1FC;
+🇬🇾 flag: Guyana; 1F1EC 1F1FE;
+🇭🇰 flag: Hong Kong SAR China; 1F1ED 1F1F0;
+🇭🇲 flag: Heard & McDonald Islands; 1F1ED 1F1F2;
+🇭🇳 flag: Honduras; 1F1ED 1F1F3;
+🇭🇷 flag: Croatia; 1F1ED 1F1F7;
+🇭🇹 flag: Haiti; 1F1ED 1F1F9;
+🇭🇺 flag: Hungary; 1F1ED 1F1FA;
+🇮🇨 flag: Canary Islands; 1F1EE 1F1E8;
+🇮🇩 flag: Indonesia; 1F1EE 1F1E9;
+🇮🇪 flag: Ireland; 1F1EE 1F1EA;
+🇮🇱 flag: Israel; 1F1EE 1F1F1;
+🇮🇲 flag: Isle of Man; 1F1EE 1F1F2;
+🇮🇳 flag: India; 1F1EE 1F1F3;
+🇮🇴 flag: British Indian Ocean Territory; 1F1EE 1F1F4;
+🇮🇶 flag: Iraq; 1F1EE 1F1F6;
+🇮🇷 flag: Iran; 1F1EE 1F1F7;
+🇮🇸 flag: Iceland; 1F1EE 1F1F8;
+🇮🇹 flag: Italy; 1F1EE 1F1F9;
+🇯🇪 flag: Jersey; 1F1EF 1F1EA;
+🇯🇲 flag: Jamaica; 1F1EF 1F1F2;
+🇯🇴 flag: Jordan; 1F1EF 1F1F4;
+🇯🇵 flag: Japan; 1F1EF 1F1F5;
+🇰🇪 flag: Kenya; 1F1F0 1F1EA;
+🇰🇬 flag: Kyrgyzstan; 1F1F0 1F1EC;
+🇰🇭 flag: Cambodia; 1F1F0 1F1ED;
+🇰🇮 flag: Kiribati; 1F1F0 1F1EE;
+🇰🇲 flag: Comoros; 1F1F0 1F1F2;
+🇰🇳 flag: St. Kitts & Nevis; 1F1F0 1F1F3;
+🇰🇵 flag: North Korea; 1F1F0 1F1F5;
+🇰🇷 flag: South Korea; 1F1F0 1F1F7;
+🇰🇼 flag: Kuwait; 1F1F0 1F1FC;
+🇰🇾 flag: Cayman Islands; 1F1F0 1F1FE;
+🇰🇿 flag: Kazakhstan; 1F1F0 1F1FF;
+🇱🇦 flag: Laos; 1F1F1 1F1E6;
+🇱🇧 flag: Lebanon; 1F1F1 1F1E7;
+🇱🇨 flag: St. Lucia; 1F1F1 1F1E8;
+🇱🇮 flag: Liechtenstein; 1F1F1 1F1EE;
+🇱🇰 flag: Sri Lanka; 1F1F1 1F1F0;
+🇱🇷 flag: Liberia; 1F1F1 1F1F7;
+🇱🇸 flag: Lesotho; 1F1F1 1F1F8;
+🇱🇹 flag: Lithuania; 1F1F1 1F1F9;
+🇱🇺 flag: Luxembourg; 1F1F1 1F1FA;
+🇱🇻 flag: Latvia; 1F1F1 1F1FB;
+🇱🇾 flag: Libya; 1F1F1 1F1FE;
+🇲🇦 flag: Morocco; 1F1F2 1F1E6;
+🇲🇨 flag: Monaco; 1F1F2 1F1E8;
+🇲🇩 flag: Moldova; 1F1F2 1F1E9;
+🇲🇪 flag: Montenegro; 1F1F2 1F1EA;
+🇲🇫 flag: St. Martin; 1F1F2 1F1EB;
+🇲🇬 flag: Madagascar; 1F1F2 1F1EC;
+🇲🇭 flag: Marshall Islands; 1F1F2 1F1ED;
+🇲🇰 flag: North Macedonia; 1F1F2 1F1F0;
+🇲🇱 flag: Mali; 1F1F2 1F1F1;
+🇲🇲 flag: Myanmar (Burma); 1F1F2 1F1F2;
+🇲🇳 flag: Mongolia; 1F1F2 1F1F3;
+🇲🇴 flag: Macao SAR China; 1F1F2 1F1F4;
+🇲🇵 flag: Northern Mariana Islands; 1F1F2 1F1F5;
+🇲🇶 flag: Martinique; 1F1F2 1F1F6;
+🇲🇷 flag: Mauritania; 1F1F2 1F1F7;
+🇲🇸 flag: Montserrat; 1F1F2 1F1F8;
+🇲🇹 flag: Malta; 1F1F2 1F1F9;
+🇲🇺 flag: Mauritius; 1F1F2 1F1FA;
+🇲🇻 flag: Maldives; 1F1F2 1F1FB;
+🇲🇼 flag: Malawi; 1F1F2 1F1FC;
+🇲🇽 flag: Mexico; 1F1F2 1F1FD;
+🇲🇾 flag: Malaysia; 1F1F2 1F1FE;
+🇲🇿 flag: Mozambique; 1F1F2 1F1FF;
+🇳🇦 flag: Namibia; 1F1F3 1F1E6;
+🇳🇨 flag: New Caledonia; 1F1F3 1F1E8;
+🇳🇪 flag: Niger; 1F1F3 1F1EA;
+🇳🇫 flag: Norfolk Island; 1F1F3 1F1EB;
+🇳🇬 flag: Nigeria; 1F1F3 1F1EC;
+🇳🇮 flag: Nicaragua; 1F1F3 1F1EE;
+🇳🇱 flag: Netherlands; 1F1F3 1F1F1;
+🇳🇴 flag: Norway; 1F1F3 1F1F4;
+🇳🇵 flag: Nepal; 1F1F3 1F1F5;
+🇳🇷 flag: Nauru; 1F1F3 1F1F7;
+🇳🇺 flag: Niue; 1F1F3 1F1FA;
+🇳🇿 flag: New Zealand; 1F1F3 1F1FF;
+🇴🇲 flag: Oman; 1F1F4 1F1F2;
+🇵🇦 flag: Panama; 1F1F5 1F1E6;
+🇵🇪 flag: Peru; 1F1F5 1F1EA;
+🇵🇫 flag: French Polynesia; 1F1F5 1F1EB;
+🇵🇬 flag: Papua New Guinea; 1F1F5 1F1EC;
+🇵🇭 flag: Philippines; 1F1F5 1F1ED;
+🇵🇰 flag: Pakistan; 1F1F5 1F1F0;
+🇵🇱 flag: Poland; 1F1F5 1F1F1;
+🇵🇲 flag: St. Pierre & Miquelon; 1F1F5 1F1F2;
+🇵🇳 flag: Pitcairn Islands; 1F1F5 1F1F3;
+🇵🇷 flag: Puerto Rico; 1F1F5 1F1F7;
+🇵🇸 flag: Palestinian Territories; 1F1F5 1F1F8;
+🇵🇹 flag: Portugal; 1F1F5 1F1F9;
+🇵🇼 flag: Palau; 1F1F5 1F1FC;
+🇵🇾 flag: Paraguay; 1F1F5 1F1FE;
+🇶🇦 flag: Qatar; 1F1F6 1F1E6;
+🇷🇪 flag: Réunion; 1F1F7 1F1EA;
+🇷🇴 flag: Romania; 1F1F7 1F1F4;
+🇷🇸 flag: Serbia; 1F1F7 1F1F8;
+🇷🇺 flag: Russia; 1F1F7 1F1FA;
+🇷🇼 flag: Rwanda; 1F1F7 1F1FC;
+🇸🇦 flag: Saudi Arabia; 1F1F8 1F1E6;
+🇸🇧 flag: Solomon Islands; 1F1F8 1F1E7;
+🇸🇨 flag: Seychelles; 1F1F8 1F1E8;
+🇸🇩 flag: Sudan; 1F1F8 1F1E9;
+🇸🇪 flag: Sweden; 1F1F8 1F1EA;
+🇸🇬 flag: Singapore; 1F1F8 1F1EC;
+🇸🇭 flag: St. Helena; 1F1F8 1F1ED;
+🇸🇮 flag: Slovenia; 1F1F8 1F1EE;
+🇸🇯 flag: Svalbard & Jan Mayen; 1F1F8 1F1EF;
+🇸🇰 flag: Slovakia; 1F1F8 1F1F0;
+🇸🇱 flag: Sierra Leone; 1F1F8 1F1F1;
+🇸🇲 flag: San Marino; 1F1F8 1F1F2;
+🇸🇳 flag: Senegal; 1F1F8 1F1F3;
+🇸🇴 flag: Somalia; 1F1F8 1F1F4;
+🇸🇷 flag: Suriname; 1F1F8 1F1F7;
+🇸🇸 flag: South Sudan; 1F1F8 1F1F8;
+🇸🇹 flag: São Tomé & Príncipe; 1F1F8 1F1F9;
+🇸🇻 flag: El Salvador; 1F1F8 1F1FB;
+🇸🇽 flag: Sint Maarten; 1F1F8 1F1FD;
+🇸🇾 flag: Syria; 1F1F8 1F1FE;
+🇸🇿 flag: Eswatini; 1F1F8 1F1FF;
+🇹🇦 flag: Tristan da Cunha; 1F1F9 1F1E6;
+🇹🇨 flag: Turks & Caicos Islands; 1F1F9 1F1E8;
+🇹🇩 flag: Chad; 1F1F9 1F1E9;
+🇹🇫 flag: French Southern Territories; 1F1F9 1F1EB;
+🇹🇬 flag: Togo; 1F1F9 1F1EC;
+🇹🇭 flag: Thailand; 1F1F9 1F1ED;
+🇹🇯 flag: Tajikistan; 1F1F9 1F1EF;
+🇹🇰 flag: Tokelau; 1F1F9 1F1F0;
+🇹🇱 flag: Timor-Leste; 1F1F9 1F1F1;
+🇹🇲 flag: Turkmenistan; 1F1F9 1F1F2;
+🇹🇳 flag: Tunisia; 1F1F9 1F1F3;
+🇹🇴 flag: Tonga; 1F1F9 1F1F4;
+🇹🇷 flag: Turkey; 1F1F9 1F1F7;
+🇹🇹 flag: Trinidad & Tobago; 1F1F9 1F1F9;
+🇹🇻 flag: Tuvalu; 1F1F9 1F1FB;
+🇹🇼 flag: Taiwan; 1F1F9 1F1FC;
+🇹🇿 flag: Tanzania; 1F1F9 1F1FF;
+🇺🇦 flag: Ukraine; 1F1FA 1F1E6;
+🇺🇬 flag: Uganda; 1F1FA 1F1EC;
+🇺🇲 flag: U.S. Outlying Islands; 1F1FA 1F1F2;
+🇺🇳 flag: United Nations; 1F1FA 1F1F3;
+🇺🇸 flag: United States; 1F1FA 1F1F8;
+🇺🇾 flag: Uruguay; 1F1FA 1F1FE;
+🇺🇿 flag: Uzbekistan; 1F1FA 1F1FF;
+🇻🇦 flag: Vatican City; 1F1FB 1F1E6;
+🇻🇨 flag: St. Vincent & Grenadines; 1F1FB 1F1E8;
+🇻🇪 flag: Venezuela; 1F1FB 1F1EA;
+🇻🇬 flag: British Virgin Islands; 1F1FB 1F1EC;
+🇻🇮 flag: U.S. Virgin Islands; 1F1FB 1F1EE;
+🇻🇳 flag: Vietnam; 1F1FB 1F1F3;
+🇻🇺 flag: Vanuatu; 1F1FB 1F1FA;
+🇼🇫 flag: Wallis & Futuna; 1F1FC 1F1EB;
+🇼🇸 flag: Samoa; 1F1FC 1F1F8;
+🇽🇰 flag: Kosovo; 1F1FD 1F1F0;
+🇾🇪 flag: Yemen; 1F1FE 1F1EA;
+🇾🇹 flag: Mayotte; 1F1FE 1F1F9;
+🇿🇦 flag: South Africa; 1F1FF 1F1E6;
+🇿🇲 flag: Zambia; 1F1FF 1F1F2;
+🇿🇼 flag: Zimbabwe; 1F1FF 1F1FC;
+🏴󠁧󠁢󠁥󠁮󠁧󠁿 flag: England; 1F3F4725E7F;
+🏴󠁧󠁢󠁳󠁣󠁴󠁿 flag: Scotland; 1F3F472334F;
+🏴󠁧󠁢󠁷󠁬󠁳󠁿 flag: Wales; 1F3F4727C3F;
diff --git a/dotfiles/system/.local/share/fonts/AppleColorEmoji.ttf b/dotfiles/system/.local/share/fonts/AppleColorEmoji.ttf
new file mode 100644
index 0000000..a2410e0
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/AppleColorEmoji.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.otf b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.otf
new file mode 100644
index 0000000..bfbf049
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.ttf b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.ttf
new file mode 100644
index 0000000..8360c44
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff
new file mode 100644
index 0000000..1292f0c
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff2 b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff2
new file mode 100644
index 0000000..2ca7854
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Bold.woff2
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.otf b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.otf
new file mode 100644
index 0000000..b516668
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.ttf b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.ttf
new file mode 100644
index 0000000..0c27a23
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff
new file mode 100644
index 0000000..01a3446
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff2 b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff2
new file mode 100644
index 0000000..1ef6d20
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-BoldItalic.woff2
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.otf b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.otf
new file mode 100644
index 0000000..245b152
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.ttf b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.ttf
new file mode 100644
index 0000000..9e710b8
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff
new file mode 100644
index 0000000..75232cb
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff2 b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff2
new file mode 100644
index 0000000..8ac24dd
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Italic.woff2
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.otf b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.otf
new file mode 100644
index 0000000..5ee83c4
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.ttf b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.ttf
new file mode 100644
index 0000000..9821fc4
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff
new file mode 100644
index 0000000..459e5b9
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff2 b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff2
new file mode 100644
index 0000000..6b8f29d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMono-Regular.woff2
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.ttf b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.ttf
new file mode 100644
index 0000000..f960162
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff
new file mode 100644
index 0000000..af819a7
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff2 b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff2
new file mode 100644
index 0000000..cb3775e
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Italic.woff2
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.ttf b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.ttf
new file mode 100644
index 0000000..51f0159
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff
new file mode 100644
index 0000000..8bda931
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff2 b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff2
new file mode 100644
index 0000000..1c14904
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/BerkeleyMonoVariable-Regular.woff2
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-Bold.otf b/dotfiles/system/.local/share/fonts/CartographCF-Bold.otf
new file mode 100644
index 0000000..0bf7258
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-Bold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-BoldItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-BoldItalic.otf
new file mode 100644
index 0000000..0f1d2ce
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-BoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-DemiBold.otf b/dotfiles/system/.local/share/fonts/CartographCF-DemiBold.otf
new file mode 100644
index 0000000..e144f18
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-DemiBold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-DemiBoldItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-DemiBoldItalic.otf
new file mode 100644
index 0000000..b8cbbc3
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-DemiBoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-ExtraBold.otf b/dotfiles/system/.local/share/fonts/CartographCF-ExtraBold.otf
new file mode 100644
index 0000000..a49a239
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-ExtraBold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-ExtraBoldItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-ExtraBoldItalic.otf
new file mode 100644
index 0000000..7c44037
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-ExtraBoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-ExtraLight.otf b/dotfiles/system/.local/share/fonts/CartographCF-ExtraLight.otf
new file mode 100644
index 0000000..16b9638
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-ExtraLight.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-ExtraLightItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-ExtraLightItalic.otf
new file mode 100644
index 0000000..3764561
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-ExtraLightItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-Heavy.otf b/dotfiles/system/.local/share/fonts/CartographCF-Heavy.otf
new file mode 100644
index 0000000..7ff45c5
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-Heavy.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-HeavyItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-HeavyItalic.otf
new file mode 100644
index 0000000..e6ba640
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-HeavyItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-Light.otf b/dotfiles/system/.local/share/fonts/CartographCF-Light.otf
new file mode 100644
index 0000000..f2193f7
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-Light.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-LightItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-LightItalic.otf
new file mode 100644
index 0000000..deb466a
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-LightItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-Regular.otf b/dotfiles/system/.local/share/fonts/CartographCF-Regular.otf
new file mode 100644
index 0000000..1169d42
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-RegularItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-RegularItalic.otf
new file mode 100644
index 0000000..d03e213
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-RegularItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-Thin.otf b/dotfiles/system/.local/share/fonts/CartographCF-Thin.otf
new file mode 100644
index 0000000..e3a1a97
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-Thin.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CartographCF-ThinItalic.otf b/dotfiles/system/.local/share/fonts/CartographCF-ThinItalic.otf
new file mode 100644
index 0000000..5fcc062
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CartographCF-ThinItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CodeliaLigatures-Bold.otf b/dotfiles/system/.local/share/fonts/CodeliaLigatures-Bold.otf
new file mode 100644
index 0000000..7117788
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CodeliaLigatures-Bold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CodeliaLigatures-BoldItalic.otf b/dotfiles/system/.local/share/fonts/CodeliaLigatures-BoldItalic.otf
new file mode 100644
index 0000000..f4836e8
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CodeliaLigatures-BoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CodeliaLigatures-Italic.otf b/dotfiles/system/.local/share/fonts/CodeliaLigatures-Italic.otf
new file mode 100644
index 0000000..7471db0
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CodeliaLigatures-Italic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/CodeliaLigatures-Regular.otf b/dotfiles/system/.local/share/fonts/CodeliaLigatures-Regular.otf
new file mode 100644
index 0000000..275774c
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/CodeliaLigatures-Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Bold.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Bold.otf
new file mode 100644
index 0000000..30661a2
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Bold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-BoldItalic.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-BoldItalic.otf
new file mode 100644
index 0000000..a906291
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-BoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Italic.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Italic.otf
new file mode 100644
index 0000000..7034019
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Italic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Light.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Light.otf
new file mode 100644
index 0000000..fea2e31
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Light.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-LightItalic.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-LightItalic.otf
new file mode 100644
index 0000000..40c0897
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-LightItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Medium.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Medium.otf
new file mode 100644
index 0000000..33f894a
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Medium.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-MediumItalic.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-MediumItalic.otf
new file mode 100644
index 0000000..12ce25a
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-MediumItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Regular.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Regular.otf
new file mode 100644
index 0000000..26bd4a3
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-SBIta.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-SBIta.otf
new file mode 100644
index 0000000..a382373
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-SBIta.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Semibold.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Semibold.otf
new file mode 100644
index 0000000..8598353
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Semibold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Thin.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Thin.otf
new file mode 100644
index 0000000..b3c1fb7
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-Thin.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-ThinItalic.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-ThinItalic.otf
new file mode 100644
index 0000000..af96f80
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-ThinItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-ULIta.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-ULIta.otf
new file mode 100644
index 0000000..42bcb59
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-ULIta.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/ComicCodeLigatures-UltraLight.otf b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-UltraLight.otf
new file mode 100644
index 0000000..0030307
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/ComicCodeLigatures-UltraLight.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Courier 10 Pitch Regular.otf b/dotfiles/system/.local/share/fonts/Courier 10 Pitch Regular.otf
new file mode 100644
index 0000000..c2d294d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Courier 10 Pitch Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/MERIFONT.TTF b/dotfiles/system/.local/share/fonts/MERIFONT.TTF
new file mode 100644
index 0000000..66b58d8
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/MERIFONT.TTF
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-Black.ttf b/dotfiles/system/.local/share/fonts/Merriweather-Black.ttf
new file mode 100644
index 0000000..50c3b33
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-Black.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-BlackItalic.ttf b/dotfiles/system/.local/share/fonts/Merriweather-BlackItalic.ttf
new file mode 100644
index 0000000..4879aba
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-BlackItalic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-Bold.ttf b/dotfiles/system/.local/share/fonts/Merriweather-Bold.ttf
new file mode 100644
index 0000000..3e10e02
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-Bold.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-BoldItalic.ttf b/dotfiles/system/.local/share/fonts/Merriweather-BoldItalic.ttf
new file mode 100644
index 0000000..5b9d0ec
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-BoldItalic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-Italic.ttf b/dotfiles/system/.local/share/fonts/Merriweather-Italic.ttf
new file mode 100644
index 0000000..8e9d03d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-Italic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-Light.ttf b/dotfiles/system/.local/share/fonts/Merriweather-Light.ttf
new file mode 100644
index 0000000..034ef03
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-Light.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-LightItalic.ttf b/dotfiles/system/.local/share/fonts/Merriweather-LightItalic.ttf
new file mode 100644
index 0000000..4d19550
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-LightItalic.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/Merriweather-Regular.ttf b/dotfiles/system/.local/share/fonts/Merriweather-Regular.ttf
new file mode 100644
index 0000000..3fecc77
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/Merriweather-Regular.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/MonoLisa-Bold.otf b/dotfiles/system/.local/share/fonts/MonoLisa-Bold.otf
new file mode 100644
index 0000000..0c21d71
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/MonoLisa-Bold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/MonoLisa-BoldItalic.otf b/dotfiles/system/.local/share/fonts/MonoLisa-BoldItalic.otf
new file mode 100644
index 0000000..8b39455
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/MonoLisa-BoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/MonoLisa-Regular.otf b/dotfiles/system/.local/share/fonts/MonoLisa-Regular.otf
new file mode 100644
index 0000000..80c8b4d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/MonoLisa-Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/MonoLisa-RegularItalic.otf b/dotfiles/system/.local/share/fonts/MonoLisa-RegularItalic.otf
new file mode 100644
index 0000000..140f54f
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/MonoLisa-RegularItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Bold.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Bold.otf
new file mode 100644
index 0000000..64b3a04
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Bold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-BoldItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-BoldItalic.otf
new file mode 100644
index 0000000..6a58baf
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-BoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBold.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBold.otf
new file mode 100644
index 0000000..738852d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBoldItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBoldItalic.otf
new file mode 100644
index 0000000..757150f
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-DemiBoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBold.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBold.otf
new file mode 100644
index 0000000..593b9cb
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBold.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBoldItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBoldItalic.otf
new file mode 100644
index 0000000..1c5437c
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-ExtBoldItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Heavy.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Heavy.otf
new file mode 100644
index 0000000..34c311d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Heavy.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-HeavyItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-HeavyItalic.otf
new file mode 100644
index 0000000..cf02929
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-HeavyItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Light.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Light.otf
new file mode 100644
index 0000000..68342b6
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Light.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-LightItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-LightItalic.otf
new file mode 100644
index 0000000..9018210
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-LightItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Medium.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Medium.otf
new file mode 100644
index 0000000..24e2f74
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Medium.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-MediumItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-MediumItalic.otf
new file mode 100644
index 0000000..032d5e5
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-MediumItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Regular.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Regular.otf
new file mode 100644
index 0000000..6e80c44
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-Regular.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/NovaletraSerifCF-RegularItalic.otf b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-RegularItalic.otf
new file mode 100644
index 0000000..a35359d
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/NovaletraSerifCF-RegularItalic.otf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProB_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProB_09.ttf
new file mode 100644
index 0000000..26340c3
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProB_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProB_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProB_liga_09.ttf
new file mode 100644
index 0000000..aee6e52
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProB_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProI_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProI_09.ttf
new file mode 100644
index 0000000..c5ea5a8
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProI_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProI_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProI_liga_09.ttf
new file mode 100644
index 0000000..0c8b519
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProI_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProR_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProR_09.ttf
new file mode 100644
index 0000000..8513a70
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProR_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProR_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProR_liga_09.ttf
new file mode 100644
index 0000000..2688b16
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProR_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProZ_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProZ_09.ttf
new file mode 100644
index 0000000..227ac44
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProZ_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataProZ_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataProZ_liga_09.ttf
new file mode 100644
index 0000000..9461300
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataProZ_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_09.ttf
new file mode 100644
index 0000000..dad7fb6
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_liga_09.ttf
new file mode 100644
index 0000000..29c2499
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_B_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_09.ttf
new file mode 100644
index 0000000..5ffa058
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_liga_09.ttf
new file mode 100644
index 0000000..1c23d01
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_I_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_09.ttf
new file mode 100644
index 0000000..c2d7bb5
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_liga_09.ttf
new file mode 100644
index 0000000..11af2e7
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_R_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_09.ttf
new file mode 100644
index 0000000..7a0b72b
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_liga_09.ttf b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_liga_09.ttf
new file mode 100644
index 0000000..2cf4ceb
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/PragmataPro_Mono_Z_liga_09.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/fonts/all-the-icons.ttf b/dotfiles/system/.local/share/fonts/all-the-icons.ttf
new file mode 100644
index 0000000..634d48e
--- /dev/null
+++ b/dotfiles/system/.local/share/fonts/all-the-icons.ttf
Binary files differ
diff --git a/dotfiles/system/.local/share/thequestionconcerningtechnology.txt b/dotfiles/system/.local/share/thequestionconcerningtechnology.txt
new file mode 100644
index 0000000..3d33ac7
--- /dev/null
+++ b/dotfiles/system/.local/share/thequestionconcerningtechnology.txt
@@ -0,0 +1,180 @@
+The Question Concerning Technology
+== Martin Heidegger ==
+
+In what follows we shall be questioning concerning technology. Questioning builds a way. We would be advised, therefore, above all to pay heed to the way, and not to fix our attention on isolated sentences and topics. The way is a way of thinking. All ways of thinking, more or less perceptibly, lead through language in a manner that is extraordinary. We shall be questioning concerning technology, and in so doing we should like to prepare a free relationship to it. The relationship will be free if it opens our human existence to the essence of technology. When we can respond to this essence, we shall be able to experience the technological within its own bounds.
+
+Technology is not equivalent to the essence of technology. When we are seeking the essence of “tree,” we have to become aware that that which pervades every tree, as tree, is not itself a tree that can be encountered among all the other trees. Likewise, the essence of technology is by no means anything technological. Thus we shall never experience our relationship to the essence of technology so long as we merely conceive and push forward the technological, put up with it, or evade it. Everywhere we remain unfree and chained to technology, whether we passionately affirm or deny it. But we are delivered over to it in the worst possible way when we regard it as something neutral; for this conception of it, to which today we particularly like to do homage, makes us utterly blind to the essence of technology.
+
+According to ancient doctrine, the essence of a thing is considered to be what the thing is. We ask the question concerning technology when we ask what it is. Everyone knows the two statements that answer our question. One says: Technology is a means to an end. The other says: Technology is a human activity. The two definitions of technology belong together. For to posit ends and procure and utilize the means to them is a human activity. The manufacture and utilization of equipment, tools, and machines, the manufactured and used things themselves, and the needs and ends that they serve, all belong to what technology is. The whole complex of these contrivances is technology. Technology itself is a contrivance, or, in Latin, an instrumentum.
+
+The current conception of technology, according to which it is a means and a human activity, can therefore be called the instrumental and anthropological definition of technology. Who would ever deny that it is correct? It is in obvious conformity with what we are envisioning when we talk about technology. The instrumental definition of technology is indeed so uncannily correct that it even holds for modern technology, of which, in other respects, we maintain with some justification that it is, in contrast to the older handwork technology, something completely different and therefore new. Even the power plant with its turbines and generators is a manmade means to an end established by man. Even the jet aircraft and the high-frequency apparatus are means to ends. A radar station is of course less simple than a weather vane. To be sure, the construction of a high-frequency apparatus requires the interlocking of various processes of technical-industrial production. And certainly a sawmill in a secluded valley of the Black Forest is a primitive means compared with the hydroelectric plant in the Rhine River.
+
+But this much remains correct: modern technology too is a means to an end. That is why the instrumental conception of technology conditions every attempt to bring man into the right relation to technology. Everything depends on our manipulating technology in the proper manner as a means. We will, as we say, “get” technology “spiritually in hand.” We will master it. The will to mastery becomes all the more urgent the more technology threatens to slip from human control.
+
+But suppose now that technology were no mere means, how would it stand with the will to master it? Yet we said, did we not, that the instrumental definition of technology is correct? To be sure. The correct always fixes upon something pertinent in whatever is under consideration. However, in order to be correct, this fixing by no means needs to uncover the thing in question in its essence. Only at the point where such an uncovering happens does the true come to pass. For that reason the merely correct is not yet the true. Only the true brings us into a free relationship with that which concerns us from out of its essence. Accordingly, the correct instrumental definition of technology still does not show us technology’s essence.
+
+In order that we may arrive at this, or at least come close to it, we must seek the true by way of the correct. We must ask: What is the instrumental itself? Within what do such things as means and end belong? A means is that whereby something is effected and thus attained. Whatever has an effect as its consequence is called a cause. But not only that by means of which something else is effected is a cause. The end in keeping with which the kind of means to be used is determined is also considered a cause. Wherever ends are pursued and means are employed, wherever instrumentality reigns, there reigns causality.
+
+For centuries philosophy has taught that there are four causes: (1) the causa materialis, the material, the matter out of which, for example, a silver chalice is made; (2) the causa formalis, the form, the shape into which the material enters; (3) the causa finalis, the end, for example, the sacrificial rite in relation to which the chalice required is determined as to its form and matter; and (4) the causa efficiens, which brings about the effect that is the finished, actual chalice, in this instance, the silversmith. What technology is, when represented as a means, discloses itself when we trace instrumentality back to fourfold causality.
+
+But suppose that causality, for its part, is veiled in darkness with respect to what it is? Certainly for centuries we have acted as though the doctrine of the four causes had fallen from heaven as a truth as clear as daylight. But it might be that the time has come to ask, Why are there just four causes? In relation to the aforementioned four, what does “cause” really mean? From whence does it come that the causal character of the four causes is so unifiedly determined that they belong together?
+
+So long as we do not allow ourselves to go into these questions, causality, and with it instrumentality, and with the latter the accepted definition of technology, remain obscure and groundless.
+
+For a long time we have been accustomed to representing cause as that which brings something about. In this connection, to bring about means to obtain results, effects. The causa efficiens, but one among the four causes, sets the standard for all causality. This goes so far that we no longer even count the causa finalis, telic finality, as causality. Causa, casus, belongs to the verb cadere, “to fall,” and means that which brings it about that something falls out as a result in such and such a way. The doctrine of the four causes goes back to Aristotle. But everything that later ages seek in Greek thought under the conception and rubric “causality,” in the realm of Greek thought and for Greek thought per se has simply nothing at all to do with bringing about and effecting. What we call cause [Ursache] and the Romans call causa is called aition by the Greeks, that to which something else is indebted [das, was ein anderes verschuldet].
+
+The four causes are the ways, all belonging at once to each other, of being responsible for something else. An example can clarify this.
+
+Silver is that out of which the silver chalice is made. As this matter (hyle), it is co-responsible for the chalice. The chalice is indebted to, that is, owes thanks to, the silver for that out of which it consists. But the sacrificial vessel is indebted not only to the silver. As a chalice, that which is indebted to the silver appears in the aspect of a chalice and not in that of a brooch or a ring. Thus the sacrificial vessel is at the same time indebted to the aspect (eidos) of chaliceness. Both the silver into which the aspect is admitted as chalice and the aspect in which the silver appears are in their respective ways co-responsible for the sacrificial vessel.
+
+But there remains yet a third that is above all responsible for the sacrificial vessel. It is that which in advance confines the chalice within the realm of consecration and bestowal. Through this the chalice is circumscribed as sacrificial vessel. Circumscribing gives bounds to the thing. With the bounds the thing does not stop; rather from out of them it begins to be what, after production, it will be. That which gives bounds, that which completes, in this sense is called in Greek telos, which is all too often translated as “aim” or “purpose,” and so misinterpreted. The telos is responsible for what as matter and for what as aspect are together co-responsible for the sacrificial vessel.
+
+Finally there is a fourth participant in the responsibility for the finished sacrificial vessel’s lying before us ready for use, that is, the silversmith — but not at all because he, in working, brings about the finished sacrificial chalice as if it were the effect of a making; the silversmith is not a causa efficiens.
+
+The Aristotelian doctrine neither knows the cause that is named by this term nor uses a Greek word that would correspond to it. The silversmith considers carefully and gathers together the three aforementioned ways of being responsible and indebted. To consider carefully [überlegen] is in Greek legein, logos. Legein is rooted in apophainesthai, to bring forward into appearance. The silversmith is co-responsible as that from whence the sacrificial vessel’s bringing forth and resting-in-self take and retain their first departure. The three previously mentioned ways of being responsible owe thanks to the pondering of the silversmith for the “that” and the “how” of their coming into appearance and into play for the production of the sacrificial vessel.
+
+Thus four ways of being responsible hold sway in the sacrificial vessel that lies ready before us. They differ from one another, yet they belong together. What unites them from the beginning? In what does this playing in unison of the four ways of being responsible play? What is the source of the unity of the four causes? What, after all, does this owing and being responsible mean, thought as the Greeks thought it?
+
+Today we are too easily inclined either to understand being responsible and being indebted moralistically as a lapse, or else to construe them in terms of effecting. In either case we bar to ourselves the way to the primal meaning of that which is later called causality. So long as this way is not opened up to us we shall also fail to see what instrumentality, which is based on causality, actually is.
+
+In order to guard against such misinterpretations of being responsible and being indebted, let us clarify the four ways of being responsible in terms of that for which they are responsible. According to our example, they are responsible for the silver chalice’s lying ready before us as a sacrificial vessel. Lying before and lying ready (hypokeisthai) characterize the presencing of something that presences. The four ways of being responsible bring something into appearance. They let it come forth into presencing [An-wesen]. They set it free to that place and so start it on its way, namely, into its complete arrival. The principal characteristic of being responsible is this starting something on its way into arrival. It is in the sense of such a starting something on its way into arrival that being responsible is an occasioning or an inducing to go forward [ver-anlassen]. On the basis of a look at what the Greeks experienced in being responsible, in aitia, we now give this verb “to occasion” a more inclusive meaning, so that it now is the name for the essence of causality thought as the Greeks thought it. The common and narrower meaning of “occasion” in contrast is nothing more than striking against and releasing, and means a kind of secondary cause within the whole of causality.
+
+But in what, then, does the playing in unison of the four ways of occasioning play? They let what is not yet present arrive into presencing. Accordingly, they are unifiedly ruled over by a bringing that brings what presences into appearance. Plato tells us what this bringing is in a sentence from the Symposium (205b): hē gar toi ek tou mē onton eis to on ionti hotōioun aitia pasa esti poiēsis. “Every occasion for whatever passes over and goes forward into presencing from that which is not presencing is poiēsis, is bringing-forth [hervor-bringen].” It is of utmost importance that we think bringing-forth in its full scope and at the same time in the sense in which the Greeks thought it. Not only handcraft manufacture, not only artistic and poetical bringing into appearance and concrete imagery, is a bringing-forth, poiēsis. Physis also, the arising of something from out of itself, is a bringing-forth, poiēsis. Physis is indeed poiēsis in the highest sense. For what presences by means of physis has the bursting open belonging to bringing-forth, for example, the bursting of a blossom into bloom, in itself (en heautōi). In contrast, what is brought forth by the artisan or the artist, for example, the silver chalice, has the bursting open belonging to bringing-forth not in itself, but in another (en allōi), in the craftsman or artist.
+
+The modes of occasioning, the four causes, are at play, then, within bringing-forth. Through bringing-forth, the growing things of nature as well as whatever is completed through the crafts and the arts come at any given time to their appearance. But how does bringing-forth happen, be it in nature or in handwork and art? What is the bringing-forth in which the fourfold way of occasioning plays? Occasioning has to do with the presencing [Anwesen] of that which at any given time comes to appearance in bringing-forth. Bringing-forth brings hither out of concealment forth into unconcealment. Bringing-forth comes to pass only insofar as something concealed comes into unconcealment. This coming rests and moves freely within what we call revealing [das Entbergen]. The Greeks have the word alētheia for revealing. The Romans translate this with veritas. We say “truth” and usually understand it as the correctness of an idea.
+
+But where have we strayed to? We are questioning concerning technology, and we have arrived now at alētheia, at revealing. What has the essence of technology to do with revealing? The answer: everything. For every bringing-forth is grounded in revealing. Bringing-forth, indeed, gathers within itself the four modes of occasioning—causality—and rules them throughout. Within its domain belong end and means, belongs instrumentality.
+
+Instrumentality is considered to be the fundamental characteristic of technology. If we inquire, step by step, into what technology, represented as means, actually is, then we shall arrive at revealing. The possibility of all productive manufacturing lies in revealing. Technology is therefore no mere means. Technology is a way of revealing. If we give heed to this, then another whole realm for the essence of technology will open itself up to us. It is the realm of revealing, that is, of truth.
+
+This prospect strikes us as strange. Indeed, it should do so, should do so as persistently as possible and with so much urgency that we will finally take seriously the simple question of what the name “technology” means. The word stems from the Greek. Technikon means that which belongs to technē. We must observe two things with respect to the meaning of this word. One is that technē is the name not only for the activities and skills of the craftsman, but also for the arts of the mind and the fine arts. Technē belongs to bringingforth, to poiēsis; it is something poietic. The other point that we should observe with regard to technē is even more important. From earliest times until Plato the word technē is linked with the word epistēmē. Both words are names for knowing in the widest sense. They mean to be entirely at home in something, to understand and be expert in it. Such knowing provides an opening up. As an opening up it is a revealing. Aristotle, in a discussion of special importance (Nicomachean Ethics, Bk. VI, chaps. 3 and 4), distinguishes between epistēmē and technē and indeed with respect to what and how they reveal. Technē is a mode of alētheuein. It reveals whatever does not bring itself forth and does not yet lie here before us, whatever can look and turn out now one way and now another. Whoever builds a house or a ship or forges a sacrificial chalice reveals what is to be brought forth, according to the perspectives of the four modes of occasioning. This revealing gathers together in advance the aspect and the matter of ship or house, with a view to the finished thing envisioned as completed, and from this gathering determines the manner of its construction. Thus what is decisive in technē does not lie at all in making and manipulating nor in the using of means, but rather in the aforementioned revealing. It is as revealing, and not as manufacturing, that technē is a bringing forth. Thus the clue to what the word technē means and to how the Greeks defined it leads us into the same context that opened itself to us when we pursued the question of what instrumentality as such in truth might be.
+
+Technology is a mode of revealing. Technology comes to presence in the realm where revealing and unconcealment take place, where alētheia, truth, happens.
+
+In opposition to this definition of the essential domain of technology, one can object that it indeed holds for Greek thought and that at best it might apply to the techniques of the handcraftsman, but that it simply does not fit modern machine-powered technology. And it is precisely the latter and it alone that is the disturbing thing, that moves us to ask the question concerning technology per se. It is said that modern technology is something incomparably different from all earlier technologies because it is based on modern physics as an exact science. Meanwhile we have come to understand more clearly that the reverse holds true as well: Modern physics, as experimental, is dependent upon technical apparatus and upon progress in the building of apparatus. The establishing of this mutual relationship between technology and physics is correct. But it remains a merely historiographical establishing of facts and says nothing about that in which this mutual relationship is grounded. The decisive question still remains: Of what essence is modern technology that it happens to think of putting exact science to use? What is modern technology? It too is a revealing. Only when we allow our attention to rest on this fundamental characteristic does that which is new in modern technology show itself to us.
+
+And yet the revealing that holds sway throughout modern technology does not unfold into a bringing-forth in the sense of poiēsis. The revealing that rules in modern technology is challenging [herausfordern], which puts to nature the unreasonable demand that it supply energy that can be extracted and stored as such. But does this not hold true for the old windmill as well? No. Its sails do indeed turn in the wind; they are left entirely to the wind’s blowing. But the windmill does not unlock energy from the air currents in order to store it.
+
+In contrast, a tract of land is challenged into the putting out of coal and ore. The earth now reveals itself as a coal mining district, the soil as a mineral deposit. The field that the peasant formerly cultivated and set in order appears differently than it did when to set in order still meant to take care of and to maintain. The work of the peasant does not challenge the soil of the field. In the sowing of the grain it places the seed in the keeping of the forces of growth and watches over its increase. But meanwhile even the cultivation of the field has come under the grip of another kind of setting-in-order, which sets upon nature. It sets upon it in the sense of challenging it.
+
+Agriculture is now the mechanized food industry. Air is now set upon to yield nitrogen, the earth to yield ore, ore to yield uranium, for example; uranium is set upon to yield atomic energy, which can be released either for destruction or for peaceful use.
+
+This setting-upon that challenges forth the energies of nature is an expediting, and in two ways. It expedites in that it unlocks and exposes. Yet that expediting is always itself directed from the beginning toward furthering something else, i.e., toward driving on to the maximum yield at the minimum expense. The coal that has been hauled out in some mining district has not been supplied in order that it may simply be present somewhere or other. It is stockpiled; that is, it is on call, ready to deliver the sun’s warmth that is stored in it. The sun’s warmth is challenged forth for heat, which in turn is ordered to deliver steam whose pressure turns the wheels that keep a factory running.
+
+The hydroelectric plant is set into the current of the Rhine. It sets the Rhine to supplying its hydraulic pressure, which then sets the turbines turning. This turning sets those machines in motion whose thrust sets going the electric current for which the long-distance power station and its network of cables are set up to dispatch electricity. In the context of the interlocking processes pertaining to the orderly disposition of electrical energy, even the Rhine itself appears as something at our command. The hydroelectric plant is not built into the Rhine River as was the old wooden bridge that joined bank with bank for hundreds of years. Rather the river is dammed up into the power plant. What the river is now, namely, a water power supplier, derives from out of the essence of the power station. In order that we may even remotely consider the monstrousness that reigns here, let us ponder for a moment the contrast that speaks out of the two titles, “The Rhine” as dammed up into the power works, and “The Rhine” as uttered out of the art work, in Hölderlin’s hymn by that name. But, it will be replied, the Rhine is still a river in the landscape, is it not? Perhaps. But how? In no other way than as an object on call for inspection by a tour group ordered there by the vacation industry.
+
+The revealing that rules throughout modern technology has the character of a setting-upon, in the sense of a challenging-forth. That challenging happens in that the energy concealed in nature is unlocked, what is unlocked is transformed, what is transformed is stored up, what is stored up is, in turn, distributed, and what is distributed is switched about ever anew. Unlocking, transforming, storing, distributing, and switching about are ways of revealing. But the revealing never simply comes to an end. Neither does it run off into the indeterminate. The revealing reveals to itself its own manifoldly interlocking paths, through regulating their course. This regulating itself is, for its part, everywhere secured. Regulating and securing even become the chief characteristics of the challenging revealing.
+
+What kind of unconcealment is it, then, that is peculiar to that which comes to stand forth through this setting-upon that challenges? Everywhere everything is ordered to stand by, to be immediately at hand, indeed to stand there just so that it may be on call for a further ordering. Whatever is ordered about in this way has its own standing. We call it the standing-reserve [Bestand]. The word expresses here something more, and something more essential, than mere “stock.” The name “standing-reserve” assumes the rank of an inclusive rubric. It designates nothing less than the way in which everything presences that is wrought upon by the challenging revealing. Whatever stands by in the sense of standing-reserve no longer stands over against us as object.
+
+Yet an airliner that stands on the runway is surely an object. Certainly. We can represent the machine so. But then it conceals itself as to what and how it is. Revealed, it stands on the taxi strip only as standing-reserve, inasmuch as it is ordered to ensure the possibility of transportation. For this it must be in its whole structure and in every one of its constituent parts, on call for duty, that is, ready for takeoff. (Here it would be appropriate to discuss Hegel’s definition of the machine as an autonomous tool. When applied to the tools of the craftsman, his characterization is correct. Characterized in this way, however, the machine is not thought at all from out of the essence of technology within which it belongs. Seen in terms of the standing-reserve, the machine is completely unautonomous, for it has its standing only from the ordering of the orderable.)
+
+The fact that now, wherever we try to point to modern technology as the challenging revealing, the words “setting-upon,” “ordering,” “standing-reserve,” obtrude and accumulate in a dry, monotonous, and therefore oppressive way, has its basis in what is now coming to utterance.
+
+Who accomplishes the challenging setting-upon through which what we call the real is revealed as standing-reserve? Obviously, man. To what extent is man capable of such a revealing? Man can indeed conceive, fashion, and carry through this or that in one way or another. But man does not have control over unconcealment itself, in which at any given time the real shows itself or withdraws. The fact that the real has been showing itself in the light of Ideas ever since the time of Plato, Plato did not bring about. The thinker only responded to what addressed itself to him.
+
+Only to the extent that man for his part is already challenged to exploit the energies of nature can this ordering revealing happen. If man is challenged, ordered, to do this, then does not man himself belong even more originally than nature within the standing-reserve? The current talk about human resources, about the supply of patients for a clinic, gives evidence of this. The forester who, in the wood, measures the felled timber and to all appearances walks the same forest path in the same way as did his grandfather is today commanded by profit-making in the lumber industry, whether he knows it or not. He is made subordinate to the orderability of cellulose, which for its part is challenged forth by the need for paper, which is then delivered to newspapers and illustrated magazines. The latter, in their turn, set public opinion to swallowing what is printed, so that a set configuration of opinion becomes available on demand. Yet precisely because man is challenged more originally than are the energies of nature, that is, into the process of ordering, he never is transformed into mere standing-reserve. Since man drives technology forward, he takes part in ordering as a way of revealing. But the unconcealment itself, within which ordering unfolds, is never a human handiwork, any more than is the realm through which man is already passing every time he as a subject relates to an object. Where and how does this revealing happen if it is no mere handiwork of man? We need not look far. We need only apprehend in an unbiased way that which has already claimed man and has done so, so decisively that he can only be man at any given time as the one so claimed. Wherever man opens his eyes and ears, unlocks his heart, and gives himself over to meditating and striving, shaping and working, entreating and thanking, he finds himself everywhere already brought into the unconcealed. The unconcealment of the unconcealed has already come to pass whenever it calls man forth into the modes of revealing allotted to him. When man, in his way, from within unconcealment reveals that which presences, he merely responds to the call of unconcealment even when he contradicts it. Thus when man, investigating, observing, ensnares nature as an area of his own conceiving, he has already been claimed by a way of revealing that challenges him to approach nature as an object of research, until even the object disappears into the objectlessness of standing-reserve.
+
+Modern technology as an ordering revealing is, then, no merely human doing. Therefore we must take that challenging that sets upon man to order the real as standing-reserve in accordance with the way in which it shows itself. That challenging gathers man into ordering. This gathering concentrates man upon ordering the real as standing-reserve.
+
+That which primordially unfolds the mountains into mountain ranges and courses through them in their folded togetherness is the gathering that we call Gebirg [mountain chain]. That original gathering from which unfold the ways in which we have feelings of one kind or another we name Gemüt [disposition]. We now name that challenging claim which gathers man thither to order the self-revealing as standing-reserve: Ge-stell [Enframing]. We dare to use this word in a sense that has been thoroughly unfamiliar up to now.
+
+According to ordinary usage, the word Gestell [frame] means some kind of apparatus, for example, a bookrack. Gestell is also the name for a skeleton. And the employment of the word Gestell [Enframing] that is now required of us seems equally eerie, not to speak of the arbitrariness with which words of a mature language are thus misused. Can anything be more strange? Surely not. Yet this strangeness is an old usage of thinking. And indeed thinkers accord with this usage precisely at the point where it is a matter of thinking that which is highest. We, late born, are no longer in a position to appreciate the significance of Plato’s daring to use the word eidos for that which in everything and in each particular thing endures as present. For eidos, in the common speech, meant the outward aspect [Ansicht] that a visible thing offers to the physical eye. Plato exacts of this word, however, something utterly extraordinary: that it name what precisely is not and never will be perceivable with physical eyes. But even this is by no means the full extent of what is extraordinary here. For idea names not only the nonsensuous aspect of what is physically visible. Aspect (idea) names and is, also, that which constitutes the essence in the audible, the tasteable, the tactile, in everything that is in any way accessible. Compared with the demands that Plato makes on language and thought in this and other instances, the use of the word Gestell as the name for the essence of modern technology, which we now venture here, is almost harmless. Even so, the usage now required remains something exacting and is open to misinterpretation.
+
+Enframing means the gathering together of that setting-upon which sets upon man, i.e., challenges him forth, to reveal the real, in the mode of ordering, as standing-reserve. Enframing means that way of revealing which holds sway in the essence of modern technology and which is itself nothing technological. On the other hand, all those things that are so familiar to us and are standard parts of an assembly, such as rods, pistons, and chassis, belong to the technological. The assembly itself, however, together with the aforementioned stockparts, falls within the sphere of technological activity; and this activity always merely responds to the challenge of Enframing, but it never comprises Enframing itself or brings it about. The word stellen [to set upon] in the name Ge-stell [Enframing] not only means challenging. At the same time it should preserve the suggestion of another Stellen from which it stems, namely, that producing and presenting [her- und dar-stellen] which, in the sense of poiēsis, lets what presences come forth into unconcealment. This producing that brings forth—for example, the erecting of a statue in the temple precinct—and the challenging ordering now under consideration are indeed fundamentally different, and yet they remain related in their essence. Both are ways of revealing, of alētheia. In Enframing, that unconcealment comes to pass in conformity with which the work of modern technology reveals the real as standing-reserve. This work is therefore neither only a human activity nor a mere means within such activity. The merely instrumental, merely anthropological definition of technology is therefore in principle untenable. And it cannot be rounded out by being referred back to some metaphysical or religious explanation that undergirds it.
+It remains true, nonetheless, that man in the technological age is, in a particularly striking way, challenged forth into revealing. That revealing concerns nature, above all, as the chief storehouse of the standing energy reserve. Accordingly, man’s ordering attitude and behavior display themselves first in the rise of modern physics as an exact science. Modern science’s way of representing pursues and entraps nature as a calculable coherence of forces. Modern physics is not experimental physics because it applies apparatus to the questioning of nature. Rather the reverse is true. Because physics, indeed already as pure theory, sets nature up to exhibit itself as a coherence of forces calculable in advance, it therefore orders its experiments precisely for the purpose of asking whether and how nature reports itself when set up in this way.
+
+But after all, mathematical physics arose almost two centuries before technology. How, then, could it have already been set upon by modern technology and placed in its service? The facts testify to the contrary. Surely technology got under way only when it could be supported by exact physical science. Reckoned chronologically, this is correct. Thought historically, it does not hit upon the truth. The modern physical theory of nature prepares the way first not simply for technology but for the essence of modern technology. For already in physics the challenging gathering-together into ordering revealing holds sway. But in it that gathering does not yet come expressly to appearance. Modern physics is the herald of Enframing, a herald whose origin is still unknown. The essence of modern technology has for a long time been concealing itself, even where power machinery has been invented, where electrical technology is in full swing, and where atomic technology is well under way. All coming to presence, not only modern technology, keeps itself everywhere concealed to the last. Nevertheless, it remains, with respect to its holding sway, that which precedes all: the earliest. The Greek thinkers already knew of this when they said: That which is earlier with regard to the arising that holds sway becomes manifest to us men only later. That which is primally early shows itself only ultimately to men. Therefore, in the realm of thinking, a painstaking effort to think through still more primally what was primally thought is not the absurd wish to revive what is past, but rather the sober readiness to be astounded before the coming of what is early.
+
+Chronologically speaking, modern physical science begins in the seventeenth century. In contrast, machine-power technology develops only in the second half of the eighteenth century. But modern technology, which for chronological reckoning is the later, is, from the point of view of the essence holding sway within it, the historically earlier.
+
+If modern physics must resign itself ever increasingly to the fact that its realm of representation remains inscrutable and incapable of being visualized, this resignation is not dictated by any committee of researchers. It is challenged forth by the rule of Enframing, which demands that nature be orderable as standing-reserve. Hence physics, in all its retreating from the representation turned only toward objects that has alone been standard till recently, will never be able to renounce this one thing: that nature reports itself in some way or other that is identifiable through calculation and that it remains orderable as a system of information. This system is determined, then, out of a causality that has changed once again. Causality now displays neither the character of the occasioning that brings forth nor the nature of the causa efficiens, let alone that of the causa formalis. It seems as though causality is shrinking into a reporting—a reporting challenged forth—of standing-reserves that must be guaranteed either simultaneously or in sequence. To this shrinking would correspond the process of growing resignation that Heisenberg’s lecture depicts in so impressive a manner.* Because the essence of modern technology lies in Enframing, modern technology must employ exact physical science. Through its so doing, the deceptive illusion arises that modern technology is applied physical science. This illusion can maintain itself only so long as neither the essential origin of modern science nor indeed the essence of modern technology is adequately found out through questioning.
+
+We are questioning concerning technology in order to bring to light our relationship to its essence. The essence of modern technology shows itself in what we call Enframing. But simply to point to Where do we find ourselves brought to, if now we think one step further regarding what Enframing itself actually is? It is nothing technological, nothing on the order of a machine. It is the way in which the real reveals itself as standing-reserve. Again we ask: Does this revealing happen somewhere beyond all human doing? No. But neither does it happen exclusively in man, or decisively through man.
+
+Enframing is the gathering together that belongs to that setting upon which sets upon man and puts him in position to reveal the real, in the mode of ordering, as standing-reserve. As the one who is challenged forth in this way, man stands within the essential realm of Enframing. He can never take up a relationship to it only subsequently. Thus the question as to how we are to arrive at a relationship to the essence of technology, asked in this way, always comes too late. But never too late comes the question as to whether we actually experience ourselves as the ones whose activities everywhere, public and private, are challenged forth by Enframing. Above all, never too late comes the question as to whether and how we actually admit ourselves into that wherein Enframing itself comes to presence.
+
+The essence of modern technology starts man upon the way of that revealing through which the real everywhere, more or less distinctly, becomes standing-reserve. “To start upon a way” means “to send” in our ordinary language. We shall call that sending-thatgathers [versammelde Schicken] which first starts man upon a way of revealing, destining [Geschick]. It is from out of this destining that the essence of all history [Geschichte] is determined. History is neither simply the object of written chronicle nor simply the fulfillment of human activity. That activity first becomes history as something destined. And it is only the destining into objectifying representation that makes the historical accessible as an object for historiography, that is, for a science, and on this basis makes possible the current equating of the historical with that which is chronicled. Enframing, as a challenging-forth into ordering, sends into a way of revealing. Enframing is an ordaining of destining, as is every way of revealing. Bringing-forth, poiēsis, is also a destining in this sense. Always the unconcealment of that which is goes upon a way of revealing. Always the destining of revealing holds complete sway over man. But that destining is never a fate that compels. For man becomes truly free only insofar as he belongs to the realm of destining and so becomes one who listens and hears, and not one who is simply constrained to obey.
+
+The essence of freedom is originally not connected with the will or even with the causality of human willing.
+
+Freedom governs the open in the sense of the cleared and lighted up, i.e., of the revealed. It is to the happening of revealing, that is, of truth, that freedom stands in the closest and most intimate kinship. All revealing belongs within a harboring and a concealing. But that which frees—the mystery—is concealed and always concealing itself. All revealing comes out of the open, goes into the open, and brings into the open. The freedom of the open consists neither in unfettered arbitrariness nor in the constraint of mere laws. Freedom is that which conceals in a way that opens to light, in whose clearing there shimmers that veil that covers what comes to presence of all truth and lets the veil appear as what veils. Freedom is the realm of the destining that at any given time starts a revealing upon its way. The essence of modern technology lies in Enframing. Enframing belongs within the destining of revealing. These sentences express something different from the talk that we hear more frequently, to the effect that technology is the fate of our age, where “fate” means the inevitableness of an unalterable course.
+
+But when we consider the essence of technology, then we experience Enframing as a destining of revealing. In this way we are already sojourning within the open space of destining, a destining that in no way confines us to a stultified compulsion to push on blindly with technology or, what comes to the same thing, to rebel helplessly against it and curse it as the work of the devil. Quite to the contrary, when we once open ourselves expressly to the essence of technology, we find ourselves unexpectedly taken into a freeing claim.
+
+The essence of technology lies in Enframing. Its holding sway belongs within destining. Since destining at any given time starts man on a way of revealing, man, thus under way, is continually approaching the brink of the possibility of pursuing and pushing forward nothing but what is revealed in ordering, and of deriving all his standards on this basis. Through this the other possibility is blocked, that man might be admitted more and sooner and ever more primally to the essence of that which is unconcealed and to its unconcealment, in order that he might experience as his essence his needed belonging to revealing.
+
+Placed between these possibilities, man is endangered from out of destining. The destining of revealing is as such, in every one of its modes, and therefore necessarily, danger.
+
+In whatever way the destining of revealing may hold sway, the unconcealment in which everything that is shows itself at any given time harbors the danger that man may misconstrue the unconcealed and misinterpret it. Thus where everything that presences exhibits itself in the light of a cause-effect coherence, even God can, for representational thinking, lose all that is exalted and holy, the mysteriousness of his distance. In the light of causality, God can sink to the level of a cause, of causa efficiens. He then becomes, even in theology, the god of the philosophers, namely, of those who define the unconcealed and the concealed in terms of the causality of making, without ever considering the essential origin of this causality.
+
+In a similar way the unconcealment in accordance with which nature presents itself as a calculable complex of the effects of forces can indeed permit correct determinations; but precisely through these successes the danger can remain that in the midst of all that is correct the true will withdraw.
+
+The destining of revealing is in itself not just any danger, but the danger.
+
+Yet when destining reigns in the mode of Enframing, it is the supreme danger. This danger attests itself to us in two ways. As soon as what is unconcealed no longer concerns man even as object, but does so, rather, exclusively as standing-reserve, and man in the midst of objectlessness is nothing but the orderer of the standing-reserve, then he comes to the very brink of a precipitous fall; that is, he comes to the point where he himself will have to be taken as standing-reserve. Meanwhile man, precisely as the one so threatened, exalts himself to the posture of lord of the earth. In this way the impression comes to prevail that everything man encounters exists only insofar as it is his construct. This illusion gives rise in turn to one final delusion: It seems as though man everywhere and always encounters only himself. Heisenberg has with complete correctness pointed out that the real must present itself to contemporary man in this way. In truth, however, precisely nowhere does man today any longer encounter himself, that is, his essence. Man stands so decisively in attendance on the challenging-forth of Enframing that he does not apprehend Enframing as a claim, that he fails to see himself as the one spoken to, and hence also fails in every way to hear in what respect he ek-sists, from out of his essence, in the realm of an exhortation or address, and thus can never encounter only himself. But Enframing does not simply endanger man in his relationship to himself and to everything that is. As a destining, it banishes man into that kind of revealing which is an ordering. Where this ordering holds sway, it drives out every other possibility of revealing. Above all, Enframing conceals that revealing which, in the sense of poiēsis, lets what presences come forth into appearance. As compared with that other revealing, the setting-upon that challenges forth thrusts man into a relation to that which is, that is at once antithetical and rigorously ordered. Where Enframing holds sway, regulating and securing of the standing-reserve mark all revealing. They no longer even let their own fundamental characteristic appear, namely, this revealing as such.
+
+Thus the challenging Enframing not only conceals a former way of revealing, bringing-forth, but it conceals revealing itself and with it That wherein unconcealment, that is, truth, comes to pass. Enframing blocks the shining-forth and holding-sway of truth. The destining that sends into ordering is consequently the extreme danger. What is dangerous is not technology. There is no demonry of technology, but rather there is the mystery of its essence. The essence of technology, as a destining of revealing, is the danger. The transformed meaning of the word “Enframing” will perhaps become somewhat more familiar to us now if we think Enframing in the sense of destining and danger.
+
+The threat to man does not come in the first instance from the potentially lethal machines and apparatus of technology. The actual threat has already affected man in his essence. The rule of Enframing threatens man with the possibility that it could be denied to him to enter into a more original revealing and hence to experience the call of a more primal truth.
+
+Thus, where Enframing reigns, there is danger in the highest sense.
+
+But where danger is, grows The saving power also.
+
+Let us think carefully about these words of Hölderlin. What does it mean “to save”? Usually we think that it means only to seize hold of a thing threatened by ruin, in order to secure it in its former continuance. But the verb “to save” says more. “To save” is to fetch something home into its essence, in order to bring the essence for the first time into its genuine appearing. If the essence of technology, Enframing, is the extreme danger, and if there is truth in Hölderlin’s words, then the rule of Enframing cannot exhaust itself solely in blocking all lighting-up of every revealing, all appearing of truth. Rather, precisely the essence of technology must harbor in itself the growth of the saving power. But in that case, might not an adequate look into what Enframing is as a destining of revealing bring into appearance the saving power in its arising?
+
+In what respect does the saving power grow there also where the danger is? Where something grows, there it takes root, from thence it thrives. Both happen concealedly and quietly and in their own time. But according to the words of the poet we have no right whatsoever to expect that there where the danger is we should be able to lay hold of the saving power immediately and without preparation. Therefore we must consider now, in advance, in what respect the saving power does most profoundly take root and thence thrive even in that wherein the extreme danger lies, in the holding sway of Enframing. In order to consider this, it is necessary, as a last step upon our way, to look with yet clearer eyes into the danger. Accordingly, we must once more question concerning technology. For we have said that in technology’s essence roots and thrives the saving power. But how shall we behold the saving power in the essence of technology so long as we do not consider in what sense of “essence” it is that Enframing is actually the essence of technology? Thus far we have understood “essence” in its current meaning. In the academic language of philosophy, “essence” means what something is; in Latin, quid. Quidditas, whatness, provides the answer to the question concerning essence. For example, what pertains to all kinds of trees—oaks, beeches, birches, firs—is the same “treeness.” Under this inclusive genus—the “universal”—fall all real and possible trees. Is then the essence of technology, Enframing, the common genus for everything technological? If that were the case then the steam turbine, the radio transmitter, and the cyclotron would each be an Enframing. But the word “Enframing” does not mean here a tool or any kind of apparatus. Still less does it mean the general concept of such resources. The machines and apparatus are no more cases and kinds of Enframing than are the man at the switchboard and the engineer in the drafting room. Each of these in its own way indeed belongs as stock-part, available resource, or executer, within Enframing; but Enframing is never the essence of technology in the sense of a genus. Enframing is a way of revealing having the character of destining, namely, the way that challenges forth. The revealing that brings forth (poiēsis) is also a way that has the character of destining. But these ways are not kinds that, arrayed beside one another, fall under the concept of revealing. Revealing is that destining which, ever suddenly and inexplicably to all thinking, apportions itself into the revealing that brings forth and that also challenges, and which allots itself to man. The challenging revealing has its origin as a destining in bringing-forth. But at the same time Enframing, in a way characteristic of a destining, blocks poiēsis. Thus Enframing, as a destining of revealing, is indeed the essence of technology, but never in the sense of genus and essentia. If we pay heed to this, something astounding strikes us: It is technology itself that makes the demand on us to think in another way what is usually understood by “essence.” But in what way?
+
+If we speak of the “essence of a house” and the “essence of a state,” we do not mean a generic type; rather we mean the ways in which house and state hold sway, administer themselves, develop and decay—the way in which they “essence” [Wesen]. Johann Peter Hebel in a poem, “Ghost on Kanderer Street,” for which Goethe had a special fondness, uses the old word die Weserei. It means the city hall inasmuch as there the life of the community gathers and village existence is constantly in play, that is, comes to presence. It is from the verb wesen that the noun is derived. Wesen understood as a verb is the same as währen [to last or endure], not only in terms of meaning, but also in terms of the phonetic formation of the word.
+
+Socrates and Plato already think the essence of something as what essences, what comes to presence, in the sense of what endures. But they think what endures as what remains permanently (aei on). And they find what endures permanently in what, as that which remains, tenaciously persists throughout all that happens. That which remains they discover, in turn, in the aspect (eidos, idea), for example, the Idea “house.”
+
+The Idea “house” displays what anything is that is fashioned as a house. Particular, real, and possible houses, in contrast, are changing and transitory derivatives of the Idea and thus belong to what does not endure.
+
+But it can never in any way be established that enduring is based solely on what Plato thinks as idea and Aristotle thinks as to ti ēn einai (that which any particular thing has always been), or what metaphysics in its most varied interpretations thinks as essentia. All essencing endures. But is enduring only permanent enduring? Does the essence of technology endure in the sense of the permanent enduring of an Idea that hovers over everything technological, thus making it seem that by technology we mean some mythological abstraction? The way in which technology essences lets itself be seen only from out of that permanent enduring in which Enframing comes to pass as a destining of revealing. Goethe once uses the mysterious word fortgewähren [to grant permanently] in place of fortwähren [to endure permanently].* He hears währen [to endure] and gewähren [to grant] here in one unarticulated accord. And if we now ponder more carefully than we did before what it is that actually endures and perhaps alone endures, we may venture to say: Only what is granted endures. That which endures primally out of the earliest beginning is what grants.
+
+As the essencing of technology, Enframing is that which endures. Does Enframing hold sway at all in the sense of granting? No doubt the question seems a horrendous blunder. For according to everything that has been said, Enframing is, rather, a destining that gathers together into the revealing that challenges forth. Challenging is anything but a granting. So it seems, so long as we do not notice that the challenging-forth into the ordering of the real as standing-reserve still remains a destining that starts man upon a way of revealing. As this destining, the coming to presence of technology gives man entry into That which, of himself, he can neither invent nor in any way make. For there is no such thing as a man who, solely of himself, is only man.
+
+But if this destining, Enframing, is the extreme danger, not only for man’s coming to presence, but for all revealing as such, should this destining still be called a granting? Yes, most emphatically, if in this destining the saving power is said to grow. Every destining of revealing comes to pass from out of a granting and as such a granting. For it is granting that first conveys to man that share in revealing which the coming-to-pass of revealing needs. As the one so needed and used, man is given to belong to the coming-to-pass of truth. The granting that sends in one way or another into revealing is as such the saving power. For the saving power lets man see and enter into the highest dignity of his essence. This dignity lies in keeping watch over the unconcealment—and with it, from the first, the concealment —of all coming to presence on this earth. It is precisely in Enframing, which threatens to sweep man away into ordering as the supposed single way of revealing, and so thrusts man into the danger of the surrender of his free essence—it is precisely in this extreme danger that the innermost indestructible belongingness of man within granting may come to light, provided that we, for our part, begin to pay heed to the coming to presence of technology.
+
+Thus the coming to presence of technology harbors in itself what we least suspect, the possible arising of the saving power. Everything, then, depends upon this: that we ponder this arising and that, recollecting, we watch over it. How can this happen? Above all through our catching sight of what comes to presence in technology, instead of merely staring at the technological. So long as we represent technology as an instrument, we remain held fast in the will to master it. We press on past the essence of technology. When, however, we ask how the instrumental comes to presence as a kind of causality, then we experience this coming to presence as the destining of a revealing.
+
+When we consider, finally, that the coming to presence of the essence of technology comes to pass in the granting that needs and uses man so that he may share in revealing, then the following becomes clear:
+
+The essence of technology is in a lofty sense ambiguous. Such ambiguity points to the mystery of all revealing, that is, of truth. On the one hand, Enframing challenges forth into the frenziedness of ordering that blocks every view into the coming-topass of revealing and so radically endangers the relation to the essence of truth.
+
+On the other hand, Enframing comes to pass for its part in the granting that lets man endure—as yet unexperienced, but perhaps more experienced in the future—that he may be the one who is needed and used for the safekeeping of the coming to presence of truth. Thus does the arising of the saving power appear. The irresistibility of ordering and the restraint of the saving power draw past each other like the paths of two stars in the course of the heavens. But precisely this, their passing by, is the hidden side of their nearness.
+
+When we look into the ambiguous essence of technology, we behold the constellation, the stellar course of the mystery. The question concerning technology is the question concerning the constellation in which revealing and concealing, in which the coming to presence of truth, comes to pass. But what help is it to us to look into the constellation of truth? We look into the danger and see the growth of the saving power. Through this we are not yet saved. But we are thereupon summoned to hope in the growing light of the saving power. How can this happen? Here and now and in little things, that we may foster the saving power in its increase. This includes holding always before our eyes the extreme danger.
+
+The coming to presence of technology threatens revealing, threatens it with the possibility that all revealing will be consumed in ordering and that everything will present itself only in the unconcealedness of standing-reserve. Human activity can never directly counter this danger. Human achievement alone can never banish it. But human reflection can ponder the fact that all saving power must be of a higher essence than what is endangered, though at the same time kindred to it.
+
+But might there not perhaps be a more primally granted revealing that could bring the saving power into its first shining forth in the midst of the danger, a revealing that in the technological age rather conceals than shows itself? There was a time when it was not technology alone that bore the name technē. Once that revealing that brings forth truth into the splendor of radiant appearing also was called technē. Once there was a time when the bringing-forth of the true into the beautiful was called technē. And the poiēsis of the fine arts also was called technē.
+
+In Greece, at the outset of the destining of the West, the arts soared to the supreme height of the revealing granted them. They brought the presence [Gegenwart] of the gods, brought the dialogue of divine and human destinings, to radiance. And art was simply called technē. It was a single, manifold revealing. It was pious, promos, i.e., yielding to the holding-sway and the safekeeping of truth.
+
+The arts were not derived from the artistic. Art works were not enjoyed aesthetically. Art was not a sector of cultural activity. What, then, was art—perhaps only for that brief but magnificent time? Why did art bear the modest name technē? Because it was a revealing that brought forth and hither, and therefore belonged within poiēsis. It was finally that revealing which holds complete sway in all the fine arts, in poetry, and in everything poetical that obtained poiēsis as its proper name.
+
+
+The same poet from whom we heard the words:
+But where danger is, grows
+The saving power also.
+
+says to us:
+… poetically dwells man upon this earth.
+
+The poetical brings the true into the splendor of what Plato in the Phaedrus calls to ekphanestaton, that which shines forth most purely. The poetical thoroughly pervades every art, every revealing of coming to presence into the beautiful.
+
+Could it be that the fine arts are called to poetic revealing? Could it be that revealing lays claim to the arts most primally, so that they for their part may expressly foster the growth of the saving power, may awaken and found anew our look into that which grants and our trust in it?
+
+Whether art may be granted this highest possibility of its essence in the midst of the extreme danger, no one can tell. Yet we can be astounded. Before what? Before this other possibility: that the frenziedness of technology may entrench itself everywhere to such an extent that someday, throughout everything technological, the essence of technology may come to presence in the coming-to-pass of truth.
+
+Because the essence of technology is nothing technological, essential reflection upon technology and decisive confrontation with it must happen in a realm that is, on the one hand, akin to the essence of technology and, on the other, fundamentally different from it.
+
+Such a realm is art. But certainly only if reflection on art, for its part, does not shut its eyes to the constellation of truth after which we are questioning.
+
+Thus questioning, we bear witness to the crisis that in our sheer preoccupation with technology we do not yet experience the coming to presence of technology, that in our sheer aesthetic-mindedness we no longer guard and preserve the coming to presence of art. Yet the more questioningly we ponder the essence of technology, the more mysterious the essence of art becomes.
+
+The closer we come to the danger, the more brightly do the ways into the saving power begin to shine and the more questioning we become. For questioning is the piety of thought.
+