summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.config/Thunar/accels.scm118
-rw-r--r--.config/Thunar/uca.xml15
-rw-r--r--.config/X11/Xmodmap248
-rw-r--r--.config/X11/Xresources164
-rw-r--r--.config/X11/xbindkeysrc96
-rw-r--r--.config/X11/xinitrc42
-rw-r--r--.config/X11/xprofile18
-rw-r--r--.config/Zeal/Zeal.conf52
-rw-r--r--.config/Zeal/style.css3
-rw-r--r--.config/git/config5
-rw-r--r--.config/gotop/gotop.conf33
-rw-r--r--.config/gtk-2.0/gtkfilechooser.ini11
-rw-r--r--.config/gtk-2.0/gtkrc-2.019
-rw-r--r--.config/gtk-2.0/gtkrc-2.0.bak20
-rw-r--r--.config/gtk-3.0/bookmarks1
-rw-r--r--.config/gtk-3.0/settings.ini20
-rw-r--r--.config/htop/htoprc63
-rw-r--r--.config/i3/config644
-rw-r--r--.config/i3blocks/config71
-rw-r--r--.config/i3blocks/systeminfo50
-rw-r--r--.config/ipython/profile_default/db/dhistbin0 -> 109 bytes
-rw-r--r--.config/ipython/profile_default/history.sqlitebin0 -> 118784 bytes
-rw-r--r--.config/ipython/profile_default/ipython_config.py1146
-rw-r--r--.config/ipython/profile_default/startup/05-keybindings.py18
-rw-r--r--.config/ipython/profile_default/startup/10-startup.ipy13
-rw-r--r--.config/ipython/profile_default/startup/20-functions.ipy13
-rw-r--r--.config/ipython/profile_default/startup/README11
-rw-r--r--.config/jgmenu/append.csv7
-rw-r--r--.config/jgmenu/backup/20230925074149958689103/jgmenurc74
-rw-r--r--.config/jgmenu/jgmenurc74
-rw-r--r--.config/keepassxc/keepassxc.ini37
-rw-r--r--.config/lf/brodie/draw_img67
-rw-r--r--.config/lf/brodie/image18
-rw-r--r--.config/lf/brodie/preview48
-rw-r--r--.config/lf/colors175
-rw-r--r--.config/lf/draw_img67
-rw-r--r--.config/lf/history7
-rw-r--r--.config/lf/icons358
-rw-r--r--.config/lf/image18
-rw-r--r--.config/lf/lfrc160
-rw-r--r--.config/lf/luke/scope56
-rw-r--r--.config/lf/preview48
-rw-r--r--.config/lxsession/i3/desktop.conf9
-rw-r--r--.config/nvim/autoload/airline/themes/onedark.vim130
-rw-r--r--.config/nvim/autoload/lightline/colorscheme/onedark.vim58
-rw-r--r--.config/nvim/autoload/onedark.vim29
-rw-r--r--.config/nvim/autoload/plug.vim2863
-rw-r--r--.config/nvim/autoload/scratch.vim49
-rw-r--r--.config/nvim/coc/coc-onload.vim144
-rw-r--r--.config/nvim/coc/coc-settings.json6
-rw-r--r--.config/nvim/colors/onedark.vim713
-rw-r--r--.config/nvim/dev.vim93
-rw-r--r--.config/nvim/init.bak.vim225
-rw-r--r--.config/nvim/init.vim178
-rw-r--r--.config/nvim/onedark.vim713
-rw-r--r--.config/nvim/other/fzf.vim19
-rw-r--r--.config/nvim/other/learn.vim649
-rw-r--r--.config/nvim/out.vim36
m---------.config/nvim/pack/colors/opt/onedark.vim0
-rw-r--r--.config/nvim/templates/_default.c5
-rw-r--r--.config/nvim/templates/_default.html13
-rw-r--r--.config/nvim/templates/_default.tex7
-rw-r--r--.config/nvim/templates/article.tex11
-rw-r--r--.config/nvim/vim.log170
-rw-r--r--.config/nvim/vimspector/python.json31
-rw-r--r--.config/python/pythonrc22
-rw-r--r--.config/shell/aliasrc85
-rw-r--r--.config/shell/bm-dirs51
-rw-r--r--.config/shell/bm-files28
-rw-r--r--.config/shell/inputrc38
-rw-r--r--.config/shell/profile268
-rw-r--r--.config/terminal-colors.d/cal.scheme5
-rw-r--r--.config/tmux/tmux-gruvbox-dark.conf53
-rw-r--r--.config/tmux/tmux-gruvbox-light.conf56
-rw-r--r--.config/tmux/tmux-onedark-theme.tmux95
-rw-r--r--.config/tmux/tmux.conf77
-rw-r--r--.config/wget/wgetrc1
-rw-r--r--.config/yt-dlp/channel.conf12
-rw-r--r--.config/yt-dlp/config14
-rw-r--r--.config/yt-dlp/playlist.conf12
-rw-r--r--.config/yt-dlp/sequenced-playlist.conf7
-rw-r--r--.config/yt-dlp/videos.conf2
-rw-r--r--.config/zathura/zathurarc10
-rw-r--r--.config/zsh/.zshrc293
-rw-r--r--.config/zsh/command-tools.zsh61
m---------.config/zsh/plugins/fast-syntax-highlighting0
-rw-r--r--.config/zsh/plugins/fzf-completion.zsh329
-rw-r--r--.config/zsh/plugins/zsh-autosuggestions.zsh864
-rw-r--r--.config/zsh/plugins/zsh-history-substring-search.zsh759
m---------.config/zsh/plugins/zsh-syntax-highlighting0
-rw-r--r--.config/zsh/zprofile21
-rwxr-xr-x.gitignore69
-rw-r--r--.gitmodules6
-rwxr-xr-x.local/bin/automountd12
-rwxr-xr-x.local/bin/backup33
-rwxr-xr-x.local/bin/clearx51
-rwxr-xr-x.local/bin/desktop/beautify102
-rwxr-xr-x.local/bin/desktop/brightness32
-rwxr-xr-x.local/bin/desktop/detect-keys3
-rwxr-xr-x.local/bin/desktop/dmenu-syncthing-devices25
-rwxr-xr-x.local/bin/desktop/dmenu-unicode11
-rwxr-xr-x.local/bin/desktop/dmenu-zeal27
-rwxr-xr-x.local/bin/desktop/edit-graphical-buffer17
-rwxr-xr-x.local/bin/desktop/i3exit54
-rwxr-xr-x.local/bin/desktop/i3exit-script18
-rwxr-xr-x.local/bin/desktop/librewolf-open39
-rwxr-xr-x.local/bin/desktop/mlock22
-rwxr-xr-x.local/bin/desktop/remap146
-rwxr-xr-x.local/bin/desktop/remapd6
-rwxr-xr-x.local/bin/desktop/setdp36
-rwxr-xr-x.local/bin/desktop/show-i3-keybindings11
-rwxr-xr-x.local/bin/desktop/toggle-xeyes7
-rwxr-xr-x.local/bin/desktop/torbrowser30
-rwxr-xr-x.local/bin/desktop/volctl50
-rwxr-xr-x.local/bin/development/dev179
-rwxr-xr-x.local/bin/development/getcomproot14
-rwxr-xr-x.local/bin/development/gitpush10
-rwxr-xr-x.local/bin/development/gitw18
-rwxr-xr-x.local/bin/development/ipy4
-rwxr-xr-x.local/bin/development/ipytest23
-rwxr-xr-x.local/bin/development/nx148
-rwxr-xr-x.local/bin/development/opout12
-rwxr-xr-x.local/bin/development/pipsearch4
-rwxr-xr-x.local/bin/development/py4
-rwxr-xr-x.local/bin/development/pyh12
-rwxr-xr-x.local/bin/development/texclear9
-rwxr-xr-x.local/bin/fcode23
-rwxr-xr-x.local/bin/fdict25
-rwxr-xr-x.local/bin/fgrp27
-rwxr-xr-x.local/bin/filter52
-rwxr-xr-x.local/bin/fm22
-rwxr-xr-x.local/bin/fmd26
-rwxr-xr-x.local/bin/fpm148
-rwxr-xr-x.local/bin/fsend47
-rwxr-xr-x.local/bin/fw10
-rwxr-xr-x.local/bin/help99
-rwxr-xr-x.local/bin/launch-gtypist101
-rwxr-xr-x.local/bin/lessopen.sh9
-rwxr-xr-x.local/bin/loop45
-rwxr-xr-x.local/bin/lsinputs12
-rwxr-xr-x.local/bin/mnt39
-rwxr-xr-x.local/bin/open48
-rwxr-xr-x.local/bin/preview59
-rwxr-xr-x.local/bin/search62
-rwxr-xr-x.local/bin/searchdb35
-rwxr-xr-x.local/bin/setbg18
-rwxr-xr-x.local/bin/shortcuts35
-rwxr-xr-x.local/bin/shorts/adbs3
-rwxr-xr-x.local/bin/shorts/append-to-history5
-rwxr-xr-x.local/bin/shorts/bs7
-rwxr-xr-x.local/bin/shorts/conv10
-rwxr-xr-x.local/bin/shorts/diffdirs6
-rwxr-xr-x.local/bin/shorts/font2svg3
-rwxr-xr-x.local/bin/shorts/preview-bat3
-rwxr-xr-x.local/bin/shorts/preview-highlight3
-rwxr-xr-x.local/bin/shorts/refcitx6
-rwxr-xr-x.local/bin/shorts/sc3
-rwxr-xr-x.local/bin/shorts/scrcpy-k8
-rwxr-xr-x.local/bin/shorts/ssha5
-rwxr-xr-x.local/bin/shorts/sync-server12
-rwxr-xr-x.local/bin/shorts/syncdrive3
-rwxr-xr-x.local/bin/shorts/synchs7
-rwxr-xr-x.local/bin/shorts/synctab19
-rwxr-xr-x.local/bin/shorts/xdg-terminal-exec3
-rwxr-xr-x.local/bin/shorts/xprint8
-rwxr-xr-x.local/bin/sshadd17
-rwxr-xr-x.local/bin/statusbar/cpu_usage55
-rwxr-xr-x.local/bin/statusbar/i3bandwidth105
-rwxr-xr-x.local/bin/statusbar/i3battery66
-rwxr-xr-x.local/bin/statusbar/i3cpu34
-rwxr-xr-x.local/bin/statusbar/i3cpubars44
-rwxr-xr-x.local/bin/statusbar/i3cpuload68
-rwxr-xr-x.local/bin/statusbar/i3memory33
-rwxr-xr-x.local/bin/statusbar/i3weather26
-rwxr-xr-x.local/bin/statusbar/i3wifi37
-rwxr-xr-x.local/bin/statusbar/memory_percent57
-rwxr-xr-x.local/bin/statusbar/memory_usage56
-rwxr-xr-x.local/bin/ttyl37
-rwxr-xr-x.local/bin/unix26
-rwxr-xr-x.local/bin/web/fpl39
-rwxr-xr-x.local/bin/web/savesite35
-rwxr-xr-x.local/bin/web/w3mman335
-rwxr-xr-x.local/bin/web/ytf10
-rwxr-xr-x.local/bin/web/ytplaylist34
-rwxr-xr-x.local/bin/web/ytv3
-rw-r--r--.local/share/applications/browser.desktop10
-rw-r--r--.local/share/applications/file.desktop4
-rw-r--r--.local/share/applications/img.desktop4
-rw-r--r--.local/share/applications/mail.desktop4
-rw-r--r--.local/share/applications/mimeapps.list25
-rw-r--r--.local/share/applications/mimeinfo.cache153
-rw-r--r--.local/share/applications/pdf.desktop4
-rw-r--r--.local/share/applications/rss.desktop5
-rw-r--r--.local/share/applications/text.desktop5
-rw-r--r--.local/share/applications/torrent.desktop5
-rw-r--r--.local/share/applications/video.desktop4
-rw-r--r--.local/share/chars/emoji1630
-rw-r--r--.local/share/chars/font-awesome1456
-rw-r--r--.local/share/chars/unicodebin0 -> 2085040 bytes
l---------.profile1
l---------.xprofile1
l---------.zprofile1
-rw-r--r--gtkrc-2.019
203 files changed, 20170 insertions, 0 deletions
diff --git a/.config/Thunar/accels.scm b/.config/Thunar/accels.scm
new file mode 100644
index 0000000..638a9f3
--- /dev/null
+++ b/.config/Thunar/accels.scm
@@ -0,0 +1,118 @@
+; thunar GtkAccelMap rc-file -*- scheme -*-
+; this file is an automated accelerator map dump
+;
+; (gtk_accel_path "<Actions>/ThunarActionManager/restore" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/undo" "<Primary>z")
+; (gtk_accel_path "<Actions>/ThunarStandardView/select-all-files" "<Primary>a")
+; (gtk_accel_path "<Actions>/ThunarBookmarks/0064c8b8c2b8ae1954479b6f2feab576" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-by-dtime" "")
+; (gtk_accel_path "<Actions>/ThunarStatusBar/toggle-last-modified" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/invert-selection" "")
+; (gtk_accel_path "<Actions>/ThunarStatusBar/toggle-display-name" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/cut" "<Primary>x")
+; (gtk_accel_path "<Actions>/ThunarActionManager/restore-show" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-in" "<Primary>plus")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-ascending" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/empty-trash" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/reload" "<Primary>r")
+; (gtk_accel_path "<Actions>/ThunarWindow/toggle-image-preview" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/cut-2" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-side-pane-menu" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/trash-delete" "Delete")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-network" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/trash-delete-2" "KP_Delete")
+; (gtk_accel_path "<Actions>/ThunarWindow/contents/help-menu" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/delete" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/set-default-app" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/back-alt" "BackSpace")
+; (gtk_accel_path "<Actions>/ThunarActionManager/open-in-new-tab" "<Primary><Shift>p")
+; (gtk_accel_path "<Actions>/ThunarWindow/switch-next-tab" "<Primary>Page_Down")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-file-menu" "F10")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-as-compact-list" "<Primary>3")
+; (gtk_accel_path "<Actions>/ThunarWindow/about" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-computer" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/clear-directory-specific-settings" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-file-system" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-parent" "<Alt>Up")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-menu" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/copy" "<Primary>c")
+; (gtk_accel_path "<Actions>/ThunarStandardView/properties" "<Alt>Return")
+; (gtk_accel_path "<Actions>/ThunarStandardView/back" "<Alt>Left")
+; (gtk_accel_path "<Actions>/ThunarWindow/sendto-menu" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-by-mtime" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/open-location" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/bookmarks-menu" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/reload-alt" "F5")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-location-selector-buttons" "")
+; (gtk_accel_path "<Actions>/ThunarStatusBar/toggle-size-in-bytes" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/unselect-all-files" "Escape")
+; (gtk_accel_path "<Actions>/ThunarActionManager/copy-2" "<Primary>Insert")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-out-alt" "<Primary>KP_Subtract")
+; (gtk_accel_path "<Actions>/ThunarWindow/cancel-search" "Escape")
+; (gtk_accel_path "<Actions>/ThunarStandardView/select-by-pattern" "<Primary>s")
+; (gtk_accel_path "<Actions>/ThunarStandardView/rename" "F2")
+; (gtk_accel_path "<Actions>/ThunarStandardView/configure-columns" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/create-document" "")
+; (gtk_accel_path "<Actions>/ThunarShortcutsPane/sendto-shortcuts" "<Primary>d")
+; (gtk_accel_path "<Actions>/ThunarActionManager/move-to-trash" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/close-tab" "<Primary>w")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-side-pane-tree" "<Primary>e")
+; (gtk_accel_path "<Actions>/ThunarActionManager/open" "<Primary>o")
+; (gtk_accel_path "<Actions>/ThunarWindow/toggle-side-pane" "F9")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-location-selector-entry" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-recent" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-home" "<Alt>Home")
+; (gtk_accel_path "<Actions>/ThunarWindow/toggle-split-view" "F3")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-templates" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-location-alt" "<Alt>d")
+; (gtk_accel_path "<Actions>/ThunarStandardView/create-folder" "<Primary><Shift>n")
+; (gtk_accel_path "<Actions>/ThunarWindow/search" "<Primary>f")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-by-type" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/paste-2" "<Shift>Insert")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-in-alt2" "<Primary>equal")
+; (gtk_accel_path "<Actions>/ThunarStandardView/duplicate" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/remove-from-recent" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-out" "<Primary>minus")
+; (gtk_accel_path "<Actions>/ThunarWindow/close-window" "<Primary>q")
+; (gtk_accel_path "<Actions>/ThunarWindow/edit-menu" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-side-pane-shortcuts" "<Primary>b")
+; (gtk_accel_path "<Actions>/ThunarWindow/show-highlight" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/contents" "F1")
+; (gtk_accel_path "<Actions>/ThunarWindow/preferences" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/switch-previous-tab" "<Primary>Page_Up")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-in-alt1" "<Primary>KP_Add")
+; (gtk_accel_path "<Actions>/ThunarStandardView/toggle-sort-order" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/open-in-new-window" "<Primary><Shift>o")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-configure-toolbar" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-location-selector-menu" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-statusbar" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/close-all-windows" "<Primary><Shift>w")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-trash" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/paste" "<Primary>v")
+; (gtk_accel_path "<Actions>/ThunarActionManager/delete-3" "<Shift>KP_Delete")
+; (gtk_accel_path "<Actions>/ThunarActionManager/execute" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-desktop" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/open-with-other" "")
+; (gtk_accel_path "<Actions>/ThunarStatusBar/toggle-size" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/sendto-desktop" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/open-location" "<Primary>l")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-menubar" "<Primary>m")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-reset-alt" "<Primary>KP_0")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-as-detailed-list" "<Primary>2")
+; (gtk_accel_path "<Actions>/ThunarWindow/view-as-icons" "<Primary>1")
+; (gtk_accel_path "<Actions>/ThunarWindow/new-window" "<Primary>n")
+; (gtk_accel_path "<Actions>/ThunarStandardView/forward" "<Alt>Right")
+; (gtk_accel_path "<Actions>/ThunarActionManager/redo" "<Primary><Shift>z")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-descending" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/file-menu" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/make-link" "")
+; (gtk_accel_path "<Actions>/ThunarActionManager/delete-2" "<Shift>Delete")
+; (gtk_accel_path "<Actions>/ThunarWindow/new-tab" "<Primary>t")
+; (gtk_accel_path "<Actions>/ThunarWindow/go-menu" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-by-size" "")
+; (gtk_accel_path "<Actions>/ThunarStandardView/arrange-items-menu" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/show-hidden" "<Primary>h")
+; (gtk_accel_path "<Actions>/ThunarStandardView/sort-by-name" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/zoom-reset" "<Primary>0")
+; (gtk_accel_path "<Actions>/ThunarStatusBar/toggle-filetype" "")
+; (gtk_accel_path "<Actions>/ThunarWindow/detach-tab" "")
diff --git a/.config/Thunar/uca.xml b/.config/Thunar/uca.xml
new file mode 100644
index 0000000..3d179a4
--- /dev/null
+++ b/.config/Thunar/uca.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<actions>
+<action>
+ <icon>utilities-terminal</icon>
+ <name>Open Terminal Here</name>
+ <submenu></submenu>
+ <unique-id>1722344429525890-1</unique-id>
+ <command>exo-open --working-directory %f --launch TerminalEmulator</command>
+ <description>Example for a custom action</description>
+ <range></range>
+ <patterns>*</patterns>
+ <startup-notify/>
+ <directories/>
+</action>
+</actions>
diff --git a/.config/X11/Xmodmap b/.config/X11/Xmodmap
new file mode 100644
index 0000000..797b664
--- /dev/null
+++ b/.config/X11/Xmodmap
@@ -0,0 +1,248 @@
+keycode 8 =
+keycode 9 = Escape NoSymbol Escape
+keycode 10 = 1 exclam 1 exclam
+keycode 11 = 2 at 2 at
+keycode 12 = 3 numbersign 3 numbersign
+keycode 13 = 4 dollar 4 dollar
+keycode 14 = 5 percent 5 percent
+keycode 15 = 6 asciicircum 6 asciicircum
+keycode 16 = 7 ampersand 7 ampersand
+keycode 17 = 8 asterisk 8 asterisk
+keycode 18 = 9 parenleft 9 parenleft
+keycode 19 = 0 parenright 0 parenright
+keycode 20 = minus underscore minus underscore
+keycode 21 = equal plus equal plus
+keycode 22 = BackSpace BackSpace BackSpace BackSpace
+keycode 23 = Tab ISO_Left_Tab Tab ISO_Left_Tab
+keycode 24 = q Q q Q
+keycode 25 = w W w W
+keycode 26 = e E e E
+keycode 27 = r R r R
+keycode 28 = t T t T
+keycode 29 = y Y y Y
+keycode 30 = u U u U
+keycode 31 = i I i I
+keycode 32 = o O o O
+keycode 33 = p P p P
+keycode 34 = bracketleft braceleft bracketleft braceleft
+keycode 35 = bracketright braceright bracketright braceright
+keycode 36 = Return NoSymbol Return
+keycode 37 = Control_L NoSymbol Control_L
+keycode 38 = a A a A
+keycode 39 = s S s S
+keycode 40 = d D d D
+keycode 41 = f F f F
+keycode 42 = g G g G
+keycode 43 = h H h H
+keycode 44 = j J j J
+keycode 45 = k K k K
+keycode 46 = l L l L
+keycode 47 = semicolon colon semicolon colon
+keycode 48 = apostrophe quotedbl apostrophe quotedbl
+keycode 49 = grave asciitilde grave asciitilde
+keycode 50 = Shift_L NoSymbol Shift_L
+keycode 51 = backslash bar backslash bar
+keycode 52 = z Z z Z
+keycode 53 = x X x X
+keycode 54 = c C c C
+keycode 55 = v V v V
+keycode 56 = b B b B
+keycode 57 = n N n N
+keycode 58 = m M m M
+keycode 59 = comma less comma less
+keycode 60 = period greater period greater
+keycode 61 = slash question slash question
+keycode 62 = Shift_R NoSymbol Shift_R
+keycode 63 = KP_Multiply KP_Multiply KP_Multiply KP_Multiply KP_Multiply KP_Multiply XF86ClearGrab
+keycode 64 = Alt_L Meta_L Alt_L Meta_L
+keycode 65 = space NoSymbol space
+keycode 66 = Caps_Lock NoSymbol Caps_Lock
+keycode 67 = F1 F1 F1 F1 F1 F1 XF86Switch_VT_1
+keycode 68 = F2 F2 F2 F2 F2 F2 XF86Switch_VT_2
+keycode 69 = F3 F3 F3 F3 F3 F3 XF86Switch_VT_3
+keycode 70 = F4 F4 F4 F4 F4 F4 XF86Switch_VT_4
+keycode 71 = F5 F5 F5 F5 F5 F5 XF86Switch_VT_5
+keycode 72 = F6 F6 F6 F6 F6 F6 XF86Switch_VT_6
+keycode 73 = F7 F7 F7 F7 F7 F7 XF86Switch_VT_7
+keycode 74 = F8 F8 F8 F8 F8 F8 XF86Switch_VT_8
+keycode 75 = F9 F9 F9 F9 F9 F9 XF86Switch_VT_9
+keycode 76 = F10 F10 F10 F10 F10 F10 XF86Switch_VT_10
+keycode 77 = Num_Lock NoSymbol Num_Lock
+keycode 78 = Scroll_Lock NoSymbol Scroll_Lock
+keycode 79 = KP_Home KP_7 KP_Home KP_7
+keycode 80 = KP_Up KP_8 KP_Up KP_8
+keycode 81 = KP_Prior KP_9 KP_Prior KP_9
+keycode 82 = KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract XF86Prev_VMode
+keycode 83 = KP_Left KP_4 KP_Left KP_4
+keycode 84 = KP_Begin KP_5 KP_Begin KP_5
+keycode 85 = KP_Right KP_6 KP_Right KP_6
+keycode 86 = KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add XF86Next_VMode
+keycode 87 = KP_End KP_1 KP_End KP_1
+keycode 88 = KP_Down KP_2 KP_Down KP_2
+keycode 89 = KP_Next KP_3 KP_Next KP_3
+keycode 90 = KP_Insert KP_0 KP_Insert KP_0
+keycode 91 = KP_Delete KP_Decimal KP_Delete KP_Decimal
+keycode 92 = ISO_Level3_Shift NoSymbol ISO_Level3_Shift
+keycode 93 =
+keycode 94 = less greater less greater bar brokenbar bar
+keycode 95 = F11 F11 F11 F11 F11 F11 XF86Switch_VT_11
+keycode 96 = F12 F12 F12 F12 F12 F12 XF86Switch_VT_12
+keycode 97 =
+keycode 98 = Katakana NoSymbol Katakana
+keycode 99 = Hiragana NoSymbol Hiragana
+keycode 100 = Henkan_Mode NoSymbol Henkan_Mode
+keycode 101 = Hiragana_Katakana NoSymbol Hiragana_Katakana
+keycode 102 = Muhenkan NoSymbol Muhenkan
+keycode 103 =
+keycode 104 = KP_Enter NoSymbol KP_Enter
+keycode 105 = Control_R NoSymbol Control_R
+keycode 106 = KP_Divide KP_Divide KP_Divide KP_Divide KP_Divide KP_Divide XF86Ungrab
+keycode 107 = Print Sys_Req Print Sys_Req
+keycode 108 = Alt_R Meta_R Alt_R Meta_R
+keycode 109 = Linefeed NoSymbol Linefeed
+keycode 110 = Home NoSymbol Home
+keycode 111 = Up NoSymbol Up
+keycode 112 = Prior NoSymbol Prior
+keycode 113 = Left NoSymbol Left
+keycode 114 = Right NoSymbol Right
+keycode 115 = End NoSymbol End
+keycode 116 = Down NoSymbol Down
+keycode 117 = Next NoSymbol Next
+keycode 118 = Insert NoSymbol Insert
+keycode 119 = Delete NoSymbol Delete
+keycode 120 =
+keycode 121 = XF86AudioMute NoSymbol XF86AudioMute
+keycode 122 = XF86AudioLowerVolume NoSymbol XF86AudioLowerVolume
+keycode 123 = XF86AudioRaiseVolume NoSymbol XF86AudioRaiseVolume
+keycode 124 = XF86PowerOff NoSymbol XF86PowerOff
+keycode 125 = KP_Equal NoSymbol KP_Equal
+keycode 126 = plusminus NoSymbol plusminus
+keycode 127 = Pause Break Pause Break
+keycode 128 = XF86LaunchA NoSymbol XF86LaunchA
+keycode 129 = KP_Decimal KP_Decimal KP_Decimal KP_Decimal
+keycode 130 = Hangul NoSymbol Hangul
+keycode 131 = Hangul_Hanja NoSymbol Hangul_Hanja
+keycode 132 =
+keycode 133 = Super_L NoSymbol Super_L
+keycode 134 = Super_R NoSymbol Super_R
+keycode 135 = Menu NoSymbol Menu
+keycode 136 = Cancel NoSymbol Cancel
+keycode 137 = Redo NoSymbol Redo
+keycode 138 = SunProps NoSymbol SunProps
+keycode 139 = Undo NoSymbol Undo
+keycode 140 = SunFront NoSymbol SunFront
+keycode 141 = XF86Copy NoSymbol XF86Copy
+keycode 142 = XF86Open NoSymbol XF86Open
+keycode 143 = XF86Paste NoSymbol XF86Paste
+keycode 144 = Find NoSymbol Find
+keycode 145 = XF86Cut NoSymbol XF86Cut
+keycode 146 = Help NoSymbol Help
+keycode 147 = XF86MenuKB NoSymbol XF86MenuKB
+keycode 148 = XF86Calculator NoSymbol XF86Calculator
+keycode 149 =
+keycode 150 = XF86Sleep NoSymbol XF86Sleep
+keycode 151 = XF86WakeUp NoSymbol XF86WakeUp
+keycode 152 = XF86Explorer NoSymbol XF86Explorer
+keycode 153 = XF86Send NoSymbol XF86Send
+keycode 154 =
+keycode 155 = XF86Xfer NoSymbol XF86Xfer
+keycode 156 = XF86Launch1 NoSymbol XF86Launch1
+keycode 157 = XF86Launch2 NoSymbol XF86Launch2
+keycode 158 = XF86WWW NoSymbol XF86WWW
+keycode 159 = XF86DOS NoSymbol XF86DOS
+keycode 160 = XF86ScreenSaver NoSymbol XF86ScreenSaver
+keycode 161 = XF86RotateWindows NoSymbol XF86RotateWindows
+keycode 162 = XF86TaskPane NoSymbol XF86TaskPane
+keycode 163 = XF86Mail NoSymbol XF86Mail
+keycode 164 = XF86Favorites NoSymbol XF86Favorites
+keycode 165 = XF86MyComputer NoSymbol XF86MyComputer
+keycode 166 = XF86Back NoSymbol XF86Back
+keycode 167 = XF86Forward NoSymbol XF86Forward
+keycode 168 =
+keycode 169 = XF86Eject NoSymbol XF86Eject
+keycode 170 = XF86Eject NoSymbol XF86Eject
+keycode 171 = XF86AudioNext NoSymbol XF86AudioNext
+keycode 172 = XF86AudioPlay XF86AudioPause XF86AudioPlay XF86AudioPause
+keycode 173 = XF86AudioPrev NoSymbol XF86AudioPrev
+keycode 174 = XF86AudioStop XF86Eject XF86AudioStop XF86Eject
+keycode 175 = XF86AudioRecord NoSymbol XF86AudioRecord
+keycode 176 = XF86AudioRewind NoSymbol XF86AudioRewind
+keycode 177 = XF86Phone NoSymbol XF86Phone
+keycode 178 =
+keycode 179 = XF86Tools NoSymbol XF86Tools
+keycode 180 = XF86HomePage NoSymbol XF86HomePage
+keycode 181 = XF86Reload NoSymbol XF86Reload
+keycode 182 = XF86Close NoSymbol XF86Close
+keycode 183 =
+keycode 184 =
+keycode 185 = XF86ScrollUp NoSymbol XF86ScrollUp
+keycode 186 = XF86ScrollDown NoSymbol XF86ScrollDown
+keycode 187 = parenleft NoSymbol parenleft
+keycode 188 = parenright NoSymbol parenright
+keycode 189 = XF86New NoSymbol XF86New
+keycode 190 = Redo NoSymbol Redo
+keycode 191 = XF86Tools NoSymbol XF86Tools
+keycode 192 = XF86Launch5 NoSymbol XF86Launch5
+keycode 193 = XF86Launch6 NoSymbol XF86Launch6
+keycode 194 = XF86Launch7 NoSymbol XF86Launch7
+keycode 195 = XF86Launch8 NoSymbol XF86Launch8
+keycode 196 = XF86Launch9 NoSymbol XF86Launch9
+keycode 197 =
+keycode 198 = XF86AudioMicMute NoSymbol XF86AudioMicMute
+keycode 199 = XF86TouchpadToggle NoSymbol XF86TouchpadToggle
+keycode 200 = XF86TouchpadOn NoSymbol XF86TouchpadOn
+keycode 201 = XF86TouchpadOff NoSymbol XF86TouchpadOff
+keycode 202 =
+keycode 203 = ISO_Level5_Shift NoSymbol ISO_Level5_Shift
+keycode 204 = NoSymbol Alt_L NoSymbol Alt_L
+keycode 205 = NoSymbol Meta_L NoSymbol Meta_L
+keycode 206 = NoSymbol Super_L NoSymbol Super_L
+keycode 207 = NoSymbol Hyper_L NoSymbol Hyper_L
+keycode 208 = XF86AudioPlay NoSymbol XF86AudioPlay
+keycode 209 = XF86AudioPause NoSymbol XF86AudioPause
+keycode 210 = XF86Launch3 NoSymbol XF86Launch3
+keycode 211 = XF86Launch4 NoSymbol XF86Launch4
+keycode 212 = XF86LaunchB NoSymbol XF86LaunchB
+keycode 213 = XF86Suspend NoSymbol XF86Suspend
+keycode 214 = XF86Close NoSymbol XF86Close
+keycode 215 = XF86AudioPlay NoSymbol XF86AudioPlay
+keycode 216 = XF86AudioForward NoSymbol XF86AudioForward
+keycode 217 =
+keycode 218 = Print NoSymbol Print
+keycode 219 =
+keycode 220 = XF86WebCam NoSymbol XF86WebCam
+keycode 221 = XF86AudioPreset NoSymbol XF86AudioPreset
+keycode 222 =
+keycode 223 = XF86Mail NoSymbol XF86Mail
+keycode 224 = XF86Messenger NoSymbol XF86Messenger
+keycode 225 = XF86Search NoSymbol XF86Search
+keycode 226 = XF86Go NoSymbol XF86Go
+keycode 227 = XF86Finance NoSymbol XF86Finance
+keycode 228 = XF86Game NoSymbol XF86Game
+keycode 229 = XF86Shop NoSymbol XF86Shop
+keycode 230 =
+keycode 231 = Cancel NoSymbol Cancel
+keycode 232 = XF86MonBrightnessDown NoSymbol XF86MonBrightnessDown
+keycode 233 = XF86MonBrightnessUp NoSymbol XF86MonBrightnessUp
+keycode 234 = XF86AudioMedia NoSymbol XF86AudioMedia
+keycode 235 = XF86Display NoSymbol XF86Display
+keycode 236 = XF86KbdLightOnOff NoSymbol XF86KbdLightOnOff
+keycode 237 = XF86KbdBrightnessDown NoSymbol XF86KbdBrightnessDown
+keycode 238 = XF86KbdBrightnessUp NoSymbol XF86KbdBrightnessUp
+keycode 239 = XF86Send NoSymbol XF86Send
+keycode 240 = XF86Reply NoSymbol XF86Reply
+keycode 241 = XF86MailForward NoSymbol XF86MailForward
+keycode 242 = XF86Save NoSymbol XF86Save
+keycode 243 = XF86Documents NoSymbol XF86Documents
+keycode 244 = XF86Battery NoSymbol XF86Battery
+keycode 245 = XF86Bluetooth NoSymbol XF86Bluetooth
+keycode 246 = XF86WLAN NoSymbol XF86WLAN
+keycode 247 = XF86UWB NoSymbol XF86UWB
+keycode 248 =
+keycode 249 = XF86Next_VMode NoSymbol XF86Next_VMode
+keycode 250 = XF86Prev_VMode NoSymbol XF86Prev_VMode
+keycode 251 = XF86MonBrightnessCycle NoSymbol XF86MonBrightnessCycle
+keycode 252 = XF86BrightnessAuto NoSymbol XF86BrightnessAuto
+keycode 253 = XF86DisplayOff NoSymbol XF86DisplayOff
+keycode 254 = XF86WWAN NoSymbol XF86WWAN
+keycode 255 = XF86RFKill NoSymbol XF86RFKill
diff --git a/.config/X11/Xresources b/.config/X11/Xresources
new file mode 100644
index 0000000..294f1fb
--- /dev/null
+++ b/.config/X11/Xresources
@@ -0,0 +1,164 @@
+!! Transparency (0-1):
+st.alpha: 0.95
+st.alphaOffset: 0.1
+
+!! Set a default font and font size as below:
+st.font: MesloLGS Nerd\ Font:size=17
+
+! st.termname: st-256color
+! st.borderpx: 2
+st.background: #1d1f21
+
+/* name dark light */
+/* black 0 8 */
+/* red 1 9 */
+/* green 2 10 */
+/* yellow 3 11 */
+/* blue 4 12 */
+/* purple 5 13 */
+/* cyan 6 14 */
+/* white 7 15 */
+
+! gruvbox neomutt selected text
+*.color8: #524334
+
+/* !! gruvbox: */
+/* *.color0: #1d2021 */
+/* *.color1: #cc241d */
+/* *.color2: #98971a */
+/* *.color3: #d79921 */
+/* *.color4: #458588 */
+/* *.color5: #b16286 */
+/* *.color6: #689d6a */
+/* *.color7: #a89984 */
+/* *.color8: #928374 */
+/* *.color9: #fb4934 */
+/* *.color10: #b8bb26 */
+/* *.color11: #fabd2f */
+/* *.color12: #83a598 */
+/* *.color13: #d3869b */
+/* *.color14: #8ec07c */
+/* *.color15: #ebdbb2 */
+/* *.color256: #1d2021 */
+/* *.color257: #ebdbb2 */
+
+/* !! gruvbox light: */
+/* *.color0: #fbf1c7 */
+/* *.color1: #cc241d */
+/* *.color2: #98971a */
+/* *.color3: #d79921 */
+/* *.color4: #458588 */
+/* *.color5: #b16286 */
+/* *.color6: #689d6a */
+/* *.color7: #7c6f64 */
+/* *.color8: #928374 */
+/* *.color9: #9d0006 */
+/* *.color10: #79740e */
+/* *.color11: #b57614 */
+/* *.color12: #076678 */
+/* *.color13: #8f3f71 */
+/* *.color14: #427b58 */
+/* *.color15: #3c3836 */
+/* *.background: #fbf1c7 */
+/* *.foreground: #282828 */
+/* st.alpha: 0.9 */
+
+/* !! brogrammer: */
+/* *.foreground: #d6dbe5 */
+/* *.background: #131313 */
+/* *.color0: #1f1f1f */
+/* *.color8: #d6dbe5 */
+/* *.color1: #f81118 */
+/* *.color9: #de352e */
+/* *.color2: #2dc55e */
+/* *.color10: #1dd361 */
+/* *.color3: #ecba0f */
+/* *.color11: #f3bd09 */
+/* *.color4: #2a84d2 */
+/* *.color12: #1081d6 */
+/* *.color5: #4e5ab7 */
+/* *.color13: #5350b9 */
+/* *.color6: #1081d6 */
+/* *.color14: #0f7ddb */
+/* *.color7: #d6dbe5 */
+/* *.color15: #ffffff */
+/* *.colorBD: #d6dbe5 */
+
+/* ! base16 */
+/* *.color0: #181818 */
+/* *.color1: #ab4642 */
+/* *.color2: #a1b56c */
+/* *.color3: #f7ca88 */
+/* *.color4: #7cafc2 */
+/* *.color5: #ba8baf */
+/* *.color6: #86c1b9 */
+/* *.color7: #d8d8d8 */
+/* *.color8: #585858 */
+/* *.color9: #ab4642 */
+/* *.color10: #a1b56c */
+/* *.color11: #f7ca88 */
+/* *.color12: #7cafc2 */
+/* *.color13: #ba8baf */
+/* *.color14: #86c1b9 */
+/* *.color15: #f8f8f8 */
+
+/* !! solarized */
+/* *.color0: #073642 */
+/* *.color1: #dc322f */
+/* *.color2: #859900 */
+/* *.color3: #b58900 */
+/* *.color4: #268bd2 */
+/* *.color5: #d33682 */
+/* *.color6: #2aa198 */
+/* *.color7: #eee8d5 */
+/* *.color9: #cb4b16 */
+/* *.color8: #fdf6e3 */
+/* *.color10: #586e75 */
+/* *.color11: #657b83 */
+/* *.color12: #839496 */
+/* *.color13: #6c71c4 */
+/* *.color14: #93a1a1 */
+/* *.color15: #fdf6e3 */
+
+/* !! xterm */
+/* *.color0: #000000 */
+/* *.color1: #cd0000 */
+/* *.color2: #00cd00 */
+/* *.color3: #cdcd00 */
+/* *.color4: #0000cd */
+/* *.color5: #cd00cd */
+/* *.color6: #00cdcd */
+/* *.color7: #e5e5e5 */
+/* *.color8: #4d4d4d */
+/* *.color9: #ff0000 */
+/* *.color10: #00ff00 */
+/* *.color11: #ffff00 */
+/* *.color12: #0000ff */
+/* *.color13: #ff00ff */
+/* *.color14: #00ffff */
+/* *.color15: #aabac8 */
+/* *.background: #000000 */
+
+/* ! Dracula Xresources palette */
+/* *.foreground: #F8F8F2 */
+/* *.background: #282A36 */
+/* *.color0: #000000 */
+/* *.color8: #4D4D4D */
+/* *.color1: #FF5555 */
+/* *.color9: #FF6E67 */
+/* *.color2: #50FA7B */
+/* *.color10: #5AF78E */
+/* *.color3: #F1FA8C */
+/* *.color11: #F4F99D */
+/* *.color4: #BD93F9 */
+/* *.color12: #CAA9FA */
+/* *.color5: #FF79C6 */
+/* *.color13: #FF92D0 */
+/* *.color6: #8BE9FD */
+/* *.color14: #9AEDFE */
+/* *.color7: #BFBFBF */
+/* *.color15: #E6E6E6 */
+
+/* *.background: .color0 */
+/* *.color256: 0#1d2021 */
+/* *.color257: 15#ebdbb2 */
diff --git a/.config/X11/xbindkeysrc b/.config/X11/xbindkeysrc
new file mode 100644
index 0000000..11b227e
--- /dev/null
+++ b/.config/X11/xbindkeysrc
@@ -0,0 +1,96 @@
+# For the benefit of emacs users: -*- shell-script -*-
+###########################
+# xbindkeys configuration #
+###########################
+#
+# Version: 1.8.7
+#
+# If you edit this file, do not forget to uncomment any lines
+# that you change.
+# The pound(#) symbol may be used anywhere for comments.
+#
+# To specify a key, you can use 'xbindkeys --key' or
+# 'xbindkeys --multikey' and put one of the two lines in this file.
+#
+# The format of a command line is:
+# "command to start"
+# associated key
+#
+#
+# A list of keys is in /usr/include/X11/keysym.h and in
+# /usr/include/X11/keysymdef.h
+# The XK_ is not needed.
+#
+# List of modifier:
+# Release, Control, Shift, Mod1 (Alt), Mod2 (NumLock),
+# Mod3 (CapsLock), Mod4, Mod5 (Scroll).
+#
+
+# The release modifier is not a standard X modifier, but you can
+# use it if you want to catch release events instead of press events
+
+# By defaults, xbindkeys does not pay attention with the modifiers
+# NumLock, CapsLock and ScrollLock.
+# Uncomment the lines above if you want to pay attention to them.
+
+#keystate_numlock = enable
+#keystate_capslock = enable
+#keystate_scrolllock= enable
+
+# Examples of commands:
+
+# "xbindkeys_show"
+# control+shift + q
+#
+# # set directly keycode (here control + f with my keyboard)
+# "xterm"
+# c:41 + m:0x4
+#
+# # specify a mouse button
+# "xterm"
+# control + b:2
+
+# "notify-send xte 'keydown Shift_R'"
+# b:9 + b:4
+
+# "notify-send xte 'keyup Shift_R'"
+# b:9 + b:5
+
+# "xte 'mouseclick 3'"
+# Shift_R
+
+"xvkbd -text "\[F8]""
+ m:0x0 + b:8
+"xvkbd -text "\[Shift]"
+ m:0x0 + b:9
+"xvkbd -text "\[Shift]\[Right]""
+ m:0x0 + b:10
+"xvkbd -text 2"
+ m:0x0 + b:11
+"xvkbd -text 3"
+ m:0x0 + b:12
+
+# "xte 'keydown Control_L'"
+# b:8
+
+# "xte 'keyup Control_L'"
+# b:8 + release
+
+#"xterm -geom 50x20+20+20"
+# Shift+Mod2+alt + s
+#
+## set directly keycode (here control+alt+mod2 + f with my keyboard)
+#"xterm"
+# alt + c:0x29 + m:4 + mod2
+#
+## Control+Shift+a release event starts rxvt
+#"rxvt"
+# release+control+shift + a
+#
+## Control + mouse button 2 release event starts rxvt
+#"rxvt"
+# Control + b:2 + Release
+
+##################################
+# End of xbindkeys configuration #
+##################################
diff --git a/.config/X11/xinitrc b/.config/X11/xinitrc
new file mode 100644
index 0000000..fa3fac4
--- /dev/null
+++ b/.config/X11/xinitrc
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# userresources=$HOME/.Xresources
+# usermodmap=$HOME/.Xmodmap
+# userresourcesconfig="${XDG_CONFIG_HOME:-$HOME/.config}/Xresources"
+# usermodmapconfig="${XDG_CONFIG_HOME:-$HOME/.config}/Xmodmap"
+# sysresources=/etc/X11/xinit/.Xresources
+# sysmodmap=/etc/X11/xinit/.Xmodmap
+
+# # merge in defaults and keymaps
+# [ -f $sysresources ] && { xrdb -merge $sysresources; }
+# [ -f $sysmodmap ] && { xmodmap $sysmodmap; }
+# [ -f "$userresources" ] && { xrdb -merge "$userresources"; }
+# [ -f "$usermodmap" ] && { xmodmap "$usermodmap"; }
+# [ -f "$userresourcesconfig" ] && { xrdb -merge "$userresourcesconfig"; }
+# [ -f "$usermodmapconfig" ] && { xmodmap "$usermodmapconfig"; }
+
+# start some nice programs
+
+# if [ -d /etc/X11/xinit/xinitrc.d ] ; then
+# for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do
+# [ -x "$f" ] && . "$f"
+# done
+# unset f
+# fi
+
+printf "\n%s\n" "~/xinitrc loaded." >> ~/.local/state/xprofile.logs
+
+if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/x11/xprofile" ]; then
+ . "${XDG_CONFIG_HOME:-$HOME/.config}/x11/xprofile"
+else
+ . "$HOME/.xprofile"
+fi
+
+# twm &
+# xclock -geometry 50x50-1+1 &
+# xterm -geometry 80x50+494+51 &
+# xterm -geometry 80x20+494-0 &
+# exec xterm -geometry 80x66+0+0 -name login
+
+export $(dbus-launch)
+exec i3
diff --git a/.config/X11/xprofile b/.config/X11/xprofile
new file mode 100644
index 0000000..29250ae
--- /dev/null
+++ b/.config/X11/xprofile
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# gui -e
+
+echo "Sourced: $(date)" >> ~/.local/state/xprofile.logs
+
+xrdb "${XDG_CONFIG_HOME:-$HOME/.config}/X11/Xresources" & xrdbpid=$!
+numlockx on &
+setdp &
+
+autostart="copyq dunst pipewire syncthing remapd"
+
+for program in $autostart; do
+ pidof -sx "$program" || "$program" &
+done >/dev/null 2>&1
+
+{ sleep 5; wireplumber; } &
+[ -n "$xrdbpid" ] && wait "$xrdbpid"
diff --git a/.config/Zeal/Zeal.conf b/.config/Zeal/Zeal.conf
new file mode 100644
index 0000000..aee4b0c
--- /dev/null
+++ b/.config/Zeal/Zeal.conf
@@ -0,0 +1,52 @@
+[General]
+check_for_update=true
+hide_on_close=false
+minimize_to_systray=false
+show_systray_icon=true
+start_minimized=false
+
+[content]
+appearance=@Variant(\0\0\0\x7f\0\0\0\x12\x43ontentAppearance\0\0\0\0\x2)
+custom_css_file=/home/master/.config/Zeal/style.css
+dark_mode=true
+default_fixed_font_size=16
+default_font_family=sans-serif
+default_font_size=16
+disable_ad=true
+external_link_policy=@Variant(\0\0\0\x7f\0\0\0\x13\x45xternalLinkPolicy\0\0\0\0\0)
+fixed_font_family=DejaVu Sans Mono
+highlight_on_navigate=true
+minimum_font_size=16
+sans_serif_font_family=DejaVu Sans
+serif_font_family=DejaVu Serif
+smooth_scrolling=true
+
+[docsets]
+path=/home/master/.local/share/Zeal/Zeal/docsets
+
+[global_shortcuts]
+show=Meta+/
+
+[internal]
+install_id=7cf1e6a2-9a52-4dfc-a7de-bc1acd562804
+version=0.7.2
+
+[proxy]
+authenticate=false
+host=localhost
+ignore_ssl_errors=false
+password=
+port=9050
+type=0
+username=
+
+[search]
+fuzzy_search_enabled=true
+
+[state]
+splitter_geometry=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\x1X\0\0\x5P\0\xff\xff\xff\xff\x1\0\0\0\x1\0)
+toc_splitter_state=@ByteArray()
+window_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\a\x80\0\0\0\0\0\0\xf\x88\0\0\x4i\0\0\a\x80\0\0\0\0\0\0\xf\x88\0\0\x4i\0\0\0\x1\0\0\0\0\b\t\0\0\a\x80\0\0\0\0\0\0\xf\x88\0\0\x4i)
+
+[tabs]
+open_new_tab_after_active=true
diff --git a/.config/Zeal/style.css b/.config/Zeal/style.css
new file mode 100644
index 0000000..f8c0936
--- /dev/null
+++ b/.config/Zeal/style.css
@@ -0,0 +1,3 @@
+.main-page-content .section-contnet p {
+ font: 40px;
+}
diff --git a/.config/git/config b/.config/git/config
new file mode 100644
index 0000000..e63dac2
--- /dev/null
+++ b/.config/git/config
@@ -0,0 +1,5 @@
+[user]
+ email = dev@vikas.rocks
+ name = Vikas Kushwaha
+[init]
+ defaultBranch = master
diff --git a/.config/gotop/gotop.conf b/.config/gotop/gotop.conf
new file mode 100644
index 0000000..aeb918c
--- /dev/null
+++ b/.config/gotop/gotop.conf
@@ -0,0 +1,33 @@
+# Scale graphs to this level; 7 is the default, 2 is zoomed out.
+graphhorizontalscale=7
+# If true, start the UI with the help visible
+helpvisible=false
+# The color scheme to use. See `--list colorschemes`
+colorscheme=monokai
+# How frequently to update the UI, in nanoseconds
+updateinterval=1000000000
+# If true, show the average CPU load
+averagecpu=false
+# If true, show load per CPU
+percpuload=false
+# Temperature units. C for Celsius, F for Fahrenheit
+tempscale=C
+# If true, display a status bar
+statusbar=false
+# The network interface to monitor
+netinterface=all
+# A layout name. See `--list layouts`
+layout=default
+# The maximum log file size, in bytes
+maxlogsize=5000000
+# If set, export data as Promethius metrics on the interface:port.
+# E.g., `:8080` (colon is required, interface is not)
+#metricsexportport=
+# Display network IO in mpbs if true
+mbps=false
+# A list of enabled temp sensors. See `--list devices`
+#temperatures=
+# Enable NVidia GPU metrics.
+nvidia=false
+# To configure the NVidia refresh rate, set a duration:
+#nvidiarefresh=30s
diff --git a/.config/gtk-2.0/gtkfilechooser.ini b/.config/gtk-2.0/gtkfilechooser.ini
new file mode 100644
index 0000000..bc097de
--- /dev/null
+++ b/.config/gtk-2.0/gtkfilechooser.ini
@@ -0,0 +1,11 @@
+[Filechooser Settings]
+LocationMode=path-bar
+ShowHidden=false
+ShowSizeColumn=true
+GeometryX=393
+GeometryY=71
+GeometryWidth=1140
+GeometryHeight=855
+SortColumn=name
+SortOrder=ascending
+StartupMode=recent
diff --git a/.config/gtk-2.0/gtkrc-2.0 b/.config/gtk-2.0/gtkrc-2.0
new file mode 100644
index 0000000..73dbc57
--- /dev/null
+++ b/.config/gtk-2.0/gtkrc-2.0
@@ -0,0 +1,19 @@
+# DO NOT EDIT! This file will be overwritten by LXAppearance.
+# Any customization should be done in ~/.gtkrc-2.0.mine instead.
+
+include "/home/master/.gtkrc-2.0.mine"
+gtk-theme-name="Arc-Dark"
+gtk-icon-theme-name="Gruvbox-Plus-Dark"
+gtk-font-name="Fira Sans 14"
+gtk-cursor-theme-size=24
+gtk-toolbar-style=GTK_TOOLBAR_ICONS
+gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
+gtk-button-images=1
+gtk-menu-images=1
+gtk-enable-event-sounds=1
+gtk-enable-input-feedback-sounds=1
+gtk-xft-antialias=1
+gtk-xft-hinting=1
+gtk-xft-hintstyle="hintmedium"
+gtk-xft-rgba="none"
+gtk-modules="canberra-gtk-module:gail:atk-bridge"
diff --git a/.config/gtk-2.0/gtkrc-2.0.bak b/.config/gtk-2.0/gtkrc-2.0.bak
new file mode 100644
index 0000000..c8d0af9
--- /dev/null
+++ b/.config/gtk-2.0/gtkrc-2.0.bak
@@ -0,0 +1,20 @@
+# DO NOT EDIT! This file will be overwritten by LXAppearance.
+# Any customization should be done in ~/.gtkrc-2.0.mine instead.
+
+include "/home/master/.gtkrc-2.0.mine"
+gtk-theme-name="Arc-Dark"
+gtk-icon-theme-name="Gruvbox-Material-Dark"
+gtk-font-name="Fira Sans 14"
+gtk-cursor-theme-name="Qogir-dark"
+gtk-cursor-theme-size=24
+gtk-toolbar-style=GTK_TOOLBAR_ICONS
+gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
+gtk-button-images=1
+gtk-menu-images=1
+gtk-enable-event-sounds=1
+gtk-enable-input-feedback-sounds=1
+gtk-xft-antialias=1
+gtk-xft-hinting=1
+gtk-xft-hintstyle="hintfull"
+gtk-xft-rgba="none"
+gtk-modules="canberra-gtk-module:gail:atk-bridge"
diff --git a/.config/gtk-3.0/bookmarks b/.config/gtk-3.0/bookmarks
new file mode 100644
index 0000000..ce1b7aa
--- /dev/null
+++ b/.config/gtk-3.0/bookmarks
@@ -0,0 +1 @@
+file:///mnt
diff --git a/.config/gtk-3.0/settings.ini b/.config/gtk-3.0/settings.ini
new file mode 100644
index 0000000..1dea2a0
--- /dev/null
+++ b/.config/gtk-3.0/settings.ini
@@ -0,0 +1,20 @@
+[Settings]
+gtk-theme-name=Arc-Dark
+gtk-icon-theme-name=Gruvbox-Plus-Dark
+gtk-sound-theme-name=Smooth
+gtk-application-prefer-dark-theme=true
+# GTK3 ignores bold or italic attributes.
+gtk-font-name=Fira Sans 14
+gtk-menu-images=1
+gtk-button-images=1
+gtk-toolbar-style=GTK_TOOLBAR_ICONS
+gtk-cursor-theme-name=Qogir-dark
+gtk-cursor-theme-size=24
+gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
+gtk-enable-event-sounds=1
+gtk-enable-input-feedback-sounds=1
+gtk-xft-antialias=1
+gtk-xft-hinting=1
+gtk-xft-hintstyle=hintmedium
+gtk-xft-rgba=none
+gtk-modules=canberra-gtk-module:gail:atk-bridge
diff --git a/.config/htop/htoprc b/.config/htop/htoprc
new file mode 100644
index 0000000..4a3ad55
--- /dev/null
+++ b/.config/htop/htoprc
@@ -0,0 +1,63 @@
+# Beware! This file is rewritten by htop when settings are changed in the interface.
+# The parser is also very primitive, and not human-friendly.
+htop_version=3.3.0
+config_reader_min_version=3
+fields=0 48 17 18 38 39 40 2 46 47 49 1
+hide_kernel_threads=1
+hide_userland_threads=0
+hide_running_in_container=0
+shadow_other_users=0
+show_thread_names=0
+show_program_path=1
+highlight_base_name=0
+highlight_deleted_exe=1
+shadow_distribution_path_prefix=0
+highlight_megabytes=1
+highlight_threads=1
+highlight_changes=0
+highlight_changes_delay_secs=5
+find_comm_in_cmdline=1
+strip_exe_from_cmdline=1
+show_merged_command=0
+header_margin=1
+screen_tabs=0
+detailed_cpu_time=0
+cpu_count_from_one=0
+show_cpu_usage=1
+show_cpu_frequency=0
+show_cpu_temperature=0
+degree_fahrenheit=0
+update_process_names=0
+account_guest_in_cpu_meter=0
+color_scheme=0
+enable_mouse=1
+delay=15
+hide_function_bar=0
+header_layout=two_50_50
+column_meters_0=LeftCPUs Memory Swap
+column_meter_modes_0=1 1 1
+column_meters_1=RightCPUs Tasks LoadAverage Uptime
+column_meter_modes_1=1 2 2 2
+tree_view=0
+sort_key=46
+tree_sort_key=0
+sort_direction=-1
+tree_sort_direction=1
+tree_view_always_by_pid=0
+all_branches_collapsed=0
+screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command
+.sort_key=PERCENT_CPU
+.tree_sort_key=PID
+.tree_view_always_by_pid=0
+.tree_view=0
+.sort_direction=-1
+.tree_sort_direction=1
+.all_branches_collapsed=0
+screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command
+.sort_key=IO_RATE
+.tree_sort_key=PID
+.tree_view_always_by_pid=0
+.tree_view=0
+.sort_direction=-1
+.tree_sort_direction=1
+.all_branches_collapsed=0
diff --git a/.config/i3/config b/.config/i3/config
new file mode 100644
index 0000000..47a3b3e
--- /dev/null
+++ b/.config/i3/config
@@ -0,0 +1,644 @@
+# i3 config file (v4)
+# Please see http://i3wm.org/docs/userguide.html for a complete reference!
+
+
+
+
+##################
+### Autostart: ###
+##################
+
+# exec --no-startup-id sh ~/.xprofile
+# exec_always xrdb ~/.Xresources
+
+# important for fonts and anti aliasing
+# exec --no-startup-id xsettingsd &
+
+# pulseaudio system tray
+# exec --no-startup-id pasystray
+
+exec st -c dropdown_tmuxdd -e tmux
+
+################################
+### Commonly Used Variables: ###
+################################
+# - Below defined are some of the very common variables that users like to customise
+# - For Keybindings search: Commonly Used Keybindings in this document
+# - Make sure that you give the absolute path to the binary / program / executable
+# - You may specify any additional arguments required by the binary / executable
+
+### Wallpaper: ###
+# - You need to specify homescreen wallpaper using azote
+set $lockScreenWallpaper '/usr/share/wallpapers/garuda-wallpapers/Garuda-Desert.png'
+set $homeScreenWallpaper '/usr/share/wallpapers/garuda-wallpapers/background.jpg'
+
+### Applications: ###
+set $preferredTerminalEmulator $TERMINAL
+set $preferredBrowser torbrowser open
+set $preferredFileManager thunar
+set $preferredMailClient $MAIL
+set $preferredTextEditor $EDITOR
+set $preferredScreenCaptureTool flameshot gui
+
+### Movement keys ###
+set $left h
+set $down j
+set $up k
+set $right l
+
+# set modifier
+set $super Mod4
+set $alt Mod1
+
+
+
+
+###########################################
+### Commonly Used Application Keybinds: ###
+###########################################
+
+bindsym $super+F2 exec --no-startup-id dmenu-unicode
+bindsym $super+Shift+F2 exec --no-startup-id dmenu-unicode get-code
+bindsym $super+F3 exec --no-startup-id st -c "dropdown_sender" -e fsend
+bindsym $super+F4 exec --no-startup-id passmenu
+bindsym $super+Shift+F4 exec --no-startup-id passmenu --type
+bindsym $super+F5 exec --no-startup-id dmenu-zeal
+bindsym $super+F7 exec --no-startup-id sh -c 'find ~/.librewolf -mindepth 1 -maxdepth 1 -type d -name '????????.*' -printf "%f\n" | cut -d. -f2- | dmenu -p "LibreWolf Profile" | xargs -I{} setsid -f librewolf -P "{}"'
+bindsym $super+b exec --no-startup-id librewolf-open
+bindsym $super+c exec --no-startup-id edit-graphical-buffer
+bindsym $super+x exec --no-startup-id toggle-xeyes
+bindsym $super+i exec --no-startup-id sh -c 'xdotool type "$(grep -v "^#\|^\s*$" ~/Documents/Notes/bookmarks.txt | tac | dmenu -i -l 50 | cut -d\ -f1)"'
+bindsym $super+Shift+z exec --no-startup-id dmenu-zeal
+bindsym $super+Shift+b exec --no-startup-id librewolf-open "$(xprint)"
+bindsym $super+period exec --no-startup-id sh -c 'xdotool click --clearmodifiers 1 && xdotool keyup super'
+bindsym $super+slash exec --no-startup-id sh -c 'xdotool click --clearmodifiers 3 && xdotool keyup super'
+bindsym $super+comma exec --no-startup-id scrcpy-k
+bindsym $super+$alt+s exec --no-startup-id sh -c 'bm="$(xprint)" && echo "$bm" >> ~/Documents/Notes/bookmarks.txt && notify-send " Bookmark added" "$bm" || notify-send "❌ Failed to add bookmark" "$bm"'
+
+bindsym $super+$alt+F1 exec --no-startup-id _macro_F1
+bindsym $super+$alt+F2 exec --no-startup-id _macro_F2
+bindsym $super+$alt+F3 exec --no-startup-id _macro_F3
+bindsym $super+$alt+F4 exec --no-startup-id _macro_F4
+bindsym $super+$alt+F5 exec --no-startup-id _macro_F5
+bindsym $super+$alt+F6 exec --no-startup-id _macro_F6
+bindsym $super+$alt+F7 exec --no-startup-id _macro_F7
+bindsym $super+$alt+F8 exec --no-startup-id _macro_F8
+bindsym $super+$alt+F9 exec --no-startup-id _macro_F9
+bindsym $super+$alt+F10 exec --no-startup-id _macro_F10
+bindsym $super+$alt+F11 exec --no-startup-id _macro_F11
+bindsym $super+$alt+F12 exec --no-startup-id _macro_F12
+
+### Screen Capturing & Print Screen: ###
+
+bindsym $super+F9 exec $preferredScreenCaptureTool
+bindsym Print exec --no-startup-id flameshot screen
+bindsym Ctrl+Print exec --no-startup-id $preferredScreenCaptureTool
+
+### Start a Terminal Emulator: ###
+# - You can change the preferredTerminalEmulator variable
+# - $TERMINAL & xfce4-terminal can also be started using their individual keybindings
+
+bindsym $super+Return exec --no-startup-id $preferredTerminalEmulator
+bindsym $super+t exec --no-startup-id xfce4-terminal
+
+font pango: source code pro 16
+
+# Use Mouse+$super to drag floating windows to their wanted position
+floating_modifier $super
+
+
+# hide/unhide i3status bar
+bindsym $super+m bar mode toggle
+
+# start dmenu (a program launcher)
+set $i3dmenu i3-dmenu-desktop --dmenu="dmenu -i"
+
+bindsym $super+Shift+d exec --no-startup-id $i3dmenu
+bindsym $super+d exec --no-startup-id dmenu_run
+
+
+
+
+###################
+### Media Keys: ###
+###################
+
+# Screen brightness controls
+set $brightnessUp brightness up
+set $brightnessDown brightness down
+# set $brightnessUp brightnessctl set +5% && notify-send -r 4023423 "brightness: $(( $(brightnessctl g) / 1200 ))%"
+# set $brightnessDown brightnessctl set 5%- && notify-send -r 4023423 "brightness: $(( $(brightnessctl g) / 1200 ))%"
+
+# Use pactl to adjust volume in PulseAudio.
+set $refresh_i3status killall -SIGUSR1 i3status
+set $raiseVolume volctl up && pkill -SIGRTMIN+4 i3block
+set $lowerVolume volctl down && pkill -SIGRTMIN+4 i3block
+# pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status
+# pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status
+set $muteOutput pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status
+set $muteInput pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status
+
+# music control
+set $nextAudio playerctl next
+set $prevAudio playerctl previous
+set $playAudio playerctl play-pause
+set $stopAudio playerctl stop
+
+bindsym XF86MonBrightnessUp exec $brightnessUp
+bindsym XF86MonBrightnessDown exec $brightnessDown
+
+bindsym XF86AudioRaiseVolume exec --no-startup-id $raiseVolume
+bindsym XF86AudioLowerVolume exec --no-startup-id $lowerVolume
+bindsym XF86AudioMute exec --no-startup-id $muteOutput
+bindsym XF86AudioMicMute exec --no-startup-id $muteInput
+#change volume
+#bindsym XF86AudioRaiseVolume exec pulseaudio-ctl up
+#bindsym XF86AudioLowerVolume exec pulseaudio-ctl down
+#bindsym XF86AudioMute exec pulseaudio-ctl mute
+
+bindsym XF86AudioNext exec $nextAudio
+bindsym XF86AudioPrev exec $prevAudio
+bindsym XF86AudioPlay exec $playAudio
+bindsym XF86AudioStop exec $stopAudio
+
+
+bindsym $super+Ctrl+Right exec $brightnessUp
+bindsym $super+Ctrl+Left exec $brightnessDown
+
+bindsym $super+Ctrl+Up exec --no-startup-id $raiseVolume
+bindsym $super+Ctrl+Down exec --no-startup-id $lowerVolume
+bindsym $super+Ctrl+Insert exec --no-startup-id $muteOutput
+bindsym $super+Ctrl+Del exec --no-startup-id $muteInput
+
+bindsym $super+Ctrl+Next exec $nextAudio
+bindsym $super+Ctrl+Prior exec $prevAudio
+bindsym $super+Ctrl+Home exec $playAudio
+bindsym $super+Ctrl+End exec $stopAudio
+
+
+# bindsym XF86TouchpadToggle exec ~/bin/toggletouchpad.sh
+bindsym XF86PowerOff exec --no-startup-id notify-send "Power Off"
+bindsym XF86PowerDown exec --no-startup-id notify-send "Power Down"
+
+# Print screen
+bindsym $super+Print --release exec --no-startup-id i3-scrot -w
+bindsym $super+Shift+Print --release exec --no-startup-id i3-scrot -s
+
+
+
+
+#########################
+### window management ###
+#########################
+
+# kill focused window
+bindsym $super+q kill
+
+# split in horizontal orientation
+# bindsym $super+apostrophe split h
+# split in vertical orientation
+# bindsym $super+v split v
+
+bindsym $super+apostrophe split toggle
+
+# change container layout (stacked, tabbed, toggle split)
+bindsym $super+s layout stacking
+bindsym $super+w layout tabbed
+bindsym $super+e layout toggle split # try 'layout default' here
+
+# enter fullscreen mode for the focused container
+bindsym $super+f fullscreen toggle
+bindsym $super+Shift+f fullscreen toggle global
+# change focus between tiling / floating windows
+bindsym $super+space focus mode_toggle
+# toggle tiling / floating
+bindsym $super+Shift+space floating toggle
+# toggle sticky
+bindsym $super+Shift+s sticky toggle
+
+# focus the parent container
+bindsym $super+a focus parent
+# focus the child container
+bindsym $super+Shift+a focus child
+
+# move the currently focused window to the scratchpad
+bindsym $super+Shift+minus move scratchpad
+# Show the next scratchpad window or hide the focused scratchpad window.
+# If there are multiple scratchpad windows, this command cycles through them.
+bindsym $super+minus scratchpad show
+
+# reload the configuration file
+bindsym $super+Shift+c reload
+# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
+bindsym $super+Shift+r restart
+bindsym $super+Shift+e exec --no-startup-id $TERMINAL -e nvim ~/.config/i3/config
+
+# resize window (you can also use the mouse for that)
+mode "resize" {
+ bindsym $left resize shrink width 30 px or 5 ppt
+ bindsym $down resize grow height 30 px or 5 ppt
+ bindsym $up resize shrink height 30 px or 5 ppt
+ bindsym $right resize grow width 30 px or 5 ppt
+
+ bindsym Left resize shrink width 1 px or 1 ppt
+ bindsym Down resize grow height 1 px or 1 ppt
+ bindsym Up resize shrink height 1 px or 1 ppt
+ bindsym Right resize grow width 1 px or 1 ppt
+
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+
+}
+bindsym $super+r mode "resize"
+
+
+# change focus
+bindsym $super+$left focus left
+bindsym $super+$down focus down
+bindsym $super+$up focus up
+bindsym $super+$right focus right
+
+# alternatively, you can use the cursor keys:
+bindsym $super+Left focus left
+bindsym $super+Down focus down
+bindsym $super+Up focus up
+bindsym $super+Right focus right
+
+# move focused window
+bindsym $super+Shift+$left move container left 30
+bindsym $super+Shift+$down move container down 30
+bindsym $super+Shift+$up move container up 30
+bindsym $super+Shift+$right move container right 30
+
+# alternatively, you can use the cursor keys:
+bindsym $super+Shift+Left move left
+bindsym $super+Shift+Down move down
+bindsym $super+Shift+Up move up
+bindsym $super+Shift+Right move right
+
+
+##################
+### Workspaces ###
+##################
+
+# navigate workspaces
+bindsym $super+bracketleft workspace $ws1
+bindsym $super+n workspace next
+bindsym $super+p workspace prev
+bindsym $super+bracketright workspace $ws10
+
+bindsym $super+Home workspace $ws1
+bindsym $super+Prior workspace prev
+bindsym $super+Next workspace next
+bindsym $super+End workspace $ws10
+
+bindsym $super+Tab workspace back_and_forth
+bindsym $super+Shift+Tab move container to workspace back_and_forth; workspace back_and_forth
+bindsym $super+$alt+Tab move container to workspace back_and_forth
+
+bindsym $super+o focus output right
+bindsym $super+Shift+o move container to output right; focus output right
+bindsym $super+$alt+o move container to output right
+bindsym $super+semicolon workspace back_and_forth
+bindsym $super+Shift+semicolon move container to workspace back_and_forth; focus output right
+bindsym $super+$alt+semicolon move container to workspace back_and_forth
+
+bindsym $super+Ctrl+semicolon workspace back_and_forth
+bindsym $super+Ctrl+Shift+semicolon move container to workspace back_and_forth; workspace back_and_forth
+bindsym $super+Ctrl+$alt+semicolon move container to workspace back_and_forth
+
+
+# move containers
+bindsym $super+Shift+bracketleft move container to workspace $ws1 ; workspace $ws1
+bindsym $super+Shift+n move container to workspace next ; workspace next
+bindsym $super+Shift+p move container to workspace prev ; workspace prev
+bindsym $super+Shift+bracketright move container to workspace $ws10; workspace $ws10
+
+bindsym $super+Shift+Home move container to workspace $ws1 ; workspace $ws1
+bindsym $super+Shift+Prior move container to workspace prev ; workspace prev
+bindsym $super+Shift+Next move container to workspace next ; workspace next
+bindsym $super+Shift+End move container to workspace $ws10; workspace $ws10
+
+
+# send containers
+bindsym $super+$alt+bracketleft move container to workspace $ws1
+bindsym $super+$alt+n move container to workspace next
+bindsym $super+$alt+p move container to workspace prev
+bindsym $super+$alt+bracketright move container to workspace $ws10
+
+bindsym $super+$alt+Home move container to workspace $ws1
+bindsym $super+$alt+Prior move container to workspace prev
+bindsym $super+$alt+Next move container to workspace next
+bindsym $super+$alt+End move container to workspace $ws10
+
+
+# set $ws1 " 1 󰣇 "
+# set $ws2 " 2  "
+# set $ws3 " 3  "
+# set $ws4 " 4  "
+# set $ws5 " 5  "
+# set $ws6 " 6  "
+# set $ws7 " 7 󰈹 "
+# set $ws8 " 8 󰈙 "
+# set $ws9 " 9  "
+# set $ws10 " 10  "
+
+set $ws1 "1:󰎤"
+set $ws2 "2:󰎧"
+set $ws3 "3:󰎪"
+set $ws4 "4:󰎭"
+set $ws5 "5:󰎱"
+set $ws6 "6:󰎳"
+set $ws7 "7:󰎶"
+set $ws8 "8:󰎹"
+set $ws9 "9:󰎼"
+set $ws10 "10:󰽽"
+
+
+# switch to workspace
+bindsym $super+1 workspace $ws1
+bindsym $super+2 workspace $ws2
+bindsym $super+3 workspace $ws3
+bindsym $super+4 workspace $ws4
+bindsym $super+5 workspace $ws5
+bindsym $super+6 workspace $ws6
+bindsym $super+7 workspace $ws7
+bindsym $super+8 workspace $ws8
+bindsym $super+9 workspace $ws9
+bindsym $super+0 workspace $ws10
+
+
+# Move to workspace with focused container
+bindsym $super+Shift+1 move container to workspace $ws1; workspace $ws1
+bindsym $super+Shift+2 move container to workspace $ws2; workspace $ws2
+bindsym $super+Shift+3 move container to workspace $ws3; workspace $ws3
+bindsym $super+Shift+4 move container to workspace $ws4; workspace $ws4
+bindsym $super+Shift+5 move container to workspace $ws5; workspace $ws5
+bindsym $super+Shift+6 move container to workspace $ws6; workspace $ws6
+bindsym $super+Shift+7 move container to workspace $ws7; workspace $ws7
+bindsym $super+Shift+8 move container to workspace $ws8; workspace $ws8
+bindsym $super+Shift+9 move container to workspace $ws9; workspace $ws9
+bindsym $super+Shift+0 move container to workspace $ws10; workspace $ws10
+
+
+# move focused container to workspace
+bindsym $super+$alt+1 move container to workspace $ws1
+bindsym $super+$alt+2 move container to workspace $ws2
+bindsym $super+$alt+3 move container to workspace $ws3
+bindsym $super+$alt+4 move container to workspace $ws4
+bindsym $super+$alt+5 move container to workspace $ws5
+bindsym $super+$alt+6 move container to workspace $ws6
+bindsym $super+$alt+7 move container to workspace $ws7
+bindsym $super+$alt+8 move container to workspace $ws8
+bindsym $super+$alt+9 move container to workspace $ws9
+bindsym $super+$alt+0 move container to workspace $ws10
+
+
+workspace $ws1 output "eDP-1-1"
+workspace $ws2 output "eDP-1-1"
+workspace $ws3 output "eDP-1-1"
+workspace $ws4 output "eDP-1-1"
+workspace $ws5 output "eDP-1-1"
+
+workspace $ws6 output "HDMI-0"
+workspace $ws7 output "HDMI-0"
+workspace $ws8 output "HDMI-0"
+workspace $ws9 output "HDMI-0"
+workspace $ws10 output "HDMI-0"
+workspace "12: W " output "HDMI-0"
+
+
+####################
+### Window rules ###
+####################
+
+# assign [class="Tor Browser"] $ws6
+# assign [class="librewolf"] $ws7
+# assign [class="Zeal"] $ws8
+
+# window rules, you can find the window class using xprop
+for_window [class=".*"] border pixel 4
+assign [class=URxvt] 1
+for_window [class=Viewnior|feh|Audacious|File-roller|Lxappearance|Lxtask|Pavucontrol|upgrade2ultimate.sh] floating enable
+for_window [class=URxvt|firedragon|Geany|Evince|Soffice|libreoffice*|mpv|Ghb|Xfburn|Gimp*|Inkscape|Vlc|Lxappearance|Audacity] focus
+for_window [class=Xfburn|GParted|System-config-printer.py|Lxtask|Pavucontrol|Exo-helper*|Lxrandr|Arandr] focus
+
+# Open specific applications in floating mode
+for_window [title="alsamixer"] floating enable border pixel 1
+for_window [class="calamares"] floating enable border normal
+for_window [class="Clipgrab"] floating enable
+for_window [title="File Transfer*"] floating enable
+for_window [class="bauh"] floating enable
+for_window [class="Galculator"] floating enable border pixel 1
+for_window [class="GParted"] floating enable border normal
+for_window [title="i3_help"] floating enable sticky enable border normal
+for_window [class="Lightdm-settings"] floating enable
+for_window [class="Lxappearance"] floating enable border normal
+for_window [class="Garuda Settings Manager"] floating enable border normal
+for_window [title="MuseScore: Play Panel"] floating enable
+for_window [class="azote"] floating enable sticky enable border normal
+for_window [class="Oblogout"] fullscreen enable
+for_window [class="octopi"] floating enable
+for_window [title="About Pale Moon"] floating enable
+for_window [class="Pamac-manager"] floating enable
+for_window [class="Pamac-updater"] floating enable
+for_window [class="Pavucontrol"] floating enable
+for_window [class="Qtconfig-qt4"] floating enable border normal
+for_window [class="qt5ct"] floating enable sticky enable border normal
+#for_window [title="sudo"] floating enable border normal
+for_window [class="Simple-scan"] floating enable border normal
+for_window [class="(?i)System-config-printer.py"] floating enable border normal
+for_window [class="Skype"] floating enable border normal
+for_window [class="Timeshift-gtk"] floating enable border normal
+for_window [class="(?i)virtualbox"] floating enable border normal
+for_window [class="Xfburn"] floating enable
+for_window [class="garuda-welcome"] floating enable
+for_window [class="Artha"] floating enable
+for_window [class="Tk"] floating enable border normal
+for_window [title="Swing"] floating enable move position center
+for_window [class="copyq"] floating enable
+for_window [class="tabbed"] floating enable border normal
+for_window [class="Yad"] floating enable border normal
+for_window [class="Dialog"] move position center
+for_window [class="KeePassXC"] move position center
+for_window [class="sun-applet-Main"] floating enable move position center
+for_window [window_type='dialog'] move position center
+for_window [title="Android Emulator - *"] floating enable border none sticky enable
+for_window [title="Emulator"] floating enable border none sticky enable
+for_window [class="mpv"] floating enable
+# for_window [class="Zeal"] floating enable move position below
+
+# #---Dropdown Windows---# #
+# General dropdown window traits. The order can matter.
+for_window [class="dropdown_*|tridactyl_*"] floating enable
+for_window [class="dropdown_*|tridactyl_*"] move scratchpad
+for_window [class="dropdown_*|tridactyl_*"] sticky enable
+for_window [class="dropdown_*|tridactyl_*"] scratchpad show
+for_window [class="dropdown_*"] move position center
+for_window [class="dropdown_tmuxdd"] scratchpad hide
+# for_window [class="dropdown_tmuxdd"] resize set 625 450
+# for_window [class="dropdown_dropdowncalc"] resize set 800 300
+# for_window [class="dropdown_tmuxdd"] border pixel 3
+# for_window [class="dropdown_dropdowncalc"] border pixel 2
+
+# setup xeyes rules
+for_window [class="XEyes"] floating enable
+for_window [class="XEyes"] sticky enable
+for_window [class="XEyes"] border pixel 0
+for_window [class="XEyes"] resize set 500 400
+for_window [class="XEyes"] move position 700 300
+# for_window [class="XEyes"] resize set 125 100
+# for_window [class="XEyes"] move position 1789 6
+
+# colour of border, background, text, indicator, and child_border
+client.focused #bf616a #2f343f #d8dee8 #bf616a #d8dee8
+client.focused_inactive #2f343f #2f343f #d8dee8 #2f343f #2f343f
+client.unfocused #2f343f #2f343f #d8dee8 #2f343f #2f343f
+client.urgent #2f343f #2f343f #d8dee8 #2f343f #2f343f
+client.placeholder #2f343f #2f343f #d8dee8 #2f343f #2f343f
+client.background #2f343f
+
+
+# change borders ?Convert this into a mode
+# bindsym $super+u border none
+# bindsym $super+y border pixel 1
+# bindsym $super+i border normal
+
+
+# panel
+# Start i3bar to display a workspace bar
+
+bar {
+ output primary
+ status_command exec i3blocks
+ bindsym --release button3 exec jgmenu --at-pointer
+ workspace_min_width 40
+ strip_workspace_numbers yes
+ #strip_workspace_name yes|no
+ # defaults
+ #colors {
+ #background #2f343f
+ #statusline #FFFFFF
+ #separator #666666
+
+ #focused_workspace #4C7899 #285577 #FFFFFF
+ #active_workspace #333333 #222222 #FFFFFF
+ #inactive_workspace #333333 #222222 #888888
+ #urgent_workspace #2F343A #900000 #FFFFFF
+ ##binding_mode #2F343A #900000 #FFFFFF
+ ## colour of border, background, and text
+ #}
+ colors {
+ background #2f343f
+ statusline #EEEEEE
+ separator #666666
+
+ focused_workspace #2f343f #2f343f #CCFFFF
+ active_workspace #2f343f #2f343f #EEEEEE
+ inactive_workspace #2f343f #2f343f #888888
+ urgent_workspace #AAFFFF #2f343f #AAFFFF
+ #binding_mode #2f343f #2f343f #EEEEEE
+ # colour of border, background, and text
+ }
+}
+
+
+bar {
+ output nonprimary
+ bindsym --release button3 exec jgmenu --at-pointer
+ workspace_min_width 40
+ strip_workspace_numbers yes
+ #strip_workspace_name yes|no
+ colors {
+ background #2f343f
+ statusline #EEEEEE
+ separator #666666
+
+ focused_workspace #2f343f #2f343f #AAFFFF
+ active_workspace #2f343f #2f343f #CCCCCC
+ inactive_workspace #2f343f #2f343f #888888
+ urgent_workspace #AACCFF #2f343f #AACCFF
+ #binding_mode #2f343f #2f343f #EEEEEE
+ # colour of border, background, and text
+ }
+}
+
+#############################
+### settings for i3-gaps: ###
+#############################
+
+# Set inner/outer gaps
+gaps inner 0
+gaps outer -2
+
+# Additionally, you can issue commands with the following syntax. This is useful to bind keys to changing the gap size.
+# gaps inner|outer current|all set|plus|minus <px>
+# gaps inner all set 10
+# gaps outer all plus 5
+
+# Smart gaps (gaps used if only more than one container on the workspace)
+smart_gaps on
+
+# Smart borders (draw borders around container only if it is not the only container on this workspace)
+# on|no_gaps (on=always activate and no_gaps=only activate if the gap size to the edge of the screen is 0)
+smart_borders on
+
+# Press $super+Shift+g to enter the gap mode. Choose o or i for modifying outer/inner gaps. Press one of + / - (in-/decrement for current workspace) or 0 (remove gaps for current workspace). If you also press Shift with these keys, the change will be global for all workspaces.
+set $mode_gaps Gaps: (o) outer, (i) inner
+set $mode_gaps_outer Outer Gaps: +|-|0 (local), Shift + +|-|0 (global)
+set $mode_gaps_inner Inner Gaps: +|-|0 (local), Shift + +|-|0 (global)
+bindsym $super+Shift+g mode "$mode_gaps"
+
+mode "$mode_gaps" {
+ bindsym o mode "$mode_gaps_outer"
+ bindsym i mode "$mode_gaps_inner"
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+mode "$mode_gaps_inner" {
+ bindsym plus gaps inner current plus 5
+ bindsym minus gaps inner current minus 5
+ bindsym 0 gaps inner current set 0
+
+ bindsym Shift+plus gaps inner all plus 5
+ bindsym Shift+minus gaps inner all minus 5
+ bindsym Shift+0 gaps inner all set 0
+
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+mode "$mode_gaps_outer" {
+ bindsym plus gaps outer current plus 5
+ bindsym minus gaps outer current minus 5
+ bindsym 0 gaps outer current set 0
+
+ bindsym Shift+plus gaps outer all plus 5
+ bindsym Shift+minus gaps outer all minus 5
+ bindsym Shift+0 gaps outer all set 0
+
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+
+# Set shut down, restart and locking features
+bindsym $super+BackSpace mode "$mode_system"
+set $mode_system (l)ock (e)xit switch_(u)ser (s)uspend (h)ibernate (r)eboot (Shift+s)hutdown
+mode "$mode_system" {
+ bindsym l exec --no-startup-id i3exit lock, mode "default"
+ bindsym e exec --no-startup-id i3exit logout, mode "default"
+ bindsym u exec --no-startup-id i3exit switch_user, mode "default"
+ bindsym s exec --no-startup-id i3exit suspend, mode "default"
+ bindsym h exec --no-startup-id i3exit hibernate, mode "default"
+ bindsym r exec --no-startup-id i3exit reboot, mode "default"
+ bindsym Shift+s exec --no-startup-id i3exit shutdown, mode "default"
+
+ # exit system mode: "Enter" or "Escape"
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+# TODO: create your own i3exit script as ?syst-power
+
+# Lock screen
+bindsym $super+Escape exec i3lock -t -i $lockScreenWallpaper
+
+# exec_always xrandr --output eDP-1-1-1 --auto --primary
diff --git a/.config/i3blocks/config b/.config/i3blocks/config
new file mode 100644
index 0000000..638f638
--- /dev/null
+++ b/.config/i3blocks/config
@@ -0,0 +1,71 @@
+# i3blocks configuration file
+#
+# The i3blocks man page describes the usage of the binary,
+# and its website describes the configuration:
+# https://vivien.github.io/i3blocks
+#
+# List of valid properties:
+# align
+# color
+# command
+# full_text
+# instance
+# interval
+# label
+# min_width
+# name
+# separator
+# separator_block_width
+# short_text
+# signal
+# urgent
+
+
+# Global properties
+separator=false
+separator_block_width=35
+
+# Guess the weather hourly
+[weather]
+separator=true
+separator_block_width=50
+command=i3weather
+interval=1800
+color=#A4C2F4
+
+[badwidth]
+seprator=false
+command=echo "$(i3bandwidth)"
+interval=1
+
+[wifi]
+# command=echo "📡 $(i3wifi wlp0s20f3)"
+command=i3wifi wlp0s20f0u9
+interval=1
+
+[battery]
+command=i3battery
+interval=1
+
+[cpu]
+command=echo " $(i3cpu)"
+interval=3
+
+[memory]
+separator=true
+separator_block_width=50
+command=echo " $(i3memory)"
+interval=1
+
+[datetime]
+separator=false
+separator_block_width=25
+# command=case "$BLOCK_BUTTON" in 1) TERM=256colors clearx -n 'cal -y --color=always | less' ;; 2) $TERMINAL -e nvim ~/.config/i3blocks/config ;; esac; date +'🕒 %H:%M:%S 🗓️ %a %d.%m.%Y '
+command=case "$BLOCK_BUTTON" in 1) $TERMINAL -e sh -c 'cal -y --color=always | less' ;; 2) $TERMINAL -e nvim ~/.config/i3blocks/config ;; esac; date +' %H:%M:%S 󰃭 %a %d.%m.%Y '
+color=#CCFFFF
+interval=1
+
+# [ip]
+# command=hostname -i # | awk '{ print "IP:" $1 }'
+# interval=once
+# color=#91E78B
diff --git a/.config/i3blocks/systeminfo b/.config/i3blocks/systeminfo
new file mode 100644
index 0000000..68a6944
--- /dev/null
+++ b/.config/i3blocks/systeminfo
@@ -0,0 +1,50 @@
+# i3blocks configuration file
+#
+# The i3blocks man page describes the usage of the binary,
+# and its website describes the configuration:
+# https://vivien.github.io/i3blocks
+#
+# List of valid properties:
+# align
+# color
+# command
+# full_text
+# instance
+# interval
+# label
+# min_width
+# name
+# separator
+# separator_block_width
+# short_text
+# signal
+# urgent
+
+
+# Global properties
+separator=false
+separator_block_width=35
+
+[badwidth]
+seprator=false
+command=echo "$(i3bandwidth)"
+interval=1
+
+[wifi]
+# command=echo "📡 $(i3wifi wlp0s20f3)"
+command=i3wifi wlp0s20f3
+interval=1
+
+[battery]
+command=i3battery
+interval=1
+
+[cpu]
+command=echo " $(i3cpu)"
+interval=3
+
+[memory]
+separator=true
+separator_block_width=50
+command=echo " $(i3memory)"
+interval=1
diff --git a/.config/ipython/profile_default/db/dhist b/.config/ipython/profile_default/db/dhist
new file mode 100644
index 0000000..a56d871
--- /dev/null
+++ b/.config/ipython/profile_default/db/dhist
Binary files differ
diff --git a/.config/ipython/profile_default/history.sqlite b/.config/ipython/profile_default/history.sqlite
new file mode 100644
index 0000000..3f42fc7
--- /dev/null
+++ b/.config/ipython/profile_default/history.sqlite
Binary files differ
diff --git a/.config/ipython/profile_default/ipython_config.py b/.config/ipython/profile_default/ipython_config.py
new file mode 100644
index 0000000..83056e8
--- /dev/null
+++ b/.config/ipython/profile_default/ipython_config.py
@@ -0,0 +1,1146 @@
+# Configuration file for ipython.
+
+#------------------------------------------------------------------------------
+# InteractiveShellApp(Configurable) configuration
+#------------------------------------------------------------------------------
+## A Mixin for applications that start InteractiveShell instances.
+#
+# Provides configurables for loading extensions and executing files
+# as part of configuring a Shell environment.
+#
+# The following methods should be called by the :meth:`initialize` method
+# of the subclass:
+#
+# - :meth:`init_path`
+# - :meth:`init_shell` (to be implemented by the subclass)
+# - :meth:`init_gui_pylab`
+# - :meth:`init_extensions`
+# - :meth:`init_code`
+
+## Execute the given command string.
+# Default: ''
+# c.InteractiveShellApp.code_to_run = ''
+
+## Run the file referenced by the PYTHONSTARTUP environment
+# variable at IPython startup.
+# Default: True
+# c.InteractiveShellApp.exec_PYTHONSTARTUP = True
+
+## List of files to run at IPython startup.
+# Default: []
+# c.InteractiveShellApp.exec_files = []
+
+## lines of code to run at IPython startup.
+# Default: []
+# c.InteractiveShellApp.exec_lines = []
+
+## A list of dotted module names of IPython extensions to load.
+# Default: []
+# c.InteractiveShellApp.extensions = []
+
+## Dotted module name(s) of one or more IPython extensions to load.
+#
+# For specifying extra extensions to load on the command-line.
+#
+# .. versionadded:: 7.10
+# Default: []
+# c.InteractiveShellApp.extra_extensions = []
+
+## A file to be run
+# Default: ''
+# c.InteractiveShellApp.file_to_run = ''
+
+## Enable GUI event loop integration with any of ('asyncio', 'glut', 'gtk',
+# 'gtk2', 'gtk3', 'gtk4', 'osx', 'pyglet', 'qt', 'qt4', 'qt5', 'qt6', 'tk',
+# 'wx', 'gtk2', 'qt4').
+# Choices: any of ['asyncio', 'glut', 'gtk', 'gtk2', 'gtk3', 'gtk4', 'osx', 'pyglet', 'qt', 'qt4', 'qt5', 'qt6', 'tk', 'wx', 'gtk2', 'qt4'] (case-insensitive) or None
+# Default: None
+# c.InteractiveShellApp.gui = None
+
+## Should variables loaded at startup (by startup files, exec_lines, etc.)
+# be hidden from tools like %who?
+# Default: True
+# c.InteractiveShellApp.hide_initial_ns = True
+
+## If True, IPython will not add the current working directory to sys.path.
+# When False, the current working directory is added to sys.path, allowing imports
+# of modules defined in the current directory.
+# Default: False
+# c.InteractiveShellApp.ignore_cwd = False
+
+## Configure matplotlib for interactive use with
+# the default matplotlib backend.
+# Choices: any of ['auto', 'agg', 'gtk', 'gtk3', 'gtk4', 'inline', 'ipympl', 'nbagg', 'notebook', 'osx', 'pdf', 'ps', 'qt', 'qt4', 'qt5', 'qt6', 'svg', 'tk', 'widget', 'wx'] (case-insensitive) or None
+# Default: None
+# c.InteractiveShellApp.matplotlib = None
+
+## Run the module as a script.
+# Default: ''
+# c.InteractiveShellApp.module_to_run = ''
+
+## Pre-load matplotlib and numpy for interactive use,
+# selecting a particular matplotlib backend and loop integration.
+# Choices: any of ['auto', 'agg', 'gtk', 'gtk3', 'gtk4', 'inline', 'ipympl', 'nbagg', 'notebook', 'osx', 'pdf', 'ps', 'qt', 'qt4', 'qt5', 'qt6', 'svg', 'tk', 'widget', 'wx'] (case-insensitive) or None
+# Default: None
+# c.InteractiveShellApp.pylab = None
+
+## If true, IPython will populate the user namespace with numpy, pylab, etc.
+# and an ``import *`` is done from numpy and pylab, when using pylab mode.
+#
+# When False, pylab mode should not import any names into the user
+# namespace.
+# Default: True
+# c.InteractiveShellApp.pylab_import_all = True
+
+## Reraise exceptions encountered loading IPython extensions?
+# Default: False
+# c.InteractiveShellApp.reraise_ipython_extension_failures = False
+
+#------------------------------------------------------------------------------
+# Application(SingletonConfigurable) configuration
+#------------------------------------------------------------------------------
+## This is an application.
+
+## The date format used by logging formatters for %(asctime)s
+# Default: '%Y-%m-%d %H:%M:%S'
+# c.Application.log_datefmt = '%Y-%m-%d %H:%M:%S'
+
+## The Logging format template
+# Default: '[%(name)s]%(highlevel)s %(message)s'
+# c.Application.log_format = '[%(name)s]%(highlevel)s %(message)s'
+
+## Set the log level by value or name.
+# Choices: any of [0, 10, 20, 30, 40, 50, 'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL']
+# Default: 30
+# c.Application.log_level = 30
+
+## Configure additional log handlers.
+#
+# The default stderr logs handler is configured by the log_level, log_datefmt
+# and log_format settings.
+#
+# This configuration can be used to configure additional handlers (e.g. to
+# output the log to a file) or for finer control over the default handlers.
+#
+# If provided this should be a logging configuration dictionary, for more
+# information see:
+# https://docs.python.org/3/library/logging.config.html#logging-config-
+# dictschema
+#
+# This dictionary is merged with the base logging configuration which defines
+# the following:
+#
+# * A logging formatter intended for interactive use called
+# ``console``.
+# * A logging handler that writes to stderr called
+# ``console`` which uses the formatter ``console``.
+# * A logger with the name of this application set to ``DEBUG``
+# level.
+#
+# This example adds a new handler that writes to a file:
+#
+# .. code-block:: python
+#
+# c.Application.logging_configuration = {
+# 'handlers': {
+# 'file': {
+# 'class': 'logging.FileHandler',
+# 'level': 'DEBUG',
+# 'filename': '<path/to/file>',
+# }
+# },
+# 'loggers': {
+# '<application-name>': {
+# 'level': 'DEBUG',
+# # NOTE: if you don't list the default "console"
+# # handler here then it will be disabled
+# 'handlers': ['console', 'file'],
+# },
+# }
+# }
+# Default: {}
+# c.Application.logging_config = {}
+
+## Instead of starting the Application, dump configuration to stdout
+# Default: False
+# c.Application.show_config = False
+
+## Instead of starting the Application, dump configuration to stdout (as JSON)
+# Default: False
+# c.Application.show_config_json = False
+
+#------------------------------------------------------------------------------
+# BaseIPythonApplication(Application) configuration
+#------------------------------------------------------------------------------
+## IPython: an enhanced interactive Python shell.
+
+# Default: False
+# c.BaseIPythonApplication.add_ipython_dir_to_sys_path = False
+
+## Whether to create profile dir if it doesn't exist
+# Default: False
+# c.BaseIPythonApplication.auto_create = False
+
+## Whether to install the default config files into the profile dir.
+# If a new profile is being created, and IPython contains config files for that
+# profile, then they will be staged into the new directory. Otherwise,
+# default config files will be automatically generated.
+# Default: False
+# c.BaseIPythonApplication.copy_config_files = False
+
+## Path to an extra config file to load.
+#
+# If specified, load this config file in addition to any other IPython
+# config.
+# Default: ''
+# c.BaseIPythonApplication.extra_config_file = ''
+
+## The name of the IPython directory. This directory is used for logging
+# configuration (through profiles), history storage, etc. The default is usually
+# $HOME/.ipython. This option can also be specified through the environment
+# variable IPYTHONDIR.
+# Default: ''
+# c.BaseIPythonApplication.ipython_dir = ''
+
+## The date format used by logging formatters for %(asctime)s
+# See also: Application.log_datefmt
+# c.BaseIPythonApplication.log_datefmt = '%Y-%m-%d %H:%M:%S'
+
+## The Logging format template
+# See also: Application.log_format
+# c.BaseIPythonApplication.log_format = '[%(name)s]%(highlevel)s %(message)s'
+
+## Set the log level by value or name.
+# See also: Application.log_level
+# c.BaseIPythonApplication.log_level = 30
+
+##
+# See also: Application.logging_config
+# c.BaseIPythonApplication.logging_config = {}
+
+## Whether to overwrite existing config files when copying
+# Default: False
+# c.BaseIPythonApplication.overwrite = False
+
+## The IPython profile to use.
+# Default: 'default'
+# c.BaseIPythonApplication.profile = 'default'
+
+## Instead of starting the Application, dump configuration to stdout
+# See also: Application.show_config
+# c.BaseIPythonApplication.show_config = False
+
+## Instead of starting the Application, dump configuration to stdout (as JSON)
+# See also: Application.show_config_json
+# c.BaseIPythonApplication.show_config_json = False
+
+## Create a massive crash report when IPython encounters what may be an
+# internal error. The default is to append a short message to the
+# usual traceback
+# Default: False
+# c.BaseIPythonApplication.verbose_crash = False
+
+#------------------------------------------------------------------------------
+# TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp) configuration
+#------------------------------------------------------------------------------
+# See also: BaseIPythonApplication.add_ipython_dir_to_sys_path
+# c.TerminalIPythonApp.add_ipython_dir_to_sys_path = False
+
+## Execute the given command string.
+# See also: InteractiveShellApp.code_to_run
+# c.TerminalIPythonApp.code_to_run = ''
+
+## Whether to install the default config files into the profile dir.
+# See also: BaseIPythonApplication.copy_config_files
+# c.TerminalIPythonApp.copy_config_files = False
+
+## Whether to display a banner upon starting IPython.
+# Default: True
+# c.TerminalIPythonApp.display_banner = True
+
+## Run the file referenced by the PYTHONSTARTUP environment
+# See also: InteractiveShellApp.exec_PYTHONSTARTUP
+# c.TerminalIPythonApp.exec_PYTHONSTARTUP = True
+
+## List of files to run at IPython startup.
+# See also: InteractiveShellApp.exec_files
+# c.TerminalIPythonApp.exec_files = []
+
+## lines of code to run at IPython startup.
+# See also: InteractiveShellApp.exec_lines
+# c.TerminalIPythonApp.exec_lines = []
+
+## A list of dotted module names of IPython extensions to load.
+# See also: InteractiveShellApp.extensions
+# c.TerminalIPythonApp.extensions = []
+
+## Path to an extra config file to load.
+# See also: BaseIPythonApplication.extra_config_file
+# c.TerminalIPythonApp.extra_config_file = ''
+
+##
+# See also: InteractiveShellApp.extra_extensions
+# c.TerminalIPythonApp.extra_extensions = []
+
+## A file to be run
+# See also: InteractiveShellApp.file_to_run
+# c.TerminalIPythonApp.file_to_run = ''
+
+## If a command or file is given via the command-line,
+# e.g. 'ipython foo.py', start an interactive shell after executing the
+# file or command.
+# Default: False
+# c.TerminalIPythonApp.force_interact = False
+
+## Enable GUI event loop integration with any of ('asyncio', 'glut', 'gtk',
+# 'gtk2', 'gtk3', 'gtk4', 'osx', 'pyglet', 'qt', 'qt4', 'qt5', 'qt6', 'tk',
+# 'wx', 'gtk2', 'qt4').
+# See also: InteractiveShellApp.gui
+# c.TerminalIPythonApp.gui = None
+
+## Should variables loaded at startup (by startup files, exec_lines, etc.)
+# See also: InteractiveShellApp.hide_initial_ns
+# c.TerminalIPythonApp.hide_initial_ns = True
+
+## If True, IPython will not add the current working directory to sys.path.
+# See also: InteractiveShellApp.ignore_cwd
+# c.TerminalIPythonApp.ignore_cwd = False
+
+## Class to use to instantiate the TerminalInteractiveShell object. Useful for
+# custom Frontends
+# Default: 'IPython.terminal.interactiveshell.TerminalInteractiveShell'
+# c.TerminalIPythonApp.interactive_shell_class = 'IPython.terminal.interactiveshell.TerminalInteractiveShell'
+
+##
+# See also: BaseIPythonApplication.ipython_dir
+# c.TerminalIPythonApp.ipython_dir = ''
+
+## The date format used by logging formatters for %(asctime)s
+# See also: Application.log_datefmt
+# c.TerminalIPythonApp.log_datefmt = '%Y-%m-%d %H:%M:%S'
+
+## The Logging format template
+# See also: Application.log_format
+# c.TerminalIPythonApp.log_format = '[%(name)s]%(highlevel)s %(message)s'
+
+## Set the log level by value or name.
+# See also: Application.log_level
+# c.TerminalIPythonApp.log_level = 30
+
+##
+# See also: Application.logging_config
+# c.TerminalIPythonApp.logging_config = {}
+
+## Configure matplotlib for interactive use with
+# See also: InteractiveShellApp.matplotlib
+# c.TerminalIPythonApp.matplotlib = None
+
+## Run the module as a script.
+# See also: InteractiveShellApp.module_to_run
+# c.TerminalIPythonApp.module_to_run = ''
+
+## Whether to overwrite existing config files when copying
+# See also: BaseIPythonApplication.overwrite
+# c.TerminalIPythonApp.overwrite = False
+
+## The IPython profile to use.
+# See also: BaseIPythonApplication.profile
+# c.TerminalIPythonApp.profile = 'default'
+
+## Pre-load matplotlib and numpy for interactive use,
+# See also: InteractiveShellApp.pylab
+# c.TerminalIPythonApp.pylab = None
+
+## If true, IPython will populate the user namespace with numpy, pylab, etc.
+# See also: InteractiveShellApp.pylab_import_all
+# c.TerminalIPythonApp.pylab_import_all = True
+
+## Start IPython quickly by skipping the loading of config files.
+# Default: False
+# c.TerminalIPythonApp.quick = False
+
+## Reraise exceptions encountered loading IPython extensions?
+# See also: InteractiveShellApp.reraise_ipython_extension_failures
+# c.TerminalIPythonApp.reraise_ipython_extension_failures = False
+
+## Instead of starting the Application, dump configuration to stdout
+# See also: Application.show_config
+# c.TerminalIPythonApp.show_config = False
+
+## Instead of starting the Application, dump configuration to stdout (as JSON)
+# See also: Application.show_config_json
+# c.TerminalIPythonApp.show_config_json = False
+
+## Create a massive crash report when IPython encounters what may be an
+# See also: BaseIPythonApplication.verbose_crash
+# c.TerminalIPythonApp.verbose_crash = False
+
+#------------------------------------------------------------------------------
+# InteractiveShell(SingletonConfigurable) configuration
+#------------------------------------------------------------------------------
+## An enhanced, interactive shell for Python.
+
+## 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying which
+# nodes should be run interactively (displaying output from expressions).
+# Choices: any of ['all', 'last', 'last_expr', 'none', 'last_expr_or_assign']
+# Default: 'last_expr'
+# c.InteractiveShell.ast_node_interactivity = 'last_expr'
+
+## A list of ast.NodeTransformer subclass instances, which will be applied to
+# user input before code is run.
+# Default: []
+# c.InteractiveShell.ast_transformers = []
+
+## Automatically run await statement in the top level repl.
+# Default: True
+# c.InteractiveShell.autoawait = True
+
+## Make IPython automatically call any callable object even if you didn't type
+# explicit parentheses. For example, 'str 43' becomes 'str(43)' automatically.
+# The value can be '0' to disable the feature, '1' for 'smart' autocall, where
+# it is not applied if there are no more arguments on the line, and '2' for
+# 'full' autocall, where all callable objects are automatically called (even if
+# no arguments are present).
+# Choices: any of [0, 1, 2]
+# Default: 0
+# c.InteractiveShell.autocall = 0
+
+## Autoindent IPython code entered interactively.
+# Default: True
+# c.InteractiveShell.autoindent = True
+
+## Enable magic commands to be called without the leading %.
+# Default: True
+# c.InteractiveShell.automagic = True
+
+## The part of the banner to be printed before the profile
+# Default: "Python 3.10.4 (main, Mar 23 2022, 23:05:40) [GCC 11.2.0]\nType 'copyright', 'credits' or 'license' for more information\nIPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.\n"
+# c.InteractiveShell.banner1 = "Python 3.10.4 (main, Mar 23 2022, 23:05:40) [GCC 11.2.0]\nType 'copyright', 'credits' or 'license' for more information\nIPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.\n"
+
+## The part of the banner to be printed after the profile
+# Default: ''
+# c.InteractiveShell.banner2 = ''
+
+## Set the size of the output cache. The default is 1000, you can change it
+# permanently in your config file. Setting it to 0 completely disables the
+# caching system, and the minimum value accepted is 3 (if you provide a value
+# less than 3, it is reset to 0 and a warning is issued). This limit is defined
+# because otherwise you'll spend more time re-flushing a too small cache than
+# working
+# Default: 1000
+# c.InteractiveShell.cache_size = 1000
+
+## Use colors for displaying information about objects. Because this information
+# is passed through a pager (like 'less'), and some pagers get confused with
+# color codes, this capability can be turned off.
+# Default: True
+# c.InteractiveShell.color_info = True
+
+## Set the color scheme (NoColor, Neutral, Linux, or LightBG).
+# Choices: any of ['Neutral', 'NoColor', 'LightBG', 'Linux'] (case-insensitive)
+# Default: 'Neutral'
+# c.InteractiveShell.colors = 'Neutral'
+
+# Default: False
+# c.InteractiveShell.debug = False
+
+## Don't call post-execute functions that have failed in the past.
+# Default: False
+# c.InteractiveShell.disable_failing_post_execute = False
+
+## If True, anything that would be passed to the pager
+# will be displayed as regular output instead.
+# Default: False
+# c.InteractiveShell.display_page = False
+
+## (Provisional API) enables html representation in mime bundles sent to pagers.
+# Default: False
+# c.InteractiveShell.enable_html_pager = False
+
+## Total length of command history
+# Default: 10000
+# c.InteractiveShell.history_length = 10000
+
+## The number of saved history entries to be loaded into the history buffer at
+# startup.
+# Default: 1000
+# c.InteractiveShell.history_load_length = 1000
+
+# Default: ''
+# c.InteractiveShell.ipython_dir = ''
+
+## Start logging to the given file in append mode. Use `logfile` to specify a log
+# file to **overwrite** logs to.
+# Default: ''
+# c.InteractiveShell.logappend = ''
+
+## The name of the logfile to use.
+# Default: ''
+# c.InteractiveShell.logfile = ''
+
+## Start logging to the default log file in overwrite mode. Use `logappend` to
+# specify a log file to **append** logs to.
+# Default: False
+# c.InteractiveShell.logstart = False
+
+## Select the loop runner that will be used to execute top-level asynchronous
+# code
+# Default: 'IPython.core.interactiveshell._asyncio_runner'
+# c.InteractiveShell.loop_runner = 'IPython.core.interactiveshell._asyncio_runner'
+
+# Choices: any of [0, 1, 2]
+# Default: 0
+# c.InteractiveShell.object_info_string_level = 0
+
+## Automatically call the pdb debugger after every exception.
+# Default: False
+# c.InteractiveShell.pdb = False
+
+# Default: False
+# c.InteractiveShell.quiet = False
+
+# Default: '\n'
+# c.InteractiveShell.separate_in = '\n'
+
+# Default: ''
+# c.InteractiveShell.separate_out = ''
+
+# Default: ''
+# c.InteractiveShell.separate_out2 = ''
+
+## Show rewritten input, e.g. for autocall.
+# Default: True
+# c.InteractiveShell.show_rewritten_input = True
+
+## Enables rich html representation of docstrings. (This requires the docrepr
+# module).
+# Default: False
+# c.InteractiveShell.sphinxify_docstring = False
+
+# Default: True
+# c.InteractiveShell.wildcards_case_sensitive = True
+
+## Switch modes for the IPython exception handlers.
+# Choices: any of ['Context', 'Plain', 'Verbose', 'Minimal'] (case-insensitive)
+# Default: 'Context'
+# c.InteractiveShell.xmode = 'Context'
+
+#------------------------------------------------------------------------------
+# TerminalInteractiveShell(InteractiveShell) configuration
+#------------------------------------------------------------------------------
+##
+# See also: InteractiveShell.ast_node_interactivity
+# c.TerminalInteractiveShell.ast_node_interactivity = 'last_expr'
+
+##
+# See also: InteractiveShell.ast_transformers
+# c.TerminalInteractiveShell.ast_transformers = []
+
+## Automatically add/delete closing bracket or quote when opening bracket or
+# quote is entered/deleted. Brackets: (), [], {} Quotes: '', ""
+# Default: False
+# c.TerminalInteractiveShell.auto_match = False
+
+##
+# See also: InteractiveShell.autoawait
+# c.TerminalInteractiveShell.autoawait = True
+
+##
+# See also: InteractiveShell.autocall
+# c.TerminalInteractiveShell.autocall = 0
+
+## Autoformatter to reformat Terminal code. Can be `'black'`, `'yapf'` or `None`
+# Default: None
+# c.TerminalInteractiveShell.autoformatter = None
+
+##
+# See also: InteractiveShell.autoindent
+# c.TerminalInteractiveShell.autoindent = True
+
+##
+# See also: InteractiveShell.automagic
+# c.TerminalInteractiveShell.automagic = True
+
+## Specifies from which source automatic suggestions are provided. Can be set to
+# `'AutoSuggestFromHistory`' or `None` to disableautomatic suggestions. Default
+# is `'AutoSuggestFromHistory`'.
+# Default: 'AutoSuggestFromHistory'
+# c.TerminalInteractiveShell.autosuggestions_provider = 'AutoSuggestFromHistory'
+
+## The part of the banner to be printed before the profile
+# See also: InteractiveShell.banner1
+# c.TerminalInteractiveShell.banner1 = "Python 3.10.4 (main, Mar 23 2022, 23:05:40) [GCC 11.2.0]\nType 'copyright', 'credits' or 'license' for more information\nIPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.\n"
+
+## The part of the banner to be printed after the profile
+# See also: InteractiveShell.banner2
+# c.TerminalInteractiveShell.banner2 = ''
+
+##
+# See also: InteractiveShell.cache_size
+# c.TerminalInteractiveShell.cache_size = 1000
+
+##
+# See also: InteractiveShell.color_info
+# c.TerminalInteractiveShell.color_info = True
+
+## Set the color scheme (NoColor, Neutral, Linux, or LightBG).
+# See also: InteractiveShell.colors
+# c.TerminalInteractiveShell.colors = 'Neutral'
+
+## Set to confirm when you try to exit IPython with an EOF (Control-D in Unix,
+# Control-Z/Enter in Windows). By typing 'exit' or 'quit', you can force a
+# direct exit without any confirmation.
+# Default: True
+c.TerminalInteractiveShell.confirm_exit = False
+
+# See also: InteractiveShell.debug
+# c.TerminalInteractiveShell.debug = False
+
+## File in which to store and read history
+# Default: '~/.pdbhistory'
+# c.TerminalInteractiveShell.debugger_history_file = '~/.pdbhistory'
+
+## Don't call post-execute functions that have failed in the past.
+# See also: InteractiveShell.disable_failing_post_execute
+# c.TerminalInteractiveShell.disable_failing_post_execute = False
+
+## Options for displaying tab completions, 'column', 'multicolumn', and
+# 'readlinelike'. These options are for `prompt_toolkit`, see `prompt_toolkit`
+# documentation for more information.
+# Choices: any of ['column', 'multicolumn', 'readlinelike']
+# Default: 'multicolumn'
+# c.TerminalInteractiveShell.display_completions = 'multicolumn'
+
+## If True, anything that would be passed to the pager
+# See also: InteractiveShell.display_page
+# c.TerminalInteractiveShell.display_page = False
+
+## Shortcut style to use at the prompt. 'vi' or 'emacs'.
+# Default: 'emacs'
+c.TerminalInteractiveShell.editing_mode = 'vi'
+
+## Set the editor used by IPython (default to $EDITOR/vi/notepad).
+# Default: 'nvim'
+# c.TerminalInteractiveShell.editor = 'nvim'
+
+## Add shortcuts from 'emacs' insert mode to 'vi' insert mode.
+# Default: True
+# c.TerminalInteractiveShell.emacs_bindings_in_vi_insert_mode = True
+
+## Allows to enable/disable the prompt toolkit history search
+# Default: True
+# c.TerminalInteractiveShell.enable_history_search = True
+
+##
+# See also: InteractiveShell.enable_html_pager
+# c.TerminalInteractiveShell.enable_html_pager = False
+
+## Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. This is
+# in addition to the F2 binding, which is always enabled.
+# Default: False
+# c.TerminalInteractiveShell.extra_open_editor_shortcuts = False
+
+## Provide an alternative handler to be called when the user presses Return. This
+# is an advanced option intended for debugging, which may be changed or removed
+# in later releases.
+# Default: None
+# c.TerminalInteractiveShell.handle_return = None
+
+## Highlight matching brackets.
+# Default: True
+# c.TerminalInteractiveShell.highlight_matching_brackets = True
+
+## The name or class of a Pygments style to use for syntax
+# highlighting. To see available styles, run `pygmentize -L styles`.
+# Default: traitlets.Undefined
+# c.TerminalInteractiveShell.highlighting_style = traitlets.Undefined
+
+## Override highlighting format for specific tokens
+# Default: {}
+# c.TerminalInteractiveShell.highlighting_style_overrides = {}
+
+## Total length of command history
+# See also: InteractiveShell.history_length
+# c.TerminalInteractiveShell.history_length = 10000
+
+##
+# See also: InteractiveShell.history_load_length
+# c.TerminalInteractiveShell.history_load_length = 1000
+
+# See also: InteractiveShell.ipython_dir
+# c.TerminalInteractiveShell.ipython_dir = ''
+
+##
+# See also: InteractiveShell.logappend
+# c.TerminalInteractiveShell.logappend = ''
+
+##
+# See also: InteractiveShell.logfile
+# c.TerminalInteractiveShell.logfile = ''
+
+##
+# See also: InteractiveShell.logstart
+# c.TerminalInteractiveShell.logstart = False
+
+## Select the loop runner that will be used to execute top-level asynchronous
+# code
+# See also: InteractiveShell.loop_runner
+# c.TerminalInteractiveShell.loop_runner = 'IPython.core.interactiveshell._asyncio_runner'
+
+# Default: {}
+# c.TerminalInteractiveShell.mime_renderers = {}
+
+## Cursor shape changes depending on vi mode: beam in vi insert mode, block in
+# nav mode, underscore in replace mode.
+# Default: True
+# c.TerminalInteractiveShell.modal_cursor = True
+
+## Enable mouse support in the prompt (Note: prevents selecting text with the
+# mouse)
+# Default: False
+# c.TerminalInteractiveShell.mouse_support = False
+
+# See also: InteractiveShell.object_info_string_level
+# c.TerminalInteractiveShell.object_info_string_level = 0
+
+##
+# See also: InteractiveShell.pdb
+# c.TerminalInteractiveShell.pdb = False
+
+## Display the current vi mode (when using vi editing mode).
+# Default: True
+c.TerminalInteractiveShell.prompt_includes_vi_mode = False
+
+## Class used to generate Prompt token for prompt_toolkit
+# Default: 'IPython.terminal.prompts.Prompts'
+# c.TerminalInteractiveShell.prompts_class = 'IPython.terminal.prompts.Prompts'
+
+# See also: InteractiveShell.quiet
+# c.TerminalInteractiveShell.quiet = False
+
+# See also: InteractiveShell.separate_in
+# c.TerminalInteractiveShell.separate_in = '\n'
+
+# See also: InteractiveShell.separate_out
+# c.TerminalInteractiveShell.separate_out = ''
+
+# See also: InteractiveShell.separate_out2
+# c.TerminalInteractiveShell.separate_out2 = ''
+
+## Show rewritten input, e.g. for autocall.
+# See also: InteractiveShell.show_rewritten_input
+# c.TerminalInteractiveShell.show_rewritten_input = True
+
+## Use `raw_input` for the REPL, without completion and prompt colors.
+#
+# Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
+# IPython own testing machinery, and emacs inferior-shell integration through elpy.
+#
+# This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
+# environment variable is set, or the current terminal is not a tty.
+# Default: False
+# c.TerminalInteractiveShell.simple_prompt = False
+
+## Number of line at the bottom of the screen to reserve for the tab completion
+# menu, search history, ...etc, the height of these menus will at most this
+# value. Increase it is you prefer long and skinny menus, decrease for short and
+# wide.
+# Default: 6
+# c.TerminalInteractiveShell.space_for_menu = 6
+
+##
+# See also: InteractiveShell.sphinxify_docstring
+# c.TerminalInteractiveShell.sphinxify_docstring = False
+
+## Automatically set the terminal title
+# Default: True
+# c.TerminalInteractiveShell.term_title = True
+
+## Customize the terminal title format. This is a python format string.
+# Available substitutions are: {cwd}.
+# Default: 'IPython: {cwd}'
+# c.TerminalInteractiveShell.term_title_format = 'IPython: {cwd}'
+
+## The time in milliseconds that is waited for a mapped key
+# sequence to complete.
+# Default: 0.5
+# c.TerminalInteractiveShell.timeoutlen = 0.5
+
+## Use 24bit colors instead of 256 colors in prompt highlighting.
+# If your terminal supports true color, the following command should
+# print ``TRUECOLOR`` in orange::
+#
+# printf "\x1b[38;2;255;100;0mTRUECOLOR\x1b[0m\n"
+# Default: False
+# c.TerminalInteractiveShell.true_color = False
+
+## The time in milliseconds that is waited for a key code
+# to complete.
+# Default: 0.01
+# c.TerminalInteractiveShell.ttimeoutlen = 0.01
+
+# See also: InteractiveShell.wildcards_case_sensitive
+# c.TerminalInteractiveShell.wildcards_case_sensitive = True
+
+## Switch modes for the IPython exception handlers.
+# See also: InteractiveShell.xmode
+# c.TerminalInteractiveShell.xmode = 'Context'
+
+#------------------------------------------------------------------------------
+# HistoryAccessor(HistoryAccessorBase) configuration
+#------------------------------------------------------------------------------
+## Access the history database without adding to it.
+#
+# This is intended for use by standalone history tools. IPython shells use
+# HistoryManager, below, which is a subclass of this.
+
+## Options for configuring the SQLite connection
+#
+# These options are passed as keyword args to sqlite3.connect
+# when establishing database connections.
+# Default: {}
+# c.HistoryAccessor.connection_options = {}
+
+## enable the SQLite history
+#
+# set enabled=False to disable the SQLite history,
+# in which case there will be no stored history, no SQLite connection,
+# and no background saving thread. This may be necessary in some
+# threaded environments where IPython is embedded.
+# Default: True
+# c.HistoryAccessor.enabled = True
+
+## Path to file to use for SQLite history database.
+#
+# By default, IPython will put the history database in the IPython
+# profile directory. If you would rather share one history among
+# profiles, you can set this value in each, so that they are consistent.
+#
+# Due to an issue with fcntl, SQLite is known to misbehave on some NFS
+# mounts. If you see IPython hanging, try setting this to something on a
+# local disk, e.g::
+#
+# ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
+#
+# you can also use the specific value `:memory:` (including the colon
+# at both end but not the back ticks), to avoid creating an history file.
+# Default: traitlets.Undefined
+# c.HistoryAccessor.hist_file = traitlets.Undefined
+
+#------------------------------------------------------------------------------
+# HistoryManager(HistoryAccessor) configuration
+#------------------------------------------------------------------------------
+## A class to organize all history-related functionality in one place.
+
+## Options for configuring the SQLite connection
+# See also: HistoryAccessor.connection_options
+# c.HistoryManager.connection_options = {}
+
+## Write to database every x commands (higher values save disk access & power).
+# Values of 1 or less effectively disable caching.
+# Default: 0
+# c.HistoryManager.db_cache_size = 0
+
+## Should the history database include output? (default: no)
+# Default: False
+# c.HistoryManager.db_log_output = False
+
+## enable the SQLite history
+# See also: HistoryAccessor.enabled
+# c.HistoryManager.enabled = True
+
+## Path to file to use for SQLite history database.
+# See also: HistoryAccessor.hist_file
+# c.HistoryManager.hist_file = traitlets.Undefined
+
+#------------------------------------------------------------------------------
+# MagicsManager(Configurable) configuration
+#------------------------------------------------------------------------------
+## Object that handles all magic-related functionality for IPython.
+
+## Automatically call line magics without requiring explicit % prefix
+# Default: True
+# c.MagicsManager.auto_magic = True
+
+## Mapping from magic names to modules to load.
+#
+# This can be used in IPython/IPykernel configuration to declare lazy magics
+# that will only be imported/registered on first use.
+#
+# For example::
+#
+# c.MagicsManager.lazy_magics = {
+# "my_magic": "slow.to.import",
+# "my_other_magic": "also.slow",
+# }
+#
+# On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or
+# `%%my_other_magic`, the corresponding module will be loaded as an ipython
+# extensions as if you had previously done `%load_ext ipython`.
+#
+# Magics names should be without percent(s) as magics can be both cell and line
+# magics.
+#
+# Lazy loading happen relatively late in execution process, and complex
+# extensions that manipulate Python/IPython internal state or global state might
+# not support lazy loading.
+# Default: {}
+# c.MagicsManager.lazy_magics = {}
+
+#------------------------------------------------------------------------------
+# ProfileDir(LoggingConfigurable) configuration
+#------------------------------------------------------------------------------
+## An object to manage the profile directory and its resources.
+#
+# The profile directory is used by all IPython applications, to manage
+# configuration, logging and security.
+#
+# This object knows how to find, create and manage these directories. This
+# should be used by any code that wants to handle profiles.
+
+## Set the profile location directly. This overrides the logic used by the
+# `profile` option.
+# Default: ''
+# c.ProfileDir.location = ''
+
+#------------------------------------------------------------------------------
+# BaseFormatter(Configurable) configuration
+#------------------------------------------------------------------------------
+## A base formatter class that is configurable.
+#
+# This formatter should usually be used as the base class of all formatters.
+# It is a traited :class:`Configurable` class and includes an extensible
+# API for users to determine how their objects are formatted. The following
+# logic is used to find a function to format an given object.
+#
+# 1. The object is introspected to see if it has a method with the name
+# :attr:`print_method`. If is does, that object is passed to that method
+# for formatting.
+# 2. If no print method is found, three internal dictionaries are consulted
+# to find print method: :attr:`singleton_printers`, :attr:`type_printers`
+# and :attr:`deferred_printers`.
+#
+# Users should use these dictionaries to register functions that will be
+# used to compute the format data for their objects (if those objects don't
+# have the special print methods). The easiest way of using these
+# dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
+# methods.
+#
+# If no function/callable is found to compute the format data, ``None`` is
+# returned and this format type is not used.
+
+# Default: {}
+# c.BaseFormatter.deferred_printers = {}
+
+# Default: True
+# c.BaseFormatter.enabled = True
+
+# Default: {}
+# c.BaseFormatter.singleton_printers = {}
+
+# Default: {}
+# c.BaseFormatter.type_printers = {}
+
+#------------------------------------------------------------------------------
+# PlainTextFormatter(BaseFormatter) configuration
+#------------------------------------------------------------------------------
+## The default pretty-printer.
+#
+# This uses :mod:`IPython.lib.pretty` to compute the format data of
+# the object. If the object cannot be pretty printed, :func:`repr` is used.
+# See the documentation of :mod:`IPython.lib.pretty` for details on
+# how to write pretty printers. Here is a simple example::
+#
+# def dtype_pprinter(obj, p, cycle):
+# if cycle:
+# return p.text('dtype(...)')
+# if hasattr(obj, 'fields'):
+# if obj.fields is None:
+# p.text(repr(obj))
+# else:
+# p.begin_group(7, 'dtype([')
+# for i, field in enumerate(obj.descr):
+# if i > 0:
+# p.text(',')
+# p.breakable()
+# p.pretty(field)
+# p.end_group(7, '])')
+
+# See also: BaseFormatter.deferred_printers
+# c.PlainTextFormatter.deferred_printers = {}
+
+# Default: ''
+# c.PlainTextFormatter.float_precision = ''
+
+## Truncate large collections (lists, dicts, tuples, sets) to this size.
+#
+# Set to 0 to disable truncation.
+# Default: 1000
+# c.PlainTextFormatter.max_seq_length = 1000
+
+# Default: 79
+# c.PlainTextFormatter.max_width = 79
+
+# Default: '\n'
+# c.PlainTextFormatter.newline = '\n'
+
+# Default: True
+# c.PlainTextFormatter.pprint = True
+
+# See also: BaseFormatter.singleton_printers
+# c.PlainTextFormatter.singleton_printers = {}
+
+# See also: BaseFormatter.type_printers
+# c.PlainTextFormatter.type_printers = {}
+
+# Default: False
+# c.PlainTextFormatter.verbose = False
+
+#------------------------------------------------------------------------------
+# Completer(Configurable) configuration
+#------------------------------------------------------------------------------
+## Enable unicode completions, e.g. \alpha<tab> . Includes completion of latex
+# commands, unicode names, and expanding unicode characters back to latex
+# commands.
+# Default: True
+# c.Completer.backslash_combining_completions = True
+
+## Enable debug for the Completer. Mostly print extra information for
+# experimental jedi integration.
+# Default: False
+# c.Completer.debug = False
+
+## Activate greedy completion
+# PENDING DEPRECATION. this is now mostly taken care of with Jedi.
+#
+# This will enable completion on elements of lists, results of function calls, etc.,
+# but can be unsafe because the code is actually evaluated on TAB.
+# Default: False
+# c.Completer.greedy = False
+
+## Experimental: restrict time (in milliseconds) during which Jedi can compute types.
+# Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
+# performance by preventing jedi to build its cache.
+# Default: 400
+# c.Completer.jedi_compute_type_timeout = 400
+
+## Experimental: Use Jedi to generate autocompletions. Default to True if jedi is
+# installed.
+# Default: True
+# c.Completer.use_jedi = True
+
+#------------------------------------------------------------------------------
+# IPCompleter(Completer) configuration
+#------------------------------------------------------------------------------
+## Extension of the completer class with IPython-specific features
+
+## Enable unicode completions, e.g. \alpha<tab> . Includes completion of latex
+# commands, unicode names, and expanding unicode characters back to latex
+# commands.
+# See also: Completer.backslash_combining_completions
+# c.IPCompleter.backslash_combining_completions = True
+
+## Enable debug for the Completer. Mostly print extra information for
+# experimental jedi integration.
+# See also: Completer.debug
+# c.IPCompleter.debug = False
+
+## Activate greedy completion
+# See also: Completer.greedy
+# c.IPCompleter.greedy = False
+
+## Experimental: restrict time (in milliseconds) during which Jedi can compute
+# types.
+# See also: Completer.jedi_compute_type_timeout
+# c.IPCompleter.jedi_compute_type_timeout = 400
+
+## DEPRECATED as of version 5.0.
+#
+# Instruct the completer to use __all__ for the completion
+#
+# Specifically, when completing on ``object.<tab>``.
+#
+# When True: only those names in obj.__all__ will be included.
+#
+# When False [default]: the __all__ attribute is ignored
+# Default: False
+# c.IPCompleter.limit_to__all__ = False
+
+## Whether to merge completion results into a single list
+#
+# If False, only the completion results from the first non-empty
+# completer will be returned.
+# Default: True
+# c.IPCompleter.merge_completions = True
+
+## Instruct the completer to omit private method names
+#
+# Specifically, when completing on ``object.<tab>``.
+#
+# When 2 [default]: all names that start with '_' will be excluded.
+#
+# When 1: all 'magic' names (``__foo__``) will be excluded.
+#
+# When 0: nothing will be excluded.
+# Choices: any of [0, 1, 2]
+# Default: 2
+# c.IPCompleter.omit__names = 2
+
+## If True, emit profiling data for completion subsystem using cProfile.
+# Default: False
+# c.IPCompleter.profile_completions = False
+
+## Template for path at which to output profile data for completions.
+# Default: '.completion_profiles'
+# c.IPCompleter.profiler_output_dir = '.completion_profiles'
+
+## Experimental: Use Jedi to generate autocompletions. Default to True if jedi is
+# installed.
+# See also: Completer.use_jedi
+# c.IPCompleter.use_jedi = True
+
+#------------------------------------------------------------------------------
+# ScriptMagics(Magics) configuration
+#------------------------------------------------------------------------------
+## Magics for talking to scripts
+#
+# This defines a base `%%script` cell magic for running a cell
+# with a program in a subprocess, and registers a few top-level
+# magics that call %%script with common interpreters.
+
+## Extra script cell magics to define
+#
+# This generates simple wrappers of `%%script foo` as `%%foo`.
+#
+# If you want to add script magics that aren't on your path,
+# specify them in script_paths
+# Default: []
+# c.ScriptMagics.script_magics = []
+
+## Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
+#
+# Only necessary for items in script_magics where the default path will not
+# find the right interpreter.
+# Default: {}
+# c.ScriptMagics.script_paths = {}
+
+#------------------------------------------------------------------------------
+# LoggingMagics(Magics) configuration
+#------------------------------------------------------------------------------
+## Magics related to all logging machinery.
+
+## Suppress output of log state when logging is enabled
+# Default: False
+# c.LoggingMagics.quiet = False
+
+#------------------------------------------------------------------------------
+# StoreMagics(Magics) configuration
+#------------------------------------------------------------------------------
+## Lightweight persistence for python variables.
+#
+# Provides the %store magic.
+
+## If True, any %store-d variables will be automatically restored
+# when IPython starts.
+# Default: False
+# c.StoreMagics.autorestore = False
diff --git a/.config/ipython/profile_default/startup/05-keybindings.py b/.config/ipython/profile_default/startup/05-keybindings.py
new file mode 100644
index 0000000..11439aa
--- /dev/null
+++ b/.config/ipython/profile_default/startup/05-keybindings.py
@@ -0,0 +1,18 @@
+from IPython import get_ipython
+from prompt_toolkit.enums import DEFAULT_BUFFER
+from prompt_toolkit.filters import HasFocus, ViInsertMode
+from prompt_toolkit.key_binding.vi_state import InputMode
+
+ip = get_ipython()
+
+def switch_to_navigation_mode(event):
+ vi_state = event.cli.vi_state
+ vi_state.input_mode = InputMode.NAVIGATION
+
+if getattr(ip, 'pt_app', None):
+ registry = ip.pt_app.key_bindings
+ registry.add_binding(u'j',u'k',
+ filter=(HasFocus(DEFAULT_BUFFER)
+ & ViInsertMode()))(switch_to_navigation_mode)
+
+
diff --git a/.config/ipython/profile_default/startup/10-startup.ipy b/.config/ipython/profile_default/startup/10-startup.ipy
new file mode 100644
index 0000000..05d2921
--- /dev/null
+++ b/.config/ipython/profile_default/startup/10-startup.ipy
@@ -0,0 +1,13 @@
+#!/usr/bin/ipython
+
+# print()
+# from math import *
+# print("Imported all functions from math")
+# import numpy as np
+# print("Imported numpy as np")
+# import sympy as sym
+# sym.var('a, b, c, x, y, z')
+
+# print("\n\t Don't waste time")
+# print("\t FOCUS ON THE ESSENTIAL \n")
+# alias q pkill ipython
diff --git a/.config/ipython/profile_default/startup/20-functions.ipy b/.config/ipython/profile_default/startup/20-functions.ipy
new file mode 100644
index 0000000..615a848
--- /dev/null
+++ b/.config/ipython/profile_default/startup/20-functions.ipy
@@ -0,0 +1,13 @@
+#!/usr/bin/ipython
+
+# def exp(x):
+# return sum([
+# x**n / m.factorial(n)
+# for n in range(0, 100)
+# ])
+#
+# def tables(from_, to_, rows=10):
+# for table in range(from_, to_+1):
+# for row in range(1, rows+1):
+# print(table, 'x', row, '=', table*row)
+# print()
diff --git a/.config/ipython/profile_default/startup/README b/.config/ipython/profile_default/startup/README
new file mode 100644
index 0000000..61d4700
--- /dev/null
+++ b/.config/ipython/profile_default/startup/README
@@ -0,0 +1,11 @@
+This is the IPython startup directory
+
+.py and .ipy files in this directory will be run *prior* to any code or files specified
+via the exec_lines or exec_files configurables whenever you load this profile.
+
+Files will be run in lexicographical order, so you can control the execution order of files
+with a prefix, e.g.::
+
+ 00-first.py
+ 50-middle.py
+ 99-last.ipy
diff --git a/.config/jgmenu/append.csv b/.config/jgmenu/append.csv
new file mode 100644
index 0000000..d370fc0
--- /dev/null
+++ b/.config/jgmenu/append.csv
@@ -0,0 +1,7 @@
+^sep()
+Lock,i3lock -c 000000,system-lock-screen
+Exit,^checkout(exit),system-shutdown
+^tag(exit)
+Suspend,systemctl -i suspend,system-log-out
+Reboot,systemctl -i reboot,system-reboot
+Poweroff,systemctl -i poweroff,system-shutdown
diff --git a/.config/jgmenu/backup/20230925074149958689103/jgmenurc b/.config/jgmenu/backup/20230925074149958689103/jgmenurc
new file mode 100644
index 0000000..c1632f7
--- /dev/null
+++ b/.config/jgmenu/backup/20230925074149958689103/jgmenurc
@@ -0,0 +1,74 @@
+# verbosity = 0
+# stay_alive = 1
+# persistent = 0
+# hide_on_startup = 0
+# csv_cmd = apps
+# tint2_look = 0
+# position_mode = fixed
+# edge_snap_x = 30
+# terminal_exec = x-terminal-emulator
+# terminal_args = -e
+# monitor = 0
+# hover_delay = 100
+# hide_back_items = 1
+# columns = 1
+# tabs = 120
+# menu_margin_x = 0
+# menu_margin_y = 0
+# menu_width = 200
+# menu_height_min = 0
+# menu_height_max = 0
+# menu_height_mode = static
+# menu_padding_top = 5
+# menu_padding_right = 5
+# menu_padding_bottom = 5
+# menu_padding_left = 5
+# menu_radius = 1
+# menu_border = 0
+# menu_halign = left
+# menu_valign = bottom
+# menu_gradient_pos = none
+# sub_spacing = 1
+# sub_padding_top = auto
+# sub_padding_right = auto
+# sub_padding_bottom = auto
+# sub_padding_left = auto
+# sub_hover_action = 1
+# item_margin_x = 3
+# item_margin_y = 3
+# item_height = 25
+# item_padding_x = 4
+# item_radius = 1
+# item_border = 0
+# item_halign = left
+# sep_height = 5
+# sep_halign = left
+# sep_markup =
+# font =
+# font_fallback = xtg
+# icon_size = 22
+# icon_text_spacing = 10
+# icon_norm_alpha = 100
+# icon_sel_alpha = 100
+# icon_theme =
+# icon_theme_fallback = xtg
+# arrow_string = ▸
+# arrow_width = 15
+# color_menu_bg = #000000 100
+# color_menu_bg_to = #000000 100
+# color_menu_border = #eeeeee 8
+# color_norm_bg = #000000 00
+# color_norm_fg = #eeeeee 100
+# color_sel_bg = #ffffff 20
+# color_sel_fg = #eeeeee 100
+# color_sel_border = #eeeeee 8
+# color_sep_fg = #ffffff 20
+# color_scroll_ind = #eeeeee 40
+# color_title_fg = #eeeeee 50
+# color_title_bg = #000000 0
+# color_title_border = #000000 0
+# csv_name_format = %n (%g)
+# csv_single_window = 0
+# csv_no_dirs = 0
+# csv_i18n =
+# csv_no_duplicates = 0
diff --git a/.config/jgmenu/jgmenurc b/.config/jgmenu/jgmenurc
new file mode 100644
index 0000000..741389b
--- /dev/null
+++ b/.config/jgmenu/jgmenurc
@@ -0,0 +1,74 @@
+# verbosity = 0
+stay_alive = 0
+# persistent = 0
+# hide_on_startup = 0
+# csv_cmd = apps
+# tint2_look = 0
+# position_mode = fixed
+# edge_snap_x = 30
+# terminal_exec = x-terminal-emulator
+# terminal_args = -e
+# monitor = 0
+# hover_delay = 100
+# hide_back_items = 1
+# columns = 1
+# tabs = 120
+# menu_margin_x = 0
+# menu_margin_y = 0
+# menu_width = 200
+# menu_height_min = 0
+# menu_height_max = 0
+# menu_height_mode = static
+# menu_padding_top = 5
+# menu_padding_right = 5
+# menu_padding_bottom = 5
+# menu_padding_left = 5
+# menu_radius = 1
+# menu_border = 0
+# menu_halign = left
+# menu_valign = bottom
+# menu_gradient_pos = none
+# sub_spacing = 1
+# sub_padding_top = auto
+# sub_padding_right = auto
+# sub_padding_bottom = auto
+# sub_padding_left = auto
+# sub_hover_action = 1
+# item_margin_x = 3
+# item_margin_y = 3
+item_height = 40
+# item_padding_x = 4
+# item_radius = 1
+# item_border = 0
+# item_halign = left
+# sep_height = 5
+# sep_halign = left
+# sep_markup =
+font = 16
+# font_fallback = xtg
+icon_size = 40
+# icon_text_spacing = 10
+# icon_norm_alpha = 100
+# icon_sel_alpha = 100
+icon_theme = Gruvbox-Material-Dark
+# icon_theme_fallback = xtg
+# arrow_string = ▸
+# arrow_width = 15
+# color_menu_bg = #000000 100
+# color_menu_bg_to = #000000 100
+# color_menu_border = #eeeeee 8
+# color_norm_bg = #000000 00
+# color_norm_fg = #eeeeee 100
+# color_sel_bg = #ffffff 20
+# color_sel_fg = #eeeeee 100
+# color_sel_border = #eeeeee 8
+# color_sep_fg = #ffffff 20
+# color_scroll_ind = #eeeeee 40
+# color_title_fg = #eeeeee 50
+# color_title_bg = #000000 0
+# color_title_border = #000000 0
+# csv_name_format = %n (%g)
+# csv_single_window = 0
+# csv_no_dirs = 0
+# csv_i18n =
+# csv_no_duplicates = 0
diff --git a/.config/keepassxc/keepassxc.ini b/.config/keepassxc/keepassxc.ini
new file mode 100644
index 0000000..a966b00
--- /dev/null
+++ b/.config/keepassxc/keepassxc.ini
@@ -0,0 +1,37 @@
+[General]
+ConfigVersion=2
+GlobalAutoTypeKey=65
+GlobalAutoTypeModifiers=402653184
+MinimizeAfterUnlock=true
+UpdateCheckMessageShown=true
+
+[Browser]
+CustomProxyLocation=
+
+[FdoSecrets]
+Enabled=false
+
+[GUI]
+CheckForUpdates=false
+CompactMode=false
+HidePreviewPanel=true
+HideToolbar=false
+MinimizeOnClose=false
+MinimizeOnStartup=true
+TrayIconAppearance=monochrome-light
+
+[KeeShare]
+Active="<?xml version=\"1.0\"?><KeeShare><Active/></KeeShare>\n"
+Foreign="<?xml version=\"1.0\"?>\n<KeeShare xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <Foreign/>\n</KeeShare>\n"
+Own="<?xml version=\"1.0\"?><KeeShare><PrivateKey>MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkFWY7hom7zgQJHmTknXljZmUa0C6v5cxJzbzq8dPbwVXg9WbBiUoM9nwzaA8szfOrQhqN8KLNIuyxlmluQvyCzqO5tTomMRwRmjK47Bj6PJGGYSsJQnzMoFxiYGTDCJgUQGhFSYXdJcdepSx6AAuE44s1CMCqiNuoVVh/RfT6Vi6U3eMYnHaDohZeBV8u+BzNr9g6fBJOQV2+duIQ2gtmg4qYt8m87Nbhlw84l8/UBZ0EQot95yIupspE3hfepuWGZFsHOfRHQo/JT2utAihw/uNmVAr3Run3IrsM/mBrk4TJfwRuJDLYUyz6eqXhpM9astXxVEdU7Id0+340FKldAgMBAAECggEAHQfCPuJVZpOGvPhi5BxNBoNSbBLCVn4bvesTWB4WlpppiVwCy7BjPfojfdGJWO0PziT4R0exGQYQdVwNKE0bYbTWbv0rnQ/UIENtoE7gsP0DksSMWz3cr5jbmWPmf1J5NN6rxuHgSXEVCq1gV1jpHm1t2v61sx7/QlI2lOB9GV2gQ/xYqgQaWmRXVKnUnruCDextohTtcS2pMbM7+xIcgp0j7b5Cc5WrA5nRG4nlD2Nbn8QNMOwK+sqXcCobLvzPCVR/P3pfmRx6D9Cq61AJW4l7R0bKiIDhOGZW+l2FUAceFWVFHx+iVRS6usoH/BarEOq81TrnM+jQHjzaL5o3uwKBgQDtvtuf7CHZy8BdW2a6uBtBSv4UstC7UCfjWiTqqGE6ds8Gp03IusKin78MhQaMkInU4aPozUq78x46+KEOyEwURi7la+QpsyWPlHI1stJ/jAQ94ntRAYg/UR8p2pEVF2T7KVJpXtEU+MuwEY1gIdHMNl3c1p+DhCZ/2OEbLR4VJwKBgQD1mKAkYXEKeyAEM03nZag3JxnQ9Ny4G4sYmkplVH1uuMANssUpkems7+Q77V8waUvISO4/GhXEAr1S9Bxmw/PaGcDZw5ym6tc40gkXGpSrn6PgXtEqzDlXuyhOiDxqQ0YWtPSwKZZgANtK5mromgpPjqXZQ7dIlfyMrgL1GOeH2wKBgQCeIg+lDIPrgMm/jtcCpQiD4mSj0dhibstJPqFFb5/UKkhDja6AMDDbyFNj+WtEvbLf5QGIDFyELQ5TfSJrWbC434G72YqWbfEy0jMxInM+oRwFKYqKc/Fy4/tNdHKBy+C/6llFeuqo/19ECji102jfYt4F0L+i05hj+xanY9gZiwKBgQDhGfcN4VHerWN29h8dTAuWIXyEDSqQhI5FCoXNwlcFOMiuxX/4zghDvcyPMM3ibWBMPqw/ogT5Fxm4Ao5Vkpza9mfQMH5Qb0a8iaZTSsWhWDy31bAZbf3Q73XOJQhazTZccZckL7noXGCikfbDIwz4RmK0dGB1YyOLPaLwStdLqQKBgD4JWKVaOmb+6GzRC4PaCQoW4QVb/JEmcSclmQMPLWRFLRdjTH9A9Z4710+GoE5K1MG+9JR/Cj5iGeHXvnvo0OEF/GAJ0UvEt5nPuSHjQQwnDyHBgiYbRe+SuYJy0nPsDCuwGWjvyAzWPZA56eQ5MzliRioDWNyXxJPHTQLjPm+z</PrivateKey><PublicKey><Signer>master</Signer><Key>MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkFWY7hom7zgQJHmTknXljZmUa0C6v5cxJzbzq8dPbwVXg9WbBiUoM9nwzaA8szfOrQhqN8KLNIuyxlmluQvyCzqO5tTomMRwRmjK47Bj6PJGGYSsJQnzMoFxiYGTDCJgUQGhFSYXdJcdepSx6AAuE44s1CMCqiNuoVVh/RfT6Vi6U3eMYnHaDohZeBV8u+BzNr9g6fBJOQV2+duIQ2gtmg4qYt8m87Nbhlw84l8/UBZ0EQot95yIupspE3hfepuWGZFsHOfRHQo/JT2utAihw/uNmVAr3Run3IrsM/mBrk4TJfwRuJDLYUyz6eqXhpM9astXxVEdU7Id0+340FKldAgMBAAECggEAHQfCPuJVZpOGvPhi5BxNBoNSbBLCVn4bvesTWB4WlpppiVwCy7BjPfojfdGJWO0PziT4R0exGQYQdVwNKE0bYbTWbv0rnQ/UIENtoE7gsP0DksSMWz3cr5jbmWPmf1J5NN6rxuHgSXEVCq1gV1jpHm1t2v61sx7/QlI2lOB9GV2gQ/xYqgQaWmRXVKnUnruCDextohTtcS2pMbM7+xIcgp0j7b5Cc5WrA5nRG4nlD2Nbn8QNMOwK+sqXcCobLvzPCVR/P3pfmRx6D9Cq61AJW4l7R0bKiIDhOGZW+l2FUAceFWVFHx+iVRS6usoH/BarEOq81TrnM+jQHjzaL5o3uwKBgQDtvtuf7CHZy8BdW2a6uBtBSv4UstC7UCfjWiTqqGE6ds8Gp03IusKin78MhQaMkInU4aPozUq78x46+KEOyEwURi7la+QpsyWPlHI1stJ/jAQ94ntRAYg/UR8p2pEVF2T7KVJpXtEU+MuwEY1gIdHMNl3c1p+DhCZ/2OEbLR4VJwKBgQD1mKAkYXEKeyAEM03nZag3JxnQ9Ny4G4sYmkplVH1uuMANssUpkems7+Q77V8waUvISO4/GhXEAr1S9Bxmw/PaGcDZw5ym6tc40gkXGpSrn6PgXtEqzDlXuyhOiDxqQ0YWtPSwKZZgANtK5mromgpPjqXZQ7dIlfyMrgL1GOeH2wKBgQCeIg+lDIPrgMm/jtcCpQiD4mSj0dhibstJPqFFb5/UKkhDja6AMDDbyFNj+WtEvbLf5QGIDFyELQ5TfSJrWbC434G72YqWbfEy0jMxInM+oRwFKYqKc/Fy4/tNdHKBy+C/6llFeuqo/19ECji102jfYt4F0L+i05hj+xanY9gZiwKBgQDhGfcN4VHerWN29h8dTAuWIXyEDSqQhI5FCoXNwlcFOMiuxX/4zghDvcyPMM3ibWBMPqw/ogT5Fxm4Ao5Vkpza9mfQMH5Qb0a8iaZTSsWhWDy31bAZbf3Q73XOJQhazTZccZckL7noXGCikfbDIwz4RmK0dGB1YyOLPaLwStdLqQKBgD4JWKVaOmb+6GzRC4PaCQoW4QVb/JEmcSclmQMPLWRFLRdjTH9A9Z4710+GoE5K1MG+9JR/Cj5iGeHXvnvo0OEF/GAJ0UvEt5nPuSHjQQwnDyHBgiYbRe+SuYJy0nPsDCuwGWjvyAzWPZA56eQ5MzliRioDWNyXxJPHTQLjPm+z</Key></PublicKey></KeeShare>\n"
+QuietSuccess=true
+
+[PasswordGenerator]
+AdditionalChars=
+AdvancedMode=false
+EnsureEvery=false
+ExcludeAlike=false
+ExcludedChars=
+Length=60
+Numbers=false
+SpecialChars=false
diff --git a/.config/lf/brodie/draw_img b/.config/lf/brodie/draw_img
new file mode 100644
index 0000000..5a70d5e
--- /dev/null
+++ b/.config/lf/brodie/draw_img
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+
+clear_screen() {
+ printf '\e[%sH\e[9999C\e[1J%b\e[1;%sr' \
+ "$((LINES-2))" "${TMUX:+\e[2J}" "$max_items"
+}
+
+# Get a file's mime_type.
+mime_type=$(file -bi "$1")
+
+# File isn't an image file, give warning.
+if [[ $mime_type != image/* ]]; then
+ lf -remote "send $id echoerr 'Not an image'"
+ exit
+fi
+
+w3m_paths=(/usr/{local/,}{lib,libexec,lib64,libexec64}/w3m/w3mi*)
+read -r w3m _ < <(type -p w3mimgdisplay "${w3m_paths[@]}")
+read -r LINES COLUMNS < <(stty size)
+
+# Get terminal window size in pixels and set it to WIDTH and HEIGHT.
+export $(xdotool getactivewindow getwindowgeometry --shell)
+
+# Get the image size in pixels.
+read -r img_width img_height < <("$w3m" <<< "5;${CACHE:-$1}")
+
+((img_width > WIDTH)) && {
+ ((img_height=img_height*WIDTH/img_width))
+ ((img_width=WIDTH))
+}
+
+((img_height > HEIGHT)) && {
+ ((img_width=img_width*HEIGHT/img_height))
+ ((img_height=HEIGHT))
+}
+
+# Variable needed for centering image.
+HALF_HEIGHT=$(expr $HEIGHT / 2)
+HALF_WIDTH=$(expr $WIDTH / 2)
+HALF_IMG_HEIGHT=$(expr $img_height / 2)
+HALF_IMG_WIDTH=$(expr $img_width / 2)
+X_POS=$(expr $HALF_WIDTH - $HALF_IMG_WIDTH)
+Y_POS=$(expr $HALF_HEIGHT - $HALF_IMG_HEIGHT)
+
+clear_screen
+# Hide the cursor.
+printf '\e[?25l'
+
+# Display the image.
+printf '0;1;%s;%s;%s;%s;;;;;%s\n3;\n4\n' \
+ ${X_POS:-0} \
+ ${Y_POS:-0} \
+ "$img_width" \
+ "$img_height" \
+ "${CACHE:-$1}" | "$w3m" &>/dev/null
+
+# Wait for user input.
+read -ern 1
+
+# Clear the image.
+printf '6;%s;%s;%s;%s\n3;' \
+ "${X_POS:-0}" \
+ "${Y_POS:-0}" \
+ "$WIDTH" \
+ "$HEIGHT" | "$w3m" &>/dev/null
+
+clear_screen
diff --git a/.config/lf/brodie/image b/.config/lf/brodie/image
new file mode 100644
index 0000000..77ddb5b
--- /dev/null
+++ b/.config/lf/brodie/image
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+readonly ID_PREVIEW="preview"
+main() {
+ case "$1" in
+ "clear")
+ declare -p -A cmd=([action]=remove [identifier]="$ID_PREVIEW") \
+ > "$FIFO_UEBERZUG"
+ ;;
+ "draw")
+ declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" \
+ [x]="$3" [y]="$4" [max_width]="$5" [max_height]="$6" \
+ [path]="$2") > "$FIFO_UEBERZUG"
+ ;;
+ "*") echo "Unknown command: '$1', '$2'" ;;
+ esac
+}
+main "$@"
+
diff --git a/.config/lf/brodie/preview b/.config/lf/brodie/preview
new file mode 100644
index 0000000..3069a06
--- /dev/null
+++ b/.config/lf/brodie/preview
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Clear the last preview (if any)
+$HOME/.config/lf/image clear
+
+# Calculate where the image should be placed on the screen.
+num=$(printf "%0.f\n" "`echo "$(tput cols) / 2" | bc`")
+numb=$(printf "%0.f\n" "`echo "$(tput cols) - $num - 1" | bc`")
+numc=$(printf "%0.f\n" "`echo "$(tput lines) - 2" | bc`")
+
+case "$1" in
+ *.tgz|*.tar.gz) tar tzf "$1";;
+ *.tar.bz2|*.tbz2) tar tjf "$1";;
+ *.tar.txz|*.txz) xz --list "$1";;
+ *.tar) tar tf "$1";;
+ *.zip|*.jar|*.war|*.ear|*.oxt) unzip -l "$1";;
+ *.rar) unrar l "$1";;
+ *.7z) 7z l "$1";;
+ *.[1-8]) man "$1" | col -b ;;
+ *.o) nm "$1" | less ;;
+ *.torrent) transmission-show "$1";;
+ *.iso) iso-info --no-header -l "$1";;
+ *odt,*.ods,*.odp,*.sxw) odt2txt "$1";;
+ *.doc) catdoc "$1" ;;
+ *.docx) docx2txt "$1" - ;;
+ *.csv) cat "$1" | sed s/,/\\n/g ;;
+ *.pdf)
+ CACHE=$(mktemp /tmp/thumbcache.XXXXX)
+ pdftoppm -png -f 1 -singlefile "$1" "$CACHE"
+ $HOME/.config/lf/image draw "$CACHE.png" $num 1 $numb $numc
+ ;;
+ *.epub)
+ CACHE=$(mktemp /tmp/thumbcache.XXXXX)
+ epub-thumbnailer "$1" "$CACHE" 1024
+ $HOME/.config/lf/image draw "$CACHE" $num 1 $numb $numc
+ ;;
+ *.bmp|*.jpg|*.jpeg|*.png|*.xpm)
+ $HOME/.config/lf/image draw "$1" $num 1 $numb $numc
+ ;;
+ *.wav|*.mp3|*.flac|*.m4a|*.wma|*.ape|*.ac3|*.og[agx]|*.spx|*.opus|*.as[fx]|*.flac) exiftool "$1";;
+ *.avi|*.mp4|*.wmv|*.dat|*.3gp|*.ogv|*.mkv|*.mpg|*.mpeg|*.vob|*.fl[icv]|*.m2v|*.mov|*.webm|*.ts|*.mts|*.m4v|*.r[am]|*.qt|*.divx)
+ CACHE=$(mktemp /tmp/thumbcache.XXXXX)
+ ffmpegthumbnailer -i "$1" -o "$CACHE" -s 0
+ $HOME/.config/lf/image draw "$CACHE" $num 1 $numb $numc
+ ;;
+ *) highlight --out-format ansi "$1" || cat "$1";;
+esac
+
diff --git a/.config/lf/colors b/.config/lf/colors
new file mode 100644
index 0000000..9edca7c
--- /dev/null
+++ b/.config/lf/colors
@@ -0,0 +1,175 @@
+# vim:ft=dircolors
+# (This is not a dircolors file but it helps to highlight colors and comments)
+
+# default values from dircolors
+# (entries with a leading # are not implemented in lf)
+# #no 00 # NORMAL
+# fi 00 # FILE
+# #rs 0 # RESET
+# di 01;34 # DIR
+# ln 01;36 # LINK
+# #mh 00 # MULTIHARDLINK
+# pi 40;33 # FIFO
+# so 01;35 # SOCK
+# #do 01;35 # DOOR
+# bd 40;33;01 # BLK
+# cd 40;33;01 # CHR
+# or 40;31;01 # ORPHAN
+# #mi 00 # MISSING
+# su 37;41 # SETUID
+# sg 30;43 # SETGID
+# #ca 30;41 # CAPABILITY
+# tw 30;42 # STICKY_OTHER_WRITABLE
+# ow 34;42 # OTHER_WRITABLE
+# st 37;44 # STICKY
+# ex 01;32 # EXEC
+
+# default values from lf (with matching order)
+# ln 01;36 # LINK
+# or 31;01 # ORPHAN
+# tw 01;34 # STICKY_OTHER_WRITABLE
+# ow 01;34 # OTHER_WRITABLE
+# st 01;34 # STICKY
+# di 01;34 # DIR
+# pi 33 # FIFO
+# so 01;35 # SOCK
+# bd 33;01 # BLK
+# cd 33;01 # CHR
+# su 01;32 # SETUID
+# sg 01;32 # SETGID
+# ex 01;32 # EXEC
+# fi 00 # FILE
+
+# file types (with matching order)
+ln 01;36 # LINK
+or 31;01 # ORPHAN
+tw 34 # STICKY_OTHER_WRITABLE
+ow 34 # OTHER_WRITABLE
+st 01;34 # STICKY
+di 01;34 # DIR
+pi 33 # FIFO
+so 01;35 # SOCK
+bd 33;01 # BLK
+cd 33;01 # CHR
+su 01;32 # SETUID
+sg 01;32 # SETGID
+ex 01;32 # EXEC
+fi 00 # FILE
+
+# archives or compressed (dircolors defaults)
+*.tar 01;31
+*.tgz 01;31
+*.arc 01;31
+*.arj 01;31
+*.taz 01;31
+*.lha 01;31
+*.lz4 01;31
+*.lzh 01;31
+*.lzma 01;31
+*.tlz 01;31
+*.txz 01;31
+*.tzo 01;31
+*.t7z 01;31
+*.zip 01;31
+*.z 01;31
+*.dz 01;31
+*.gz 01;31
+*.lrz 01;31
+*.lz 01;31
+*.lzo 01;31
+*.xz 01;31
+*.zst 01;31
+*.tzst 01;31
+*.bz2 01;31
+*.bz 01;31
+*.tbz 01;31
+*.tbz2 01;31
+*.tz 01;31
+*.deb 01;31
+*.rpm 01;31
+*.jar 01;31
+*.war 01;31
+*.ear 01;31
+*.sar 01;31
+*.rar 01;31
+*.alz 01;31
+*.ace 01;31
+*.zoo 01;31
+*.cpio 01;31
+*.7z 01;31
+*.rz 01;31
+*.cab 01;31
+*.wim 01;31
+*.swm 01;31
+*.dwm 01;31
+*.esd 01;31
+
+# image formats (dircolors defaults)
+*.jpg 01;35
+*.jpeg 01;35
+*.mjpg 01;35
+*.mjpeg 01;35
+*.gif 01;35
+*.bmp 01;35
+*.pbm 01;35
+*.pgm 01;35
+*.ppm 01;35
+*.tga 01;35
+*.xbm 01;35
+*.xpm 01;35
+*.tif 01;35
+*.tiff 01;35
+*.png 01;35
+*.webp 01;35
+*.svg 01;35
+*.svgz 01;35
+*.mng 01;35
+*.pcx 01;35
+*.mov 01;35
+*.mpg 01;35
+*.mpeg 01;35
+*.m2v 01;35
+*.mkv 01;35
+*.webm 01;35
+*.ogm 01;35
+*.mp4 01;35
+*.m4v 01;35
+*.mp4v 01;35
+*.vob 01;35
+*.qt 01;35
+*.nuv 01;35
+*.wmv 01;35
+*.asf 01;35
+*.rm 01;35
+*.rmvb 01;35
+*.flc 01;35
+*.avi 01;35
+*.fli 01;35
+*.flv 01;35
+*.gl 01;35
+*.dl 01;35
+*.xcf 01;35
+*.xwd 01;35
+*.yuv 01;35
+*.cgm 01;35
+*.emf 01;35
+*.ogv 01;35
+*.ogx 01;35
+
+# audio formats (dircolors defaults)
+*.aac 00;36
+*.au 00;36
+*.flac 00;36
+*.m4a 00;36
+*.mid 00;36
+*.midi 00;36
+*.mka 00;36
+*.mp3 00;36
+*.mpc 00;36
+*.ogg 00;36
+*.ra 00;36
+*.wav 00;36
+*.oga 00;36
+*.opus 00;36
+*.spx 00;36
+*.xspf 00;36
diff --git a/.config/lf/draw_img b/.config/lf/draw_img
new file mode 100644
index 0000000..5a70d5e
--- /dev/null
+++ b/.config/lf/draw_img
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+
+clear_screen() {
+ printf '\e[%sH\e[9999C\e[1J%b\e[1;%sr' \
+ "$((LINES-2))" "${TMUX:+\e[2J}" "$max_items"
+}
+
+# Get a file's mime_type.
+mime_type=$(file -bi "$1")
+
+# File isn't an image file, give warning.
+if [[ $mime_type != image/* ]]; then
+ lf -remote "send $id echoerr 'Not an image'"
+ exit
+fi
+
+w3m_paths=(/usr/{local/,}{lib,libexec,lib64,libexec64}/w3m/w3mi*)
+read -r w3m _ < <(type -p w3mimgdisplay "${w3m_paths[@]}")
+read -r LINES COLUMNS < <(stty size)
+
+# Get terminal window size in pixels and set it to WIDTH and HEIGHT.
+export $(xdotool getactivewindow getwindowgeometry --shell)
+
+# Get the image size in pixels.
+read -r img_width img_height < <("$w3m" <<< "5;${CACHE:-$1}")
+
+((img_width > WIDTH)) && {
+ ((img_height=img_height*WIDTH/img_width))
+ ((img_width=WIDTH))
+}
+
+((img_height > HEIGHT)) && {
+ ((img_width=img_width*HEIGHT/img_height))
+ ((img_height=HEIGHT))
+}
+
+# Variable needed for centering image.
+HALF_HEIGHT=$(expr $HEIGHT / 2)
+HALF_WIDTH=$(expr $WIDTH / 2)
+HALF_IMG_HEIGHT=$(expr $img_height / 2)
+HALF_IMG_WIDTH=$(expr $img_width / 2)
+X_POS=$(expr $HALF_WIDTH - $HALF_IMG_WIDTH)
+Y_POS=$(expr $HALF_HEIGHT - $HALF_IMG_HEIGHT)
+
+clear_screen
+# Hide the cursor.
+printf '\e[?25l'
+
+# Display the image.
+printf '0;1;%s;%s;%s;%s;;;;;%s\n3;\n4\n' \
+ ${X_POS:-0} \
+ ${Y_POS:-0} \
+ "$img_width" \
+ "$img_height" \
+ "${CACHE:-$1}" | "$w3m" &>/dev/null
+
+# Wait for user input.
+read -ern 1
+
+# Clear the image.
+printf '6;%s;%s;%s;%s\n3;' \
+ "${X_POS:-0}" \
+ "${Y_POS:-0}" \
+ "$WIDTH" \
+ "$HEIGHT" | "$w3m" &>/dev/null
+
+clear_screen
diff --git a/.config/lf/history b/.config/lf/history
new file mode 100644
index 0000000..1732142
--- /dev/null
+++ b/.config/lf/history
@@ -0,0 +1,7 @@
+$ mkdir "Gutar Gu S01 720p 10bit"
+$ mkdir Telusko
+$ mkdir Telusko
+$ mkdir system.txt
+$ mkdir Series
+$ chmod -x .dmenurc
+$ chmod -x .dmenurc
diff --git a/.config/lf/icons b/.config/lf/icons
new file mode 100644
index 0000000..7b900bc
--- /dev/null
+++ b/.config/lf/icons
@@ -0,0 +1,358 @@
+# vim:ft=conf
+
+# These examples require Nerd Fonts or a compatible font to be used.
+# See https://www.nerdfonts.com for more information.
+
+# default values from lf (with matching order)
+# ln l # LINK
+# or l # ORPHAN
+# tw t # STICKY_OTHER_WRITABLE
+# ow d # OTHER_WRITABLE
+# st t # STICKY
+# di d # DIR
+# pi p # FIFO
+# so s # SOCK
+# bd b # BLK
+# cd c # CHR
+# su u # SETUID
+# sg g # SETGID
+# ex x # EXEC
+# fi - # FILE
+
+# file types (with matching order)
+ln  # LINK
+or  # ORPHAN
+tw t # STICKY_OTHER_WRITABLE
+ow  # OTHER_WRITABLE
+st t # STICKY
+di  # DIR
+pi p # FIFO
+so s # SOCK
+bd b # BLK
+cd c # CHR
+su u # SETUID
+sg g # SETGID
+ex  # EXEC
+fi  # FILE
+
+# file extensions (vim-devicons)
+*.styl 
+*.sass 
+*.scss 
+*.htm 
+*.html 
+*.slim 
+*.haml 
+*.ejs 
+*.css 
+*.less 
+*.md 
+*.mdx 
+*.markdown 
+*.rmd 
+*.json 
+*.webmanifest 
+*.js 
+*.mjs 
+*.jsx 
+*.rb 
+*.gemspec 
+*.rake 
+*.php 
+*.py 
+*.pyc 
+*.pyo 
+*.pyd 
+*.coffee 
+*.mustache 
+*.hbs 
+*.conf 
+*.ini 
+*.yml 
+*.yaml 
+*.toml 
+*.bat 
+*.mk 
+*.jpg 
+*.jpeg 
+*.bmp 
+*.png 
+*.webp 
+*.gif 
+*.ico 
+*.twig 
+*.cpp 
+*.c++ 
+*.cxx 
+*.cc 
+*.cp 
+*.c 
+*.cs 󰌛
+*.h 
+*.hh 
+*.hpp 
+*.hxx 
+*.hs 
+*.lhs 
+*.nix 
+*.lua 
+*.java 
+*.sh 
+*.fish 
+*.bash 
+*.zsh 
+*.ksh 
+*.csh 
+*.awk 
+*.ps1 
+*.ml λ
+*.mli λ
+*.diff 
+*.db 
+*.sql 
+*.dump 
+*.clj 
+*.cljc 
+*.cljs 
+*.edn 
+*.scala 
+*.go 
+*.dart 
+*.xul 
+*.sln 
+*.suo 
+*.pl 
+*.pm 
+*.t 
+*.rss 
+'*.f#' 
+*.fsscript 
+*.fsx 
+*.fs 
+*.fsi 
+*.rs 
+*.rlib 
+*.d 
+*.erl 
+*.hrl 
+*.ex 
+*.exs 
+*.eex 
+*.leex 
+*.heex 
+*.vim 
+*.ai 
+*.psd 
+*.psb 
+*.ts 
+*.tsx 
+*.jl 
+*.pp 
+*.vue 
+*.elm 
+*.swift 
+*.xcplayground 
+*.tex 󰙩
+*.r 󰟔
+*.rproj 󰗆
+*.sol 󰡪
+*.pem 
+
+# file names (vim-devicons) (case-insensitive not supported in lf)
+*gruntfile.coffee 
+*gruntfile.js 
+*gruntfile.ls 
+*gulpfile.coffee 
+*gulpfile.js 
+*gulpfile.ls 
+*mix.lock 
+*dropbox 
+*.ds_store 
+*.gitconfig 
+*.gitignore 
+*.gitattributes 
+*.gitlab-ci.yml 
+*.bashrc 
+*.zshrc 
+*.zshenv 
+*.zprofile 
+*.vimrc 
+*.gvimrc 
+*_vimrc 
+*_gvimrc 
+*.bashprofile 
+*favicon.ico 
+*license 
+*node_modules 
+*react.jsx 
+*procfile 
+*dockerfile 
+*docker-compose.yml 
+*rakefile 
+*config.ru 
+*gemfile 
+*makefile 
+*cmakelists.txt 
+*robots.txt 󰚩
+
+# file names (case-sensitive adaptations)
+*Gruntfile.coffee 
+*Gruntfile.js 
+*Gruntfile.ls 
+*Gulpfile.coffee 
+*Gulpfile.js 
+*Gulpfile.ls 
+*Dropbox 
+*.DS_Store 
+*LICENSE 
+*React.jsx 
+*Procfile 
+*Dockerfile 
+*Docker-compose.yml 
+*Rakefile 
+*Gemfile 
+*Makefile 
+*CMakeLists.txt 
+
+# file patterns (vim-devicons) (patterns not supported in lf)
+# .*jquery.*\.js$ 
+# .*angular.*\.js$ 
+# .*backbone.*\.js$ 
+# .*require.*\.js$ 
+# .*materialize.*\.js$ 
+# .*materialize.*\.css$ 
+# .*mootools.*\.js$ 
+# .*vimrc.* 
+# Vagrantfile$ 
+
+# file patterns (file name adaptations)
+*jquery.min.js 
+*angular.min.js 
+*backbone.min.js 
+*require.min.js 
+*materialize.min.js 
+*materialize.min.css 
+*mootools.min.js 
+*vimrc 
+Vagrantfile 
+
+# archives or compressed (extensions from dircolors defaults)
+*.tar 
+*.tgz 
+*.arc 
+*.arj 
+*.taz 
+*.lha 
+*.lz4 
+*.lzh 
+*.lzma 
+*.tlz 
+*.txz 
+*.tzo 
+*.t7z 
+*.zip 
+*.z 
+*.dz 
+*.gz 
+*.lrz 
+*.lz 
+*.lzo 
+*.xz 
+*.zst 
+*.tzst 
+*.bz2 
+*.bz 
+*.tbz 
+*.tbz2 
+*.tz 
+*.deb 
+*.rpm 
+*.jar 
+*.war 
+*.ear 
+*.sar 
+*.rar 
+*.alz 
+*.ace 
+*.zoo 
+*.cpio 
+*.7z 
+*.rz 
+*.cab 
+*.wim 
+*.swm 
+*.dwm 
+*.esd 
+
+# image formats (extensions from dircolors defaults)
+*.jpg 
+*.jpeg 
+*.mjpg 
+*.mjpeg 
+*.gif 
+*.bmp 
+*.pbm 
+*.pgm 
+*.ppm 
+*.tga 
+*.xbm 
+*.xpm 
+*.tif 
+*.tiff 
+*.png 
+*.svg 
+*.svgz 
+*.mng 
+*.pcx 
+*.mov 
+*.mpg 
+*.mpeg 
+*.m2v 
+*.mkv 
+*.webm 
+*.ogm 
+*.mp4 
+*.m4v 
+*.mp4v 
+*.vob 
+*.qt 
+*.nuv 
+*.wmv 
+*.asf 
+*.rm 
+*.rmvb 
+*.flc 
+*.avi 
+*.fli 
+*.flv 
+*.gl 
+*.dl 
+*.xcf 
+*.xwd 
+*.yuv 
+*.cgm 
+*.emf 
+*.ogv 
+*.ogx 
+
+# audio formats (extensions from dircolors defaults)
+*.aac 
+*.au 
+*.flac 
+*.m4a 
+*.mid 
+*.midi 
+*.mka 
+*.mp3 
+*.mpc 
+*.ogg 
+*.ra 
+*.wav 
+*.oga 
+*.opus 
+*.spx 
+*.xspf 
+
+# other formats
+*.pdf 
+*.log 
diff --git a/.config/lf/image b/.config/lf/image
new file mode 100644
index 0000000..77ddb5b
--- /dev/null
+++ b/.config/lf/image
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+readonly ID_PREVIEW="preview"
+main() {
+ case "$1" in
+ "clear")
+ declare -p -A cmd=([action]=remove [identifier]="$ID_PREVIEW") \
+ > "$FIFO_UEBERZUG"
+ ;;
+ "draw")
+ declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" \
+ [x]="$3" [y]="$4" [max_width]="$5" [max_height]="$6" \
+ [path]="$2") > "$FIFO_UEBERZUG"
+ ;;
+ "*") echo "Unknown command: '$1', '$2'" ;;
+ esac
+}
+main "$@"
+
diff --git a/.config/lf/lfrc b/.config/lf/lfrc
new file mode 100644
index 0000000..daf9b1f
--- /dev/null
+++ b/.config/lf/lfrc
@@ -0,0 +1,160 @@
+# interpreter for shell commands
+set shell sh
+
+# set '-eu' options for shell commands
+# These options are used to have safer shell commands. Option '-e' is used to
+# exit on error and option '-u' is used to give error for unset variables.
+# Option '-f' disables pathname expansion which can be useful when $f, $fs, and
+# $fx variables contain names with '*' or '?' characters. However, this option
+# is used selectively within individual commands as it can be limiting at
+# times.
+set shellopts '-eu'
+
+# set internal field separator (IFS) to "\n" for shell commands
+# This is useful to automatically split file names in $fs and $fx properly
+# since default file separator used in these variables (i.e. 'filesep' option)
+# is newline. You need to consider the values of these options and create your
+# commands accordingly.
+set ifs "\n"
+
+# leave some space at the top and the bottom of the screen
+set scrolloff 5
+
+# Basic Settings
+set hidden true
+#set drawbox true
+set icons true
+set ignorecase true
+set smartcase true
+set mouse
+set previewer preview
+set preview
+
+cmd open $$OPENER $f
+
+cmd on-cd &{{
+ sed -i "\|^$PWD$|d" ${XDG_DATA_HOME:-$HOME/.local/share}/cdhist
+ echo "$PWD" >> ${XDG_DATA_HOME:-$HOME/.local/share}/cdhist
+}}
+
+cmd extract ${{
+ # extract the current file with the right command
+ # (xkcd link: https://xkcd.com/1168/)
+ set -f
+ for f in $fx; do case "$f" in
+ *.tar) tar xvf "$f" ;;
+ *.tar.bz|*.tar.bz2|*.tbz|*.tbz2) tar xjvf "$f" ;;
+ *.tar.gz|*.tgz) tar xzvf "$f" ;;
+ *.tar.xz|*.txz) tar xJvf "$f" ;;
+ *.gz) gunzip "$f" ;;
+ *.zip) unzip "$f" ;;
+ *.rar) unrar x "$f" ;;
+ *.7z) 7z x "$f" ;;
+ *.zst) unzstd "$f" ;;
+ *) echo "Unsupported format" >&2; exit 1 ;;
+ esac done
+}}
+
+cmd link_index %{{
+ case "$f" in
+ *.html) index="index.html" ;;
+ *) echo "Unsupported file"; exit 1 ;;
+ esac
+ [ -e "$index" ] && [ ! -L "$index" ] && {
+ echo "Failed: $index already exists and is not a symbolic link"
+ exit
+ }
+ ln -sf "$f" "$index"
+}}
+
+cmd select_eval ${{
+ res="$(eval "$@")"
+ [ -d "$res" ] &&
+ lf -remote "send $id cd \"$res\"" ||
+ lf -remote "send $id select \"$res\""
+}}
+
+cmd link %{{
+ set -- $(cat ~/.local/share/lf/files)
+ mode="$1"
+ shift
+ [ "$#" -lt 1 ] &&
+ { lf -remote "send $id echo no files to link"; exit 0; }
+ case "$mode" in
+ copy) ln -sr -t . -- "$@";;
+ move) ln -t . -- "$@";;
+ esac
+ rm ~/.local/share/lf/files
+ lf -remote "send clear"
+}}
+
+# Basic Functions
+cmap <tab> cmd-menu-complete
+cmap <backtab> cmd-menu-complete-back
+map <enter> shell
+map <delete> trash
+map <c-space> set preview!
+map <c-n> push $mkdir<space>""<c-b>
+map <a-s> :source ~/.config/lf/lfrc
+map <tab> :toggle; down
+map <backtab> :toggle; up
+map Z :toggle; up
+map <c-j> select_eval "fzf --reverse --header-first --header='Jump to location'"
+map <backspace> ${{ lf -remote "send $id select \"$(cat ${XDG_DATA_HOME:-$HOME/.local/share}/openhist |
+ fzf --tac --reverse --header-first --header='File History')\"" }}
+map <c-k> ${{ lf -remote "send $id cd \"$(cat ${XDG_DATA_HOME:-$HOME/.local/share}/cdhist |
+ fzf --tac --reverse --header-first --header='Path History')\"" }}
+map <c-c> ${{ lf -remote "send $id cd \"$(find -mindepth 1 -type d |
+ fzf --reverse --header-first --header='Jump to directory')\"" }}
+
+map c
+map d
+map I :rename; cmd-home
+map i :rename
+map a :rename; cmd-right
+map A :rename; cmd-end
+map S push A<c-u>
+map o $LESSOPEN="|preview %s" less $f
+map O $mimeopen --ask $f
+map . set hidden!
+map x cut
+map M $lf -remote "send $id select \"$(fmd)\""
+map D delete
+map W $setsid -f $TERMINAL >/dev/null 2>&1
+map X !$f
+map T !dev test $f
+map b $vidir
+map V push :!nvim<space>""<c-b>
+map P :link
+
+map ge extract $f
+map gl clear
+map gx ${{ chmod u+x $fx; lf -remote "send $id reload"; }}
+map gX ${{ chmod -x $fx; lf -remote "send $id reload"; }}
+map gm push $chmod<space>--<space>$fx<c-a><a-f><space>
+map gL %lf -remote "send ${id} select '$(readlink $f)'"
+map gd !du -hd1
+map gf !file $f
+map gy %{{ printf "%s" "$f" | xsel -b }}
+map gY %{{ printf "%s" "$fs" | xsel -b }}
+map gi link_index
+map gsh $setbg $f
+map gsl $setbg -l $f
+map zpp set previewer preview
+map zpc set previewer cat
+map zpb set previewer preview-bat
+map zph set previewer preview-highlight
+
+# Trash Mappings
+map dd ${{ echo "$fx" | xargs -I{} trash-put "{}" }}
+map dtc $trash-empty
+map dtr $trash-restore
+# Dragon Mapping
+map dr %dragon-drop -a -x $fx
+map ds %dragon-drop -a $fx
+map di %dragon-drop $fx
+map dm %cpdragon
+map dc %mvdragon
+map dl %dlfile
+
+source ~/.config/lf/shortcutrc
diff --git a/.config/lf/luke/scope b/.config/lf/luke/scope
new file mode 100644
index 0000000..cc55669
--- /dev/null
+++ b/.config/lf/luke/scope
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# File preview handler for lf.
+
+set -C -f
+IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}"
+
+image() {
+ if [ -f "$1" ] && [ -n "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] && command -V ueberzug >/dev/null 2>&1; then
+ printf '{"action": "add", "identifier": "PREVIEW", "x": "%s", "y": "%s", "width": "%s", "height": "%s", "scaler": "contain", "path": "%s"}\n' "$4" "$5" "$(($2-1))" "$(($3-1))" "$1" > "$FIFO_UEBERZUG"
+ else
+ mediainfo "$6"
+ fi
+}
+
+ifub() {
+ [ -n "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] && command -V ueberzug >/dev/null 2>&1
+}
+
+# Note that the cache file name is a function of file information, meaning if
+# an image appears in multiple places across the machine, it will not have to
+# be regenerated once seen.
+
+case "$(file --dereference --brief --mime-type -- "$1")" in
+ image/avif) CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
+ [ ! -f "$CACHE" ] && convert "$1" "$CACHE.jpg"
+ image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1" ;;
+ image/vnd.djvu)
+ CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
+ [ ! -f "$CACHE" ] && djvused "$1" -e 'select 1; save-page-with /dev/stdout' | convert -density 200 - "$CACHE.jpg" > /dev/null 2>&1
+ image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1" ;;
+ image/*) image "$1" "$2" "$3" "$4" "$5" "$1" ;;
+ text/html) lynx -width="$4" -display_charset=utf-8 -dump "$1" ;;
+ text/troff) man ./ "$1" | col -b ;;
+ text/* | */xml | application/json | application/x-ndjson) bat --terminal-width "$(($4-2))" -f "$1" ;;
+ audio/* | application/octet-stream) mediainfo "$1" || exit 1 ;;
+ video/* )
+ CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
+ [ ! -f "$CACHE" ] && ffmpegthumbnailer -i "$1" -o "$CACHE" -s 0
+ image "$CACHE" "$2" "$3" "$4" "$5" "$1"
+ ;;
+ */pdf)
+ CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
+ [ ! -f "$CACHE.jpg" ] && pdftoppm -jpeg -f 1 -singlefile "$1" "$CACHE"
+ image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1"
+ ;;
+ */epub+zip|*/mobi*)
+ CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | cut -d' ' -f1)"
+ [ ! -f "$CACHE.jpg" ] && gnome-epub-thumbnailer "$1" "$CACHE.jpg"
+ image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1"
+ ;;
+ application/*zip) atool --list -- "$1" ;;
+ *opendocument*) odt2txt "$1" ;;
+ application/pgp-encrypted) gpg -d -- "$1" ;;
+esac
+exit 1
diff --git a/.config/lf/preview b/.config/lf/preview
new file mode 100644
index 0000000..3069a06
--- /dev/null
+++ b/.config/lf/preview
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Clear the last preview (if any)
+$HOME/.config/lf/image clear
+
+# Calculate where the image should be placed on the screen.
+num=$(printf "%0.f\n" "`echo "$(tput cols) / 2" | bc`")
+numb=$(printf "%0.f\n" "`echo "$(tput cols) - $num - 1" | bc`")
+numc=$(printf "%0.f\n" "`echo "$(tput lines) - 2" | bc`")
+
+case "$1" in
+ *.tgz|*.tar.gz) tar tzf "$1";;
+ *.tar.bz2|*.tbz2) tar tjf "$1";;
+ *.tar.txz|*.txz) xz --list "$1";;
+ *.tar) tar tf "$1";;
+ *.zip|*.jar|*.war|*.ear|*.oxt) unzip -l "$1";;
+ *.rar) unrar l "$1";;
+ *.7z) 7z l "$1";;
+ *.[1-8]) man "$1" | col -b ;;
+ *.o) nm "$1" | less ;;
+ *.torrent) transmission-show "$1";;
+ *.iso) iso-info --no-header -l "$1";;
+ *odt,*.ods,*.odp,*.sxw) odt2txt "$1";;
+ *.doc) catdoc "$1" ;;
+ *.docx) docx2txt "$1" - ;;
+ *.csv) cat "$1" | sed s/,/\\n/g ;;
+ *.pdf)
+ CACHE=$(mktemp /tmp/thumbcache.XXXXX)
+ pdftoppm -png -f 1 -singlefile "$1" "$CACHE"
+ $HOME/.config/lf/image draw "$CACHE.png" $num 1 $numb $numc
+ ;;
+ *.epub)
+ CACHE=$(mktemp /tmp/thumbcache.XXXXX)
+ epub-thumbnailer "$1" "$CACHE" 1024
+ $HOME/.config/lf/image draw "$CACHE" $num 1 $numb $numc
+ ;;
+ *.bmp|*.jpg|*.jpeg|*.png|*.xpm)
+ $HOME/.config/lf/image draw "$1" $num 1 $numb $numc
+ ;;
+ *.wav|*.mp3|*.flac|*.m4a|*.wma|*.ape|*.ac3|*.og[agx]|*.spx|*.opus|*.as[fx]|*.flac) exiftool "$1";;
+ *.avi|*.mp4|*.wmv|*.dat|*.3gp|*.ogv|*.mkv|*.mpg|*.mpeg|*.vob|*.fl[icv]|*.m2v|*.mov|*.webm|*.ts|*.mts|*.m4v|*.r[am]|*.qt|*.divx)
+ CACHE=$(mktemp /tmp/thumbcache.XXXXX)
+ ffmpegthumbnailer -i "$1" -o "$CACHE" -s 0
+ $HOME/.config/lf/image draw "$CACHE" $num 1 $numb $numc
+ ;;
+ *) highlight --out-format ansi "$1" || cat "$1";;
+esac
+
diff --git a/.config/lxsession/i3/desktop.conf b/.config/lxsession/i3/desktop.conf
new file mode 100644
index 0000000..175a374
--- /dev/null
+++ b/.config/lxsession/i3/desktop.conf
@@ -0,0 +1,9 @@
+[Mouse]
+AccFactor=20
+AccThreshold=10
+LeftHanded=0
+
+[Keyboard]
+Delay=500
+Interval=30
+Beep=1
diff --git a/.config/nvim/autoload/airline/themes/onedark.vim b/.config/nvim/autoload/airline/themes/onedark.vim
new file mode 100644
index 0000000..65181dd
--- /dev/null
+++ b/.config/nvim/autoload/airline/themes/onedark.vim
@@ -0,0 +1,130 @@
+" [onedark.vim](https://github.com/joshdick/onedark.vim/)
+
+" This is a [vim-airline](https://github.com/vim-airline/vim-airline) theme for use with
+" the [onedark.vim](https://github.com/joshdick/onedark.vim) colorscheme.
+
+" It is based on vim-airline's ["tomorrow" theme](https://github.com/vim-airline/vim-airline-themes/blob/master/autoload/airline/themes/tomorrow.vim).
+function! airline#themes#onedark#refresh()
+ let s:colors = onedark#GetColors()
+
+ if get(g:, 'onedark_termcolors', 256) == 16
+ let s:term_red = s:colors.red.cterm16
+ let s:term_green = s:colors.green.cterm16
+ let s:term_yellow = s:colors.yellow.cterm16
+ let s:term_blue = s:colors.blue.cterm16
+ let s:term_purple = s:colors.purple.cterm16
+ let s:term_white = s:colors.white.cterm16
+ let s:term_cursor_grey = s:colors.cursor_grey.cterm16
+ let s:term_visual_grey = s:colors.visual_grey.cterm16
+ else
+ let s:term_red = s:colors.red.cterm
+ let s:term_green = s:colors.green.cterm
+ let s:term_yellow = s:colors.yellow.cterm
+ let s:term_blue = s:colors.blue.cterm
+ let s:term_purple = s:colors.purple.cterm
+ let s:term_white = s:colors.white.cterm
+ let s:term_cursor_grey = s:colors.cursor_grey.cterm
+ let s:term_visual_grey = s:colors.visual_grey.cterm
+ endif
+
+ let g:airline#themes#onedark#palette = {}
+
+ let g:airline#themes#onedark#palette.accents = {
+ \ 'red': [ s:colors.red.gui, '', s:term_red, 0 ]
+ \ }
+
+ let s:N1 = [ s:colors.cursor_grey.gui, s:colors.green.gui, s:term_cursor_grey, s:term_green ]
+ let s:N2 = [ s:colors.white.gui, s:colors.visual_grey.gui, s:term_white, s:term_visual_grey ]
+ let s:N3 = [ s:colors.green.gui, s:colors.cursor_grey.gui, s:term_green, s:term_cursor_grey ]
+ let g:airline#themes#onedark#palette.normal = airline#themes#generate_color_map(s:N1, s:N2, s:N3)
+
+ let group = airline#themes#get_highlight('vimCommand')
+ let g:airline#themes#onedark#palette.normal_modified = {
+ \ 'airline_c': [ group[0], '', group[2], '', '' ]
+ \ }
+
+ let s:I1 = [ s:colors.cursor_grey.gui, s:colors.blue.gui, s:term_cursor_grey, s:term_blue ]
+ let s:I2 = s:N2
+ let s:I3 = [ s:colors.blue.gui, s:colors.cursor_grey.gui, s:term_blue, '' ]
+ let g:airline#themes#onedark#palette.insert = airline#themes#generate_color_map(s:I1, s:I2, s:I3)
+ let g:airline#themes#onedark#palette.insert_modified = g:airline#themes#onedark#palette.normal_modified
+
+ let s:R1 = [ s:colors.cursor_grey.gui, s:colors.red.gui, s:term_cursor_grey, s:term_red ]
+ let s:R2 = s:N2
+ let s:R3 = [ s:colors.red.gui, s:colors.cursor_grey.gui, s:term_red, '' ]
+ let g:airline#themes#onedark#palette.replace = airline#themes#generate_color_map(s:R1, s:R2, s:R3)
+ let g:airline#themes#onedark#palette.replace_modified = g:airline#themes#onedark#palette.normal_modified
+
+ let s:V1 = [ s:colors.cursor_grey.gui, s:colors.purple.gui, s:term_cursor_grey, s:term_purple ]
+ let s:V2 = s:N2
+ let s:V3 = [ s:colors.purple.gui, s:colors.cursor_grey.gui, s:term_purple, '' ]
+ let g:airline#themes#onedark#palette.visual = airline#themes#generate_color_map(s:V1, s:V2, s:V3)
+ let g:airline#themes#onedark#palette.visual_modified = g:airline#themes#onedark#palette.normal_modified
+
+ let s:IA1 = [ s:colors.cursor_grey.gui, s:colors.white.gui, s:term_cursor_grey, s:term_white ]
+ let s:IA2 = [ s:colors.white.gui, s:colors.visual_grey.gui, s:term_white, s:term_visual_grey ]
+ let s:IA3 = s:N2
+ let g:airline#themes#onedark#palette.inactive = airline#themes#generate_color_map(s:IA1, s:IA2, s:IA3)
+ let g:airline#themes#onedark#palette.inactive_modified = {
+ \ 'airline_c': [ group[0], '', group[2], '', '' ]
+ \ }
+
+ " Warning/Error styling code from vim-airline's ["base16" theme](https://github.com/vim-airline/vim-airline-themes/blob/master/autoload/airline/themes/base16.vim)
+
+ " Warnings
+ let s:WI = [ s:colors.cursor_grey.gui, s:colors.yellow.gui, s:term_cursor_grey, s:term_yellow ]
+ let g:airline#themes#onedark#palette.normal.airline_warning = [
+ \ s:WI[0], s:WI[1], s:WI[2], s:WI[3]
+ \ ]
+
+ let g:airline#themes#onedark#palette.normal_modified.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ let g:airline#themes#onedark#palette.insert.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ let g:airline#themes#onedark#palette.insert_modified.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ let g:airline#themes#onedark#palette.visual.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ let g:airline#themes#onedark#palette.visual_modified.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ let g:airline#themes#onedark#palette.replace.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ let g:airline#themes#onedark#palette.replace_modified.airline_warning =
+ \ g:airline#themes#onedark#palette.normal.airline_warning
+
+ " Errors
+ let s:ER = [ s:colors.cursor_grey.gui, s:colors.red.gui, s:term_cursor_grey, s:term_red ]
+ let g:airline#themes#onedark#palette.normal.airline_error = [
+ \ s:ER[0], s:ER[1], s:ER[2], s:ER[3]
+ \ ]
+
+ let g:airline#themes#onedark#palette.normal_modified.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+ let g:airline#themes#onedark#palette.insert.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+ let g:airline#themes#onedark#palette.insert_modified.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+ let g:airline#themes#onedark#palette.visual.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+ let g:airline#themes#onedark#palette.visual_modified.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+ let g:airline#themes#onedark#palette.replace.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+ let g:airline#themes#onedark#palette.replace_modified.airline_error =
+ \ g:airline#themes#onedark#palette.normal.airline_error
+
+endfunction
+
+call airline#themes#onedark#refresh()
diff --git a/.config/nvim/autoload/lightline/colorscheme/onedark.vim b/.config/nvim/autoload/lightline/colorscheme/onedark.vim
new file mode 100644
index 0000000..d04a501
--- /dev/null
+++ b/.config/nvim/autoload/lightline/colorscheme/onedark.vim
@@ -0,0 +1,58 @@
+" [onedark.vim](https://github.com/joshdick/onedark.vim/)
+
+" This is a [lightline.vim](https://github.com/itchyny/lightline.vim) colorscheme for use with
+" the [onedark.vim](https://github.com/joshdick/onedark.vim) colorscheme.
+
+let s:colors = onedark#GetColors()
+
+if get(g:, 'onedark_termcolors', 256) == 16
+ let s:term_red = s:colors.red.cterm16
+ let s:term_green = s:colors.green.cterm16
+ let s:term_yellow = s:colors.yellow.cterm16
+ let s:term_blue = s:colors.blue.cterm16
+ let s:term_purple = s:colors.purple.cterm16
+ let s:term_white = s:colors.white.cterm16
+ let s:term_cursor_grey = s:colors.cursor_grey.cterm16
+ let s:term_visual_grey = s:colors.visual_grey.cterm16
+else
+ let s:term_red = s:colors.red.cterm
+ let s:term_green = s:colors.green.cterm
+ let s:term_yellow = s:colors.yellow.cterm
+ let s:term_blue = s:colors.blue.cterm
+ let s:term_purple = s:colors.purple.cterm
+ let s:term_white = s:colors.white.cterm
+ let s:term_cursor_grey = s:colors.cursor_grey.cterm
+ let s:term_visual_grey = s:colors.visual_grey.cterm
+endif
+
+let s:red = [ s:colors.red.gui, s:term_red ]
+let s:green = [ s:colors.green.gui, s:term_green ]
+let s:yellow = [ s:colors.yellow.gui, s:term_yellow ]
+let s:blue = [ s:colors.blue.gui, s:term_blue ]
+let s:purple = [ s:colors.purple.gui, s:term_purple ]
+let s:white = [ s:colors.white.gui, s:term_white ]
+let s:cursor_grey = [ s:colors.cursor_grey.gui, s:term_cursor_grey ]
+let s:visual_grey = [ s:colors.visual_grey.gui, s:term_visual_grey ]
+
+let s:p = {'normal': {}, 'inactive': {}, 'insert': {}, 'replace': {}, 'visual': {}, 'tabline': {}}
+let s:p.normal.left = [ [ s:cursor_grey, s:green ], [ s:white, s:visual_grey ] ]
+let s:p.normal.right = [ [ s:cursor_grey, s:green ], [ s:white, s:visual_grey ] ]
+let s:p.inactive.left = [ [ s:white, s:visual_grey ], [ s:white, s:visual_grey ] ]
+let s:p.inactive.right = [ [ s:cursor_grey, s:white ], [ s:cursor_grey, s:white ] ]
+let s:p.insert.left = [ [ s:cursor_grey, s:blue ], [ s:white, s:visual_grey ] ]
+let s:p.insert.right = [ [ s:cursor_grey, s:blue ], [ s:white, s:visual_grey ] ]
+let s:p.replace.left = [ [ s:cursor_grey, s:red ], [ s:white, s:visual_grey ] ]
+let s:p.replace.right = [ [ s:cursor_grey, s:red ], [ s:white, s:visual_grey ] ]
+let s:p.visual.left = [ [ s:cursor_grey, s:purple ], [ s:white, s:visual_grey ] ]
+let s:p.visual.right = [ [ s:cursor_grey, s:purple ], [ s:white, s:visual_grey ] ]
+let s:p.normal.middle = [ [ s:white, s:cursor_grey ] ]
+let s:p.inactive.middle = [ [ s:white, s:visual_grey ] ]
+let s:p.tabline.left = [ [ s:white, s:visual_grey ] ]
+let s:p.tabline.tabsel = [ [ s:cursor_grey, s:white ] ]
+let s:p.tabline.middle = [ [ s:white, s:cursor_grey ] ]
+let s:p.tabline.right = [ [ s:white, s:visual_grey ] ]
+let s:p.normal.error = [ [ s:cursor_grey, s:red ] ]
+let s:p.normal.warning = [ [ s:cursor_grey, s:yellow ] ]
+
+let g:lightline#colorscheme#onedark#palette = lightline#colorscheme#flatten(s:p)
+
diff --git a/.config/nvim/autoload/onedark.vim b/.config/nvim/autoload/onedark.vim
new file mode 100644
index 0000000..4630ff4
--- /dev/null
+++ b/.config/nvim/autoload/onedark.vim
@@ -0,0 +1,29 @@
+" [onedark.vim](https://github.com/joshdick/onedark.vim/)
+
+let s:overrides = get(g:, "onedark_color_overrides", {})
+
+let s:colors = {
+ \ "red": get(s:overrides, "red", { "gui": "#E06C75", "cterm": "204", "cterm16": "1" }),
+ \ "dark_red": get(s:overrides, "dark_red", { "gui": "#BE5046", "cterm": "196", "cterm16": "9" }),
+ \ "green": get(s:overrides, "green", { "gui": "#98C379", "cterm": "114", "cterm16": "2" }),
+ \ "yellow": get(s:overrides, "yellow", { "gui": "#E5C07B", "cterm": "180", "cterm16": "3" }),
+ \ "dark_yellow": get(s:overrides, "dark_yellow", { "gui": "#D19A66", "cterm": "173", "cterm16": "11" }),
+ \ "blue": get(s:overrides, "blue", { "gui": "#61AFEF", "cterm": "39", "cterm16": "4" }),
+ \ "purple": get(s:overrides, "purple", { "gui": "#C678DD", "cterm": "170", "cterm16": "5" }),
+ \ "cyan": get(s:overrides, "cyan", { "gui": "#56B6C2", "cterm": "38", "cterm16": "6" }),
+ \ "white": get(s:overrides, "white", { "gui": "#ABB2BF", "cterm": "145", "cterm16": "15" }),
+ \ "black": get(s:overrides, "black", { "gui": "#282C34", "cterm": "235", "cterm16": "0" }),
+ \ "foreground": get(s:overrides, "foreground", { "gui": "#ABB2BF", "cterm": "145", "cterm16": "NONE" }),
+ \ "background": get(s:overrides, "background", { "gui": "#282C34", "cterm": "235", "cterm16": "NONE" }),
+ \ "comment_grey": get(s:overrides, "comment_grey", { "gui": "#5C6370", "cterm": "59", "cterm16": "7" }),
+ \ "gutter_fg_grey": get(s:overrides, "gutter_fg_grey", { "gui": "#4B5263", "cterm": "238", "cterm16": "8" }),
+ \ "cursor_grey": get(s:overrides, "cursor_grey", { "gui": "#2C323C", "cterm": "236", "cterm16": "0" }),
+ \ "visual_grey": get(s:overrides, "visual_grey", { "gui": "#3E4452", "cterm": "237", "cterm16": "8" }),
+ \ "menu_grey": get(s:overrides, "menu_grey", { "gui": "#3E4452", "cterm": "237", "cterm16": "7" }),
+ \ "special_grey": get(s:overrides, "special_grey", { "gui": "#3B4048", "cterm": "238", "cterm16": "7" }),
+ \ "vertsplit": get(s:overrides, "vertsplit", { "gui": "#3E4452", "cterm": "59", "cterm16": "7" }),
+ \}
+
+function! onedark#GetColors()
+ return s:colors
+endfunction
diff --git a/.config/nvim/autoload/plug.vim b/.config/nvim/autoload/plug.vim
new file mode 100644
index 0000000..5c910ca
--- /dev/null
+++ b/.config/nvim/autoload/plug.vim
@@ -0,0 +1,2863 @@
+" vim-plug: Vim plugin manager
+" ============================
+"
+" 1. Download plug.vim and put it in 'autoload' directory
+"
+" # Vim
+" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
+" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
+"
+" # Neovim
+" sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \
+" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
+"
+" 2. Add a vim-plug section to your ~/.vimrc (or ~/.config/nvim/init.vim for Neovim)
+"
+" call plug#begin()
+"
+" " List your plugins here
+" Plug 'tpope/vim-sensible'
+"
+" call plug#end()
+"
+" 3. Reload the file or restart Vim, then you can,
+"
+" :PlugInstall to install plugins
+" :PlugUpdate to update plugins
+" :PlugDiff to review the changes from the last update
+" :PlugClean to remove plugins no longer in the list
+"
+" For more information, see https://github.com/junegunn/vim-plug
+"
+"
+" Copyright (c) 2024 Junegunn Choi
+"
+" MIT License
+"
+" Permission is hereby granted, free of charge, to any person obtaining
+" a copy of this software and associated documentation files (the
+" "Software"), to deal in the Software without restriction, including
+" without limitation the rights to use, copy, modify, merge, publish,
+" distribute, sublicense, and/or sell copies of the Software, and to
+" permit persons to whom the Software is furnished to do so, subject to
+" the following conditions:
+"
+" The above copyright notice and this permission notice shall be
+" included in all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if exists('g:loaded_plug')
+ finish
+endif
+let g:loaded_plug = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let s:plug_src = 'https://github.com/junegunn/vim-plug.git'
+let s:plug_tab = get(s:, 'plug_tab', -1)
+let s:plug_buf = get(s:, 'plug_buf', -1)
+let s:mac_gui = has('gui_macvim') && has('gui_running')
+let s:is_win = has('win32')
+let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)
+let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
+if s:is_win && &shellslash
+ set noshellslash
+ let s:me = resolve(expand('<sfile>:p'))
+ set shellslash
+else
+ let s:me = resolve(expand('<sfile>:p'))
+endif
+let s:base_spec = { 'branch': '', 'frozen': 0 }
+let s:TYPE = {
+\ 'string': type(''),
+\ 'list': type([]),
+\ 'dict': type({}),
+\ 'funcref': type(function('call'))
+\ }
+let s:loaded = get(s:, 'loaded', {})
+let s:triggers = get(s:, 'triggers', {})
+
+function! s:is_powershell(shell)
+ return a:shell =~# 'powershell\(\.exe\)\?$' || a:shell =~# 'pwsh\(\.exe\)\?$'
+endfunction
+
+function! s:isabsolute(dir) abort
+ return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)')
+endfunction
+
+function! s:git_dir(dir) abort
+ let gitdir = s:trim(a:dir) . '/.git'
+ if isdirectory(gitdir)
+ return gitdir
+ endif
+ if !filereadable(gitdir)
+ return ''
+ endif
+ let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*')
+ if len(gitdir) && !s:isabsolute(gitdir)
+ let gitdir = a:dir . '/' . gitdir
+ endif
+ return isdirectory(gitdir) ? gitdir : ''
+endfunction
+
+function! s:git_origin_url(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let config = gitdir . '/config'
+ if empty(gitdir) || !filereadable(config)
+ return ''
+ endif
+ return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze')
+endfunction
+
+function! s:git_revision(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+
+ let line = get(readfile(head), 0, '')
+ let ref = matchstr(line, '^ref: \zs.*')
+ if empty(ref)
+ return line
+ endif
+
+ if filereadable(gitdir . '/' . ref)
+ return get(readfile(gitdir . '/' . ref), 0, '')
+ endif
+
+ if filereadable(gitdir . '/packed-refs')
+ for line in readfile(gitdir . '/packed-refs')
+ if line =~# ' ' . ref
+ return matchstr(line, '^[0-9a-f]*')
+ endif
+ endfor
+ endif
+
+ return ''
+endfunction
+
+function! s:git_local_branch(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+ let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*')
+ return len(branch) ? branch : 'HEAD'
+endfunction
+
+function! s:git_origin_branch(spec)
+ if len(a:spec.branch)
+ return a:spec.branch
+ endif
+
+ " The file may not be present if this is a local repository
+ let gitdir = s:git_dir(a:spec.dir)
+ let origin_head = gitdir.'/refs/remotes/origin/HEAD'
+ if len(gitdir) && filereadable(origin_head)
+ return matchstr(get(readfile(origin_head), 0, ''),
+ \ '^ref: refs/remotes/origin/\zs.*')
+ endif
+
+ " The command may not return the name of a branch in detached HEAD state
+ let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir))
+ return v:shell_error ? '' : result[-1]
+endfunction
+
+if s:is_win
+ function! s:plug_call(fn, ...)
+ let shellslash = &shellslash
+ try
+ set noshellslash
+ return call(a:fn, a:000)
+ finally
+ let &shellslash = shellslash
+ endtry
+ endfunction
+else
+ function! s:plug_call(fn, ...)
+ return call(a:fn, a:000)
+ endfunction
+endif
+
+function! s:plug_getcwd()
+ return s:plug_call('getcwd')
+endfunction
+
+function! s:plug_fnamemodify(fname, mods)
+ return s:plug_call('fnamemodify', a:fname, a:mods)
+endfunction
+
+function! s:plug_expand(fmt)
+ return s:plug_call('expand', a:fmt, 1)
+endfunction
+
+function! s:plug_tempname()
+ return s:plug_call('tempname')
+endfunction
+
+function! plug#begin(...)
+ if a:0 > 0
+ let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p'))
+ elseif exists('g:plug_home')
+ let home = s:path(g:plug_home)
+ elseif has('nvim')
+ let home = stdpath('data') . '/plugged'
+ elseif !empty(&rtp)
+ let home = s:path(split(&rtp, ',')[0]) . '/plugged'
+ else
+ return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
+ endif
+ if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp
+ return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.')
+ endif
+
+ let g:plug_home = home
+ let g:plugs = {}
+ let g:plugs_order = []
+ let s:triggers = {}
+
+ call s:define_commands()
+ return 1
+endfunction
+
+function! s:define_commands()
+ command! -nargs=+ -bar Plug call plug#(<args>)
+ if !executable('git')
+ return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.')
+ endif
+ if has('win32')
+ \ && &shellslash
+ \ && (&shell =~# 'cmd\(\.exe\)\?$' || s:is_powershell(&shell))
+ return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.')
+ endif
+ if !has('nvim')
+ \ && (has('win32') || has('win32unix'))
+ \ && !has('multi_byte')
+ return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.')
+ endif
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>])
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(<bang>0, [<f-args>])
+ command! -nargs=0 -bar -bang PlugClean call s:clean(<bang>0)
+ command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif
+ command! -nargs=0 -bar PlugStatus call s:status()
+ command! -nargs=0 -bar PlugDiff call s:diff()
+ command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(<bang>0, <f-args>)
+endfunction
+
+function! s:to_a(v)
+ return type(a:v) == s:TYPE.list ? a:v : [a:v]
+endfunction
+
+function! s:to_s(v)
+ return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
+endfunction
+
+function! s:glob(from, pattern)
+ return s:lines(globpath(a:from, a:pattern))
+endfunction
+
+function! s:source(from, ...)
+ let found = 0
+ for pattern in a:000
+ for vim in s:glob(a:from, pattern)
+ execute 'source' s:esc(vim)
+ let found = 1
+ endfor
+ endfor
+ return found
+endfunction
+
+function! s:assoc(dict, key, val)
+ let a:dict[a:key] = add(get(a:dict, a:key, []), a:val)
+endfunction
+
+function! s:ask(message, ...)
+ call inputsave()
+ echohl WarningMsg
+ let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) '))
+ echohl None
+ call inputrestore()
+ echo "\r"
+ return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0
+endfunction
+
+function! s:ask_no_interrupt(...)
+ try
+ return call('s:ask', a:000)
+ catch
+ return 0
+ endtry
+endfunction
+
+function! s:lazy(plug, opt)
+ return has_key(a:plug, a:opt) &&
+ \ (empty(s:to_a(a:plug[a:opt])) ||
+ \ !isdirectory(a:plug.dir) ||
+ \ len(s:glob(s:rtp(a:plug), 'plugin')) ||
+ \ len(s:glob(s:rtp(a:plug), 'after/plugin')))
+endfunction
+
+function! plug#end()
+ if !exists('g:plugs')
+ return s:err('plug#end() called without calling plug#begin() first')
+ endif
+
+ if exists('#PlugLOD')
+ augroup PlugLOD
+ autocmd!
+ augroup END
+ augroup! PlugLOD
+ endif
+ let lod = { 'ft': {}, 'map': {}, 'cmd': {} }
+
+ if get(g:, 'did_load_filetypes', 0)
+ filetype off
+ endif
+ for name in g:plugs_order
+ if !has_key(g:plugs, name)
+ continue
+ endif
+ let plug = g:plugs[name]
+ if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for')
+ let s:loaded[name] = 1
+ continue
+ endif
+
+ if has_key(plug, 'on')
+ let s:triggers[name] = { 'map': [], 'cmd': [] }
+ for cmd in s:to_a(plug.on)
+ if cmd =~? '^<Plug>.\+'
+ if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
+ call s:assoc(lod.map, cmd, name)
+ endif
+ call add(s:triggers[name].map, cmd)
+ elseif cmd =~# '^[A-Z]'
+ let cmd = substitute(cmd, '!*$', '', '')
+ if exists(':'.cmd) != 2
+ call s:assoc(lod.cmd, cmd, name)
+ endif
+ call add(s:triggers[name].cmd, cmd)
+ else
+ call s:err('Invalid `on` option: '.cmd.
+ \ '. Should start with an uppercase letter or `<Plug>`.')
+ endif
+ endfor
+ endif
+
+ if has_key(plug, 'for')
+ let types = s:to_a(plug.for)
+ if !empty(types)
+ augroup filetypedetect
+ call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')
+ if has('nvim-0.5.0')
+ call s:source(s:rtp(plug), 'ftdetect/**/*.lua', 'after/ftdetect/**/*.lua')
+ endif
+ augroup END
+ endif
+ for type in types
+ call s:assoc(lod.ft, type, name)
+ endfor
+ endif
+ endfor
+
+ for [cmd, names] in items(lod.cmd)
+ execute printf(
+ \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
+ \ cmd, string(cmd), string(names))
+ endfor
+
+ for [map, names] in items(lod.map)
+ for [mode, map_prefix, key_prefix] in
+ \ [['i', '<C-\><C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
+ execute printf(
+ \ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, %s, "%s")<CR>',
+ \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix)
+ endfor
+ endfor
+
+ for [ft, names] in items(lod.ft)
+ augroup PlugLOD
+ execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
+ \ ft, string(ft), string(names))
+ augroup END
+ endfor
+
+ call s:reorg_rtp()
+ filetype plugin indent on
+ if has('vim_starting')
+ if has('syntax') && !exists('g:syntax_on')
+ syntax enable
+ end
+ else
+ call s:reload_plugins()
+ endif
+endfunction
+
+function! s:loaded_names()
+ return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)')
+endfunction
+
+function! s:load_plugin(spec)
+ call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim')
+ if has('nvim-0.5.0')
+ call s:source(s:rtp(a:spec), 'plugin/**/*.lua', 'after/plugin/**/*.lua')
+ endif
+endfunction
+
+function! s:reload_plugins()
+ for name in s:loaded_names()
+ call s:load_plugin(g:plugs[name])
+ endfor
+endfunction
+
+function! s:trim(str)
+ return substitute(a:str, '[\/]\+$', '', '')
+endfunction
+
+function! s:version_requirement(val, min)
+ for idx in range(0, len(a:min) - 1)
+ let v = get(a:val, idx, 0)
+ if v < a:min[idx] | return 0
+ elseif v > a:min[idx] | return 1
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:git_version_requirement(...)
+ if !exists('s:git_version')
+ let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)')
+ endif
+ return s:version_requirement(s:git_version, a:000)
+endfunction
+
+function! s:progress_opt(base)
+ return a:base && !s:is_win &&
+ \ s:git_version_requirement(1, 7, 1) ? '--progress' : ''
+endfunction
+
+function! s:rtp(spec)
+ return s:path(a:spec.dir . get(a:spec, 'rtp', ''))
+endfunction
+
+if s:is_win
+ function! s:path(path)
+ return s:trim(substitute(a:path, '/', '\', 'g'))
+ endfunction
+
+ function! s:dirpath(path)
+ return s:path(a:path) . '\'
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo =~? '^[a-z]:\|^[%~]'
+ endfunction
+
+ " Copied from fzf
+ function! s:wrap_cmds(cmds)
+ let cmds = [
+ \ '@echo off',
+ \ 'setlocal enabledelayedexpansion']
+ \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds])
+ \ + ['endlocal']
+ if has('iconv')
+ if !exists('s:codepage')
+ let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0)
+ endif
+ return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage))
+ endif
+ return map(cmds, 'v:val."\r"')
+ endfunction
+
+ function! s:batchfile(cmd)
+ let batchfile = s:plug_tempname().'.bat'
+ call writefile(s:wrap_cmds(a:cmd), batchfile)
+ let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0})
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ return [batchfile, cmd]
+ endfunction
+else
+ function! s:path(path)
+ return s:trim(a:path)
+ endfunction
+
+ function! s:dirpath(path)
+ return substitute(a:path, '[/\\]*$', '/', '')
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo[0] =~ '[/$~]'
+ endfunction
+endif
+
+function! s:err(msg)
+ echohl ErrorMsg
+ echom '[vim-plug] '.a:msg
+ echohl None
+endfunction
+
+function! s:warn(cmd, msg)
+ echohl WarningMsg
+ execute a:cmd 'a:msg'
+ echohl None
+endfunction
+
+function! s:esc(path)
+ return escape(a:path, ' ')
+endfunction
+
+function! s:escrtp(path)
+ return escape(a:path, ' ,')
+endfunction
+
+function! s:remove_rtp()
+ for name in s:loaded_names()
+ let rtp = s:rtp(g:plugs[name])
+ execute 'set rtp-='.s:escrtp(rtp)
+ let after = globpath(rtp, 'after')
+ if isdirectory(after)
+ execute 'set rtp-='.s:escrtp(after)
+ endif
+ endfor
+endfunction
+
+function! s:reorg_rtp()
+ if !empty(s:first_rtp)
+ execute 'set rtp-='.s:first_rtp
+ execute 'set rtp-='.s:last_rtp
+ endif
+
+ " &rtp is modified from outside
+ if exists('s:prtp') && s:prtp !=# &rtp
+ call s:remove_rtp()
+ unlet! s:middle
+ endif
+
+ let s:middle = get(s:, 'middle', &rtp)
+ let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
+ let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)')
+ let rtp = join(map(rtps, 'escape(v:val, ",")'), ',')
+ \ . ','.s:middle.','
+ \ . join(map(afters, 'escape(v:val, ",")'), ',')
+ let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
+ let s:prtp = &rtp
+
+ if !empty(s:first_rtp)
+ execute 'set rtp^='.s:first_rtp
+ execute 'set rtp+='.s:last_rtp
+ endif
+endfunction
+
+function! s:doautocmd(...)
+ if exists('#'.join(a:000, '#'))
+ execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)
+ endif
+endfunction
+
+function! s:dobufread(names)
+ for name in a:names
+ let path = s:rtp(g:plugs[name])
+ for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin']
+ if len(finddir(dir, path))
+ if exists('#BufRead')
+ doautocmd BufRead
+ endif
+ return
+ endif
+ endfor
+ endfor
+endfunction
+
+function! plug#load(...)
+ if a:0 == 0
+ return s:err('Argument missing: plugin name(s) required')
+ endif
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000
+ let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)')
+ if !empty(unknowns)
+ let s = len(unknowns) > 1 ? 's' : ''
+ return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
+ end
+ let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)')
+ if !empty(unloaded)
+ for name in unloaded
+ call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ endfor
+ call s:dobufread(unloaded)
+ return 1
+ end
+ return 0
+endfunction
+
+function! s:remove_triggers(name)
+ if !has_key(s:triggers, a:name)
+ return
+ endif
+ for cmd in s:triggers[a:name].cmd
+ execute 'silent! delc' cmd
+ endfor
+ for map in s:triggers[a:name].map
+ execute 'silent! unmap' map
+ execute 'silent! iunmap' map
+ endfor
+ call remove(s:triggers, a:name)
+endfunction
+
+function! s:lod(names, types, ...)
+ for name in a:names
+ call s:remove_triggers(name)
+ let s:loaded[name] = 1
+ endfor
+ call s:reorg_rtp()
+
+ for name in a:names
+ let rtp = s:rtp(g:plugs[name])
+ for dir in a:types
+ call s:source(rtp, dir.'/**/*.vim')
+ if has('nvim-0.5.0') " see neovim#14686
+ call s:source(rtp, dir.'/**/*.lua')
+ endif
+ endfor
+ if a:0
+ if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2))
+ execute 'runtime' a:1
+ endif
+ call s:source(rtp, a:2)
+ endif
+ call s:doautocmd('User', name)
+ endfor
+endfunction
+
+function! s:lod_ft(pat, names)
+ let syn = 'syntax/'.a:pat.'.vim'
+ call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)
+ execute 'autocmd! PlugLOD FileType' a:pat
+ call s:doautocmd('filetypeplugin', 'FileType')
+ call s:doautocmd('filetypeindent', 'FileType')
+endfunction
+
+function! s:lod_cmd(cmd, bang, l1, l2, args, names)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
+endfunction
+
+function! s:lod_map(map, names, with_prefix, prefix)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ let extra = ''
+ while 1
+ let c = getchar(0)
+ if c == 0
+ break
+ endif
+ let extra .= nr2char(c)
+ endwhile
+
+ if a:with_prefix
+ let prefix = v:count ? v:count : ''
+ let prefix .= '"'.v:register.a:prefix
+ if mode(1) == 'no'
+ if v:operator == 'c'
+ let prefix = "\<esc>" . prefix
+ endif
+ let prefix .= v:operator
+ endif
+ call feedkeys(prefix, 'n')
+ endif
+ call feedkeys(substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)
+endfunction
+
+function! plug#(repo, ...)
+ if a:0 > 1
+ return s:err('Invalid number of arguments (1..2)')
+ endif
+
+ try
+ let repo = s:trim(a:repo)
+ let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec
+ let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??'))
+ let spec = extend(s:infer_properties(name, repo), opts)
+ if !has_key(g:plugs, name)
+ call add(g:plugs_order, name)
+ endif
+ let g:plugs[name] = spec
+ let s:loaded[name] = get(s:loaded, name, 0)
+ catch
+ return s:err(repo . ' ' . v:exception)
+ endtry
+endfunction
+
+function! s:parse_options(arg)
+ let opts = copy(s:base_spec)
+ let type = type(a:arg)
+ let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)'
+ if type == s:TYPE.string
+ if empty(a:arg)
+ throw printf(opt_errfmt, 'tag', 'string')
+ endif
+ let opts.tag = a:arg
+ elseif type == s:TYPE.dict
+ for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as']
+ if has_key(a:arg, opt)
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string')
+ endif
+ endfor
+ for opt in ['on', 'for']
+ if has_key(a:arg, opt)
+ \ && type(a:arg[opt]) != s:TYPE.list
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string or list')
+ endif
+ endfor
+ if has_key(a:arg, 'do')
+ \ && type(a:arg.do) != s:TYPE.funcref
+ \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do))
+ throw printf(opt_errfmt, 'do', 'string or funcref')
+ endif
+ call extend(opts, a:arg)
+ if has_key(opts, 'dir')
+ let opts.dir = s:dirpath(s:plug_expand(opts.dir))
+ endif
+ else
+ throw 'Invalid argument type (expected: string or dictionary)'
+ endif
+ return opts
+endfunction
+
+function! s:infer_properties(name, repo)
+ let repo = a:repo
+ if s:is_local_plug(repo)
+ return { 'dir': s:dirpath(s:plug_expand(repo)) }
+ else
+ if repo =~ ':'
+ let uri = repo
+ else
+ if repo !~ '/'
+ throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo)
+ endif
+ let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')
+ let uri = printf(fmt, repo)
+ endif
+ return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri }
+ endif
+endfunction
+
+function! s:install(force, names)
+ call s:update_impl(0, a:force, a:names)
+endfunction
+
+function! s:update(force, names)
+ call s:update_impl(1, a:force, a:names)
+endfunction
+
+function! plug#helptags()
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ for spec in values(g:plugs)
+ let docd = join([s:rtp(spec), 'doc'], '/')
+ if isdirectory(docd)
+ silent! execute 'helptags' s:esc(docd)
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:syntax()
+ syntax clear
+ syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber
+ syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX,plugAbort
+ syn match plugNumber /[0-9]\+[0-9.]*/ contained
+ syn match plugBracket /[[\]]/ contained
+ syn match plugX /x/ contained
+ syn match plugAbort /\~/ contained
+ syn match plugDash /^-\{1}\ /
+ syn match plugPlus /^+/
+ syn match plugStar /^*/
+ syn match plugMessage /\(^- \)\@<=.*/
+ syn match plugName /\(^- \)\@<=[^ ]*:/
+ syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/
+ syn match plugTag /(tag: [^)]\+)/
+ syn match plugInstall /\(^+ \)\@<=[^:]*/
+ syn match plugUpdate /\(^* \)\@<=[^:]*/
+ syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag
+ syn match plugEdge /^ \X\+$/
+ syn match plugEdge /^ \X*/ contained nextgroup=plugSha
+ syn match plugSha /[0-9a-f]\{7,9}/ contained
+ syn match plugRelDate /([^)]*)$/ contained
+ syn match plugNotLoaded /(not loaded)$/
+ syn match plugError /^x.*/
+ syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/
+ syn match plugH2 /^.*:\n-\+$/
+ syn match plugH2 /^-\{2,}/
+ syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean
+ hi def link plug1 Title
+ hi def link plug2 Repeat
+ hi def link plugH2 Type
+ hi def link plugX Exception
+ hi def link plugAbort Ignore
+ hi def link plugBracket Structure
+ hi def link plugNumber Number
+
+ hi def link plugDash Special
+ hi def link plugPlus Constant
+ hi def link plugStar Boolean
+
+ hi def link plugMessage Function
+ hi def link plugName Label
+ hi def link plugInstall Function
+ hi def link plugUpdate Type
+
+ hi def link plugError Error
+ hi def link plugDeleted Ignore
+ hi def link plugRelDate Comment
+ hi def link plugEdge PreProc
+ hi def link plugSha Identifier
+ hi def link plugTag Constant
+
+ hi def link plugNotLoaded Comment
+endfunction
+
+function! s:lpad(str, len)
+ return a:str . repeat(' ', a:len - len(a:str))
+endfunction
+
+function! s:lines(msg)
+ return split(a:msg, "[\r\n]")
+endfunction
+
+function! s:lastline(msg)
+ return get(s:lines(a:msg), -1, '')
+endfunction
+
+function! s:new_window()
+ execute get(g:, 'plug_window', '-tabnew')
+endfunction
+
+function! s:plug_window_exists()
+ let buflist = tabpagebuflist(s:plug_tab)
+ return !empty(buflist) && index(buflist, s:plug_buf) >= 0
+endfunction
+
+function! s:switch_in()
+ if !s:plug_window_exists()
+ return 0
+ endif
+
+ if winbufnr(0) != s:plug_buf
+ let s:pos = [tabpagenr(), winnr(), winsaveview()]
+ execute 'normal!' s:plug_tab.'gt'
+ let winnr = bufwinnr(s:plug_buf)
+ execute winnr.'wincmd w'
+ call add(s:pos, winsaveview())
+ else
+ let s:pos = [winsaveview()]
+ endif
+
+ setlocal modifiable
+ return 1
+endfunction
+
+function! s:switch_out(...)
+ call winrestview(s:pos[-1])
+ setlocal nomodifiable
+ if a:0 > 0
+ execute a:1
+ endif
+
+ if len(s:pos) > 1
+ execute 'normal!' s:pos[0].'gt'
+ execute s:pos[1] 'wincmd w'
+ call winrestview(s:pos[2])
+ endif
+endfunction
+
+function! s:finish_bindings()
+ nnoremap <silent> <buffer> R :call <SID>retry()<cr>
+ nnoremap <silent> <buffer> D :PlugDiff<cr>
+ nnoremap <silent> <buffer> S :PlugStatus<cr>
+ nnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ xnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
+ nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
+endfunction
+
+function! s:prepare(...)
+ if empty(s:plug_getcwd())
+ throw 'Invalid current working directory. Cannot proceed.'
+ endif
+
+ for evar in ['$GIT_DIR', '$GIT_WORK_TREE']
+ if exists(evar)
+ throw evar.' detected. Cannot proceed.'
+ endif
+ endfor
+
+ call s:job_abort(0)
+ if s:switch_in()
+ if b:plug_preview == 1
+ pc
+ endif
+ enew
+ else
+ call s:new_window()
+ endif
+
+ nnoremap <silent> <buffer> q :call <SID>close_pane()<cr>
+ if a:0 == 0
+ call s:finish_bindings()
+ endif
+ let b:plug_preview = -1
+ let s:plug_tab = tabpagenr()
+ let s:plug_buf = winbufnr(0)
+ call s:assign_name()
+
+ for k in ['<cr>', 'L', 'o', 'X', 'd', 'dd']
+ execute 'silent! unmap <buffer>' k
+ endfor
+ setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell
+ if exists('+colorcolumn')
+ setlocal colorcolumn=
+ endif
+ setf vim-plug
+ if exists('g:syntax_on')
+ call s:syntax()
+ endif
+endfunction
+
+function! s:close_pane()
+ if b:plug_preview == 1
+ pc
+ let b:plug_preview = -1
+ elseif exists('s:jobs') && !empty(s:jobs)
+ call s:job_abort(1)
+ else
+ bd
+ endif
+endfunction
+
+function! s:assign_name()
+ " Assign buffer name
+ let prefix = '[Plugins]'
+ let name = prefix
+ let idx = 2
+ while bufexists(name)
+ let name = printf('%s (%s)', prefix, idx)
+ let idx = idx + 1
+ endwhile
+ silent! execute 'f' fnameescape(name)
+endfunction
+
+function! s:chsh(swap)
+ let prev = [&shell, &shellcmdflag, &shellredir]
+ if !s:is_win
+ set shell=sh
+ endif
+ if a:swap
+ if s:is_powershell(&shell)
+ let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s'
+ elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$'
+ set shellredir=>%s\ 2>&1
+ endif
+ endif
+ return prev
+endfunction
+
+function! s:bang(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(a:0)
+ " FIXME: Escaping is incomplete. We could use shellescape with eval,
+ " but it won't work on Windows.
+ let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%')
+ execute "normal! :execute g:_plug_bang\<cr>\<cr>"
+ finally
+ unlet g:_plug_bang
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ return v:shell_error ? 'Exit status: ' . v:shell_error : ''
+endfunction
+
+function! s:regress_bar()
+ let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '')
+ call s:progress_bar(2, bar, len(bar))
+endfunction
+
+function! s:is_updated(dir)
+ return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir))
+endfunction
+
+function! s:do(pull, force, todo)
+ if has('nvim')
+ " Reset &rtp to invalidate Neovim cache of loaded Lua modules
+ " See https://github.com/junegunn/vim-plug/pull/1157#issuecomment-1809226110
+ let &rtp = &rtp
+ endif
+ for [name, spec] in items(a:todo)
+ if !isdirectory(spec.dir)
+ continue
+ endif
+ let installed = has_key(s:update.new, name)
+ let updated = installed ? 0 :
+ \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir))
+ if a:force || installed || updated
+ execute 'cd' s:esc(spec.dir)
+ call append(3, '- Post-update hook for '. name .' ... ')
+ let error = ''
+ let type = type(spec.do)
+ if type == s:TYPE.string
+ if spec.do[0] == ':'
+ if !get(s:loaded, name, 0)
+ let s:loaded[name] = 1
+ call s:reorg_rtp()
+ endif
+ call s:load_plugin(spec)
+ try
+ execute spec.do[1:]
+ catch
+ let error = v:exception
+ endtry
+ if !s:plug_window_exists()
+ cd -
+ throw 'Warning: vim-plug was terminated by the post-update hook of '.name
+ endif
+ else
+ let error = s:bang(spec.do)
+ endif
+ elseif type == s:TYPE.funcref
+ try
+ call s:load_plugin(spec)
+ let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged')
+ call spec.do({ 'name': name, 'status': status, 'force': a:force })
+ catch
+ let error = v:exception
+ endtry
+ else
+ let error = 'Invalid hook type'
+ endif
+ call s:switch_in()
+ call setline(4, empty(error) ? (getline(4) . 'OK')
+ \ : ('x' . getline(4)[1:] . error))
+ if !empty(error)
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ endif
+ cd -
+ endif
+ endfor
+endfunction
+
+function! s:hash_match(a, b)
+ return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0
+endfunction
+
+function! s:checkout(spec)
+ let sha = a:spec.commit
+ let output = s:git_revision(a:spec.dir)
+ let error = 0
+ if !empty(output) && !s:hash_match(sha, s:lines(output)[0])
+ let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : ''
+ let output = s:system(
+ \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
+ let error = v:shell_error
+ endif
+ return [output, error]
+endfunction
+
+function! s:finish(pull)
+ let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))
+ if new_frozen
+ let s = new_frozen > 1 ? 's' : ''
+ call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
+ endif
+ call append(3, '- Finishing ... ') | 4
+ redraw
+ call plug#helptags()
+ call plug#end()
+ call setline(4, getline(4) . 'Done!')
+ redraw
+ let msgs = []
+ if !empty(s:update.errors)
+ call add(msgs, "Press 'R' to retry.")
+ endif
+ if a:pull && len(s:update.new) < len(filter(getline(5, '$'),
+ \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'"))
+ call add(msgs, "Press 'D' to see the updated changes.")
+ endif
+ echo join(msgs, ' ')
+ call s:finish_bindings()
+endfunction
+
+function! s:retry()
+ if empty(s:update.errors)
+ return
+ endif
+ echo
+ call s:update_impl(s:update.pull, s:update.force,
+ \ extend(copy(s:update.errors), [s:update.threads]))
+endfunction
+
+function! s:is_managed(name)
+ return has_key(g:plugs[a:name], 'uri')
+endfunction
+
+function! s:names(...)
+ return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
+endfunction
+
+function! s:check_ruby()
+ silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'")
+ if !exists('g:plug_ruby')
+ redraw!
+ return s:warn('echom', 'Warning: Ruby interface is broken')
+ endif
+ let ruby_version = split(g:plug_ruby, '\.')
+ unlet g:plug_ruby
+ return s:version_requirement(ruby_version, [1, 8, 7])
+endfunction
+
+function! s:update_impl(pull, force, args) abort
+ let sync = index(a:args, '--sync') >= 0 || has('vim_starting')
+ let args = filter(copy(a:args), 'v:val != "--sync"')
+ let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
+ \ remove(args, -1) : get(g:, 'plug_threads', 16)
+
+ let managed = filter(deepcopy(g:plugs), 's:is_managed(v:key)')
+ let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :
+ \ filter(managed, 'index(args, v:key) >= 0')
+
+ if empty(todo)
+ return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install'))
+ endif
+
+ if !s:is_win && s:git_version_requirement(2, 3)
+ let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : ''
+ let $GIT_TERMINAL_PROMPT = 0
+ for plug in values(todo)
+ let plug.uri = substitute(plug.uri,
+ \ '^https://git::@github\.com', 'https://github.com', '')
+ endfor
+ endif
+
+ if !isdirectory(g:plug_home)
+ try
+ call mkdir(g:plug_home, 'p')
+ catch
+ return s:err(printf('Invalid plug directory: %s. '.
+ \ 'Try to call plug#begin with a valid directory', g:plug_home))
+ endtry
+ endif
+
+ if has('nvim') && !exists('*jobwait') && threads > 1
+ call s:warn('echom', '[vim-plug] Update Neovim for parallel installer')
+ endif
+
+ let use_job = s:nvim || s:vim8
+ let python = (has('python') || has('python3')) && !use_job
+ let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby()
+
+ let s:update = {
+ \ 'start': reltime(),
+ \ 'all': todo,
+ \ 'todo': copy(todo),
+ \ 'errors': [],
+ \ 'pull': a:pull,
+ \ 'force': a:force,
+ \ 'new': {},
+ \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1,
+ \ 'bar': '',
+ \ 'fin': 0
+ \ }
+
+ call s:prepare(1)
+ call append(0, ['', ''])
+ normal! 2G
+ silent! redraw
+
+ " Set remote name, overriding a possible user git config's clone.defaultRemoteName
+ let s:clone_opt = ['--origin', 'origin']
+ if get(g:, 'plug_shallow', 1)
+ call extend(s:clone_opt, ['--depth', '1'])
+ if s:git_version_requirement(1, 7, 10)
+ call add(s:clone_opt, '--no-single-branch')
+ endif
+ endif
+
+ if has('win32unix') || has('wsl')
+ call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input'])
+ endif
+
+ let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : ''
+
+ " Python version requirement (>= 2.7)
+ if python && !has('python3') && !ruby && !use_job && s:update.threads > 1
+ redir => pyv
+ silent python import platform; print platform.python_version()
+ redir END
+ let python = s:version_requirement(
+ \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
+ endif
+
+ if (python || ruby) && s:update.threads > 1
+ try
+ let imd = &imd
+ if s:mac_gui
+ set noimd
+ endif
+ if ruby
+ call s:update_ruby()
+ else
+ call s:update_python()
+ endif
+ catch
+ let lines = getline(4, '$')
+ let printed = {}
+ silent! 4,$d _
+ for line in lines
+ let name = s:extract_name(line, '.', '')
+ if empty(name) || !has_key(printed, name)
+ call append('$', line)
+ if !empty(name)
+ let printed[name] = 1
+ if line[0] == 'x' && index(s:update.errors, name) < 0
+ call add(s:update.errors, name)
+ end
+ endif
+ endif
+ endfor
+ finally
+ let &imd = imd
+ call s:update_finish()
+ endtry
+ else
+ call s:update_vim()
+ while use_job && sync
+ sleep 100m
+ if s:update.fin
+ break
+ endif
+ endwhile
+ endif
+endfunction
+
+function! s:log4(name, msg)
+ call setline(4, printf('- %s (%s)', a:msg, a:name))
+ redraw
+endfunction
+
+function! s:update_finish()
+ if exists('s:git_terminal_prompt')
+ let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt
+ endif
+ if s:switch_in()
+ call append(3, '- Updating ...') | 4
+ for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))'))
+ let [pos, _] = s:logpos(name)
+ if !pos
+ continue
+ endif
+ let out = ''
+ let error = 0
+ if has_key(spec, 'commit')
+ call s:log4(name, 'Checking out '.spec.commit)
+ let [out, error] = s:checkout(spec)
+ elseif has_key(spec, 'tag')
+ let tag = spec.tag
+ if tag =~ '\*'
+ let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir))
+ if !v:shell_error && !empty(tags)
+ let tag = tags[0]
+ call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
+ call append(3, '')
+ endif
+ endif
+ call s:log4(name, 'Checking out '.tag)
+ let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
+ let error = v:shell_error
+ endif
+ if !error && filereadable(spec.dir.'/.gitmodules') &&
+ \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))
+ call s:log4(name, 'Updating submodules. This may take a while.')
+ let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir)
+ let error = v:shell_error
+ endif
+ let msg = s:format_message(v:shell_error ? 'x': '-', name, out)
+ if error
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ silent execute pos 'd _'
+ call append(4, msg) | 4
+ elseif !empty(out)
+ call setline(pos, msg[0])
+ endif
+ redraw
+ endfor
+ silent 4 d _
+ try
+ call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")'))
+ catch
+ call s:warn('echom', v:exception)
+ call s:warn('echo', '')
+ return
+ endtry
+ call s:finish(s:update.pull)
+ call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
+ call s:switch_out('normal! gg')
+ endif
+endfunction
+
+function! s:mark_aborted(name, message)
+ let attrs = { 'running': 0, 'error': 1, 'abort': 1, 'lines': [a:message] }
+ let s:jobs[a:name] = extend(get(s:jobs, a:name, {}), attrs)
+endfunction
+
+function! s:job_abort(cancel)
+ if (!s:nvim && !s:vim8) || !exists('s:jobs')
+ return
+ endif
+
+ for [name, j] in items(s:jobs)
+ if s:nvim
+ silent! call jobstop(j.jobid)
+ elseif s:vim8
+ silent! call job_stop(j.jobid)
+ endif
+ if j.new
+ call s:rm_rf(g:plugs[name].dir)
+ endif
+ if a:cancel
+ call s:mark_aborted(name, 'Aborted')
+ endif
+ endfor
+
+ if a:cancel
+ for todo in values(s:update.todo)
+ let todo.abort = 1
+ endfor
+ else
+ let s:jobs = {}
+ endif
+endfunction
+
+function! s:last_non_empty_line(lines)
+ let len = len(a:lines)
+ for idx in range(len)
+ let line = a:lines[len-idx-1]
+ if !empty(line)
+ return line
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:bullet_for(job, ...)
+ if a:job.running
+ return a:job.new ? '+' : '*'
+ endif
+ if get(a:job, 'abort', 0)
+ return '~'
+ endif
+ return a:job.error ? 'x' : get(a:000, 0, '-')
+endfunction
+
+function! s:job_out_cb(self, data) abort
+ let self = a:self
+ let data = remove(self.lines, -1) . a:data
+ let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]')
+ call extend(self.lines, lines)
+ " To reduce the number of buffer updates
+ let self.tick = get(self, 'tick', -1) + 1
+ if !self.running || self.tick % len(s:jobs) == 0
+ let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines)
+ if len(result)
+ call s:log(s:bullet_for(self), self.name, result)
+ endif
+ endif
+endfunction
+
+function! s:job_exit_cb(self, data) abort
+ let a:self.running = 0
+ let a:self.error = a:data != 0
+ call s:reap(a:self.name)
+ call s:tick()
+endfunction
+
+function! s:job_cb(fn, job, ch, data)
+ if !s:plug_window_exists() " plug window closed
+ return s:job_abort(0)
+ endif
+ call call(a:fn, [a:job, a:data])
+endfunction
+
+function! s:nvim_cb(job_id, data, event) dict abort
+ return (a:event == 'stdout' || a:event == 'stderr') ?
+ \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) :
+ \ s:job_cb('s:job_exit_cb', self, 0, a:data)
+endfunction
+
+function! s:spawn(name, spec, queue, opts)
+ let job = { 'name': a:name, 'spec': a:spec, 'running': 1, 'error': 0, 'lines': [''],
+ \ 'new': get(a:opts, 'new', 0), 'queue': copy(a:queue) }
+ let Item = remove(job.queue, 0)
+ let argv = type(Item) == s:TYPE.funcref ? call(Item, [a:spec]) : Item
+ let s:jobs[a:name] = job
+
+ if s:nvim
+ if has_key(a:opts, 'dir')
+ let job.cwd = a:opts.dir
+ endif
+ call extend(job, {
+ \ 'on_stdout': function('s:nvim_cb'),
+ \ 'on_stderr': function('s:nvim_cb'),
+ \ 'on_exit': function('s:nvim_cb'),
+ \ })
+ let jid = s:plug_call('jobstart', argv, job)
+ if jid > 0
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = [jid < 0 ? argv[0].' is not executable' :
+ \ 'Invalid arguments (or job table is full)']
+ endif
+ elseif s:vim8
+ let cmd = join(map(copy(argv), 'plug#shellescape(v:val, {"script": 0})'))
+ if has_key(a:opts, 'dir')
+ let cmd = s:with_cd(cmd, a:opts.dir, 0)
+ endif
+ let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd]
+ let jid = job_start(s:is_win ? join(argv, ' ') : argv, {
+ \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]),
+ \ 'err_mode': 'raw',
+ \ 'out_mode': 'raw'
+ \})
+ if job_status(jid) == 'run'
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = ['Failed to start job']
+ endif
+ else
+ let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [argv, a:opts.dir] : [argv]))
+ let job.error = v:shell_error != 0
+ let job.running = 0
+ endif
+endfunction
+
+function! s:reap(name)
+ let job = remove(s:jobs, a:name)
+ if job.error
+ call add(s:update.errors, a:name)
+ elseif get(job, 'new', 0)
+ let s:update.new[a:name] = 1
+ endif
+
+ let more = len(get(job, 'queue', []))
+ let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines)
+ if len(result)
+ call s:log(s:bullet_for(job), a:name, result)
+ endif
+
+ if !job.error && more
+ let job.spec.queue = job.queue
+ let s:update.todo[a:name] = job.spec
+ else
+ let s:update.bar .= s:bullet_for(job, '=')
+ call s:bar()
+ endif
+endfunction
+
+function! s:bar()
+ if s:switch_in()
+ let total = len(s:update.all)
+ call setline(1, (s:update.pull ? 'Updating' : 'Installing').
+ \ ' plugins ('.len(s:update.bar).'/'.total.')')
+ call s:progress_bar(2, s:update.bar, total)
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:logpos(name)
+ let max = line('$')
+ for i in range(4, max > 4 ? max : 4)
+ if getline(i) =~# '^[-+x*] '.a:name.':'
+ for j in range(i + 1, max > 5 ? max : 5)
+ if getline(j) !~ '^ '
+ return [i, j - 1]
+ endif
+ endfor
+ return [i, i]
+ endif
+ endfor
+ return [0, 0]
+endfunction
+
+function! s:log(bullet, name, lines)
+ if s:switch_in()
+ let [b, e] = s:logpos(a:name)
+ if b > 0
+ silent execute printf('%d,%d d _', b, e)
+ if b > winheight('.')
+ let b = 4
+ endif
+ else
+ let b = 4
+ endif
+ " FIXME For some reason, nomodifiable is set after :d in vim8
+ setlocal modifiable
+ call append(b - 1, s:format_message(a:bullet, a:name, a:lines))
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:update_vim()
+ let s:jobs = {}
+
+ call s:bar()
+ call s:tick()
+endfunction
+
+function! s:checkout_command(spec)
+ let a:spec.branch = s:git_origin_branch(a:spec)
+ return ['git', 'checkout', '-q', a:spec.branch, '--']
+endfunction
+
+function! s:merge_command(spec)
+ let a:spec.branch = s:git_origin_branch(a:spec)
+ return ['git', 'merge', '--ff-only', 'origin/'.a:spec.branch]
+endfunction
+
+function! s:tick()
+ let pull = s:update.pull
+ let prog = s:progress_opt(s:nvim || s:vim8)
+while 1 " Without TCO, Vim stack is bound to explode
+ if empty(s:update.todo)
+ if empty(s:jobs) && !s:update.fin
+ call s:update_finish()
+ let s:update.fin = 1
+ endif
+ return
+ endif
+
+ let name = keys(s:update.todo)[0]
+ let spec = remove(s:update.todo, name)
+ if get(spec, 'abort', 0)
+ call s:mark_aborted(name, 'Skipped')
+ call s:reap(name)
+ continue
+ endif
+
+ let queue = get(spec, 'queue', [])
+ let new = empty(globpath(spec.dir, '.git', 1))
+
+ if empty(queue)
+ call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
+ redraw
+ endif
+
+ let has_tag = has_key(spec, 'tag')
+ if len(queue)
+ call s:spawn(name, spec, queue, { 'dir': spec.dir })
+ elseif !new
+ let [error, _] = s:git_validate(spec, 0)
+ if empty(error)
+ if pull
+ let cmd = s:git_version_requirement(2) ? ['git', '-c', 'credential.helper=', 'fetch'] : ['git', 'fetch']
+ if has_tag && !empty(globpath(spec.dir, '.git/shallow'))
+ call extend(cmd, ['--depth', '99999999'])
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ let queue = [cmd, split('git remote set-head origin -a')]
+ if !has_tag && !has_key(spec, 'commit')
+ call extend(queue, [function('s:checkout_command'), function('s:merge_command')])
+ endif
+ call s:spawn(name, spec, queue, { 'dir': spec.dir })
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 }
+ endif
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 }
+ endif
+ else
+ let cmd = ['git', 'clone']
+ if !has_tag
+ call extend(cmd, s:clone_opt)
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, spec, [extend(cmd, [spec.uri, s:trim(spec.dir)]), function('s:checkout_command'), function('s:merge_command')], { 'new': 1 })
+ endif
+
+ if !s:jobs[name].running
+ call s:reap(name)
+ endif
+ if len(s:jobs) >= s:update.threads
+ break
+ endif
+endwhile
+endfunction
+
+function! s:update_python()
+let py_exe = has('python') ? 'python' : 'python3'
+execute py_exe "<< EOF"
+import datetime
+import functools
+import os
+try:
+ import queue
+except ImportError:
+ import Queue as queue
+import random
+import re
+import shutil
+import signal
+import subprocess
+import tempfile
+import threading as thr
+import time
+import traceback
+import vim
+
+G_NVIM = vim.eval("has('nvim')") == '1'
+G_PULL = vim.eval('s:update.pull') == '1'
+G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1
+G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))
+G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt'))
+G_PROGRESS = vim.eval('s:progress_opt(1)')
+G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))
+G_STOP = thr.Event()
+G_IS_WIN = vim.eval('s:is_win') == '1'
+
+class PlugError(Exception):
+ def __init__(self, msg):
+ self.msg = msg
+class CmdTimedOut(PlugError):
+ pass
+class CmdFailed(PlugError):
+ pass
+class InvalidURI(PlugError):
+ pass
+class Action(object):
+ INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-']
+
+class Buffer(object):
+ def __init__(self, lock, num_plugs, is_pull):
+ self.bar = ''
+ self.event = 'Updating' if is_pull else 'Installing'
+ self.lock = lock
+ self.maxy = int(vim.eval('winheight(".")'))
+ self.num_plugs = num_plugs
+
+ def __where(self, name):
+ """ Find first line with name in current buffer. Return line num. """
+ found, lnum = False, 0
+ matcher = re.compile('^[-+x*] {0}:'.format(name))
+ for line in vim.current.buffer:
+ if matcher.search(line) is not None:
+ found = True
+ break
+ lnum += 1
+
+ if not found:
+ lnum = -1
+ return lnum
+
+ def header(self):
+ curbuf = vim.current.buffer
+ curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs)
+
+ num_spaces = self.num_plugs - len(self.bar)
+ curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')
+
+ with self.lock:
+ vim.command('normal! 2G')
+ vim.command('redraw')
+
+ def write(self, action, name, lines):
+ first, rest = lines[0], lines[1:]
+ msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]
+ msg.extend([' ' + line for line in rest])
+
+ try:
+ if action == Action.ERROR:
+ self.bar += 'x'
+ vim.command("call add(s:update.errors, '{0}')".format(name))
+ elif action == Action.DONE:
+ self.bar += '='
+
+ curbuf = vim.current.buffer
+ lnum = self.__where(name)
+ if lnum != -1: # Found matching line num
+ del curbuf[lnum]
+ if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]):
+ lnum = 3
+ else:
+ lnum = 3
+ curbuf.append(msg, lnum)
+
+ self.header()
+ except vim.error:
+ pass
+
+class Command(object):
+ CD = 'cd /d' if G_IS_WIN else 'cd'
+
+ def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None):
+ self.cmd = cmd
+ if cmd_dir:
+ self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd)
+ self.timeout = timeout
+ self.callback = cb if cb else (lambda msg: None)
+ self.clean = clean if clean else (lambda: None)
+ self.proc = None
+
+ @property
+ def alive(self):
+ """ Returns true only if command still running. """
+ return self.proc and self.proc.poll() is None
+
+ def execute(self, ntries=3):
+ """ Execute the command with ntries if CmdTimedOut.
+ Returns the output of the command if no Exception.
+ """
+ attempt, finished, limit = 0, False, self.timeout
+
+ while not finished:
+ try:
+ attempt += 1
+ result = self.try_command()
+ finished = True
+ return result
+ except CmdTimedOut:
+ if attempt != ntries:
+ self.notify_retry()
+ self.timeout += limit
+ else:
+ raise
+
+ def notify_retry(self):
+ """ Retry required for command, notify user. """
+ for count in range(3, 0, -1):
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+ msg = 'Timeout. Will retry in {0} second{1} ...'.format(
+ count, 's' if count != 1 else '')
+ self.callback([msg])
+ time.sleep(1)
+ self.callback(['Retrying ...'])
+
+ def try_command(self):
+ """ Execute a cmd & poll for callback. Returns list of output.
+ Raises CmdFailed -> return code for Popen isn't 0
+ Raises CmdTimedOut -> command exceeded timeout without new output
+ """
+ first_line = True
+
+ try:
+ tfile = tempfile.NamedTemporaryFile(mode='w+b')
+ preexec_fn = not G_IS_WIN and os.setsid or None
+ self.proc = subprocess.Popen(self.cmd, stdout=tfile,
+ stderr=subprocess.STDOUT,
+ stdin=subprocess.PIPE, shell=True,
+ preexec_fn=preexec_fn)
+ thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,))
+ thrd.start()
+
+ thread_not_started = True
+ while thread_not_started:
+ try:
+ thrd.join(0.1)
+ thread_not_started = False
+ except RuntimeError:
+ pass
+
+ while self.alive:
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+
+ if first_line or random.random() < G_LOG_PROB:
+ first_line = False
+ line = '' if G_IS_WIN else nonblock_read(tfile.name)
+ if line:
+ self.callback([line])
+
+ time_diff = time.time() - os.path.getmtime(tfile.name)
+ if time_diff > self.timeout:
+ raise CmdTimedOut(['Timeout!'])
+
+ thrd.join(0.5)
+
+ tfile.seek(0)
+ result = [line.decode('utf-8', 'replace').rstrip() for line in tfile]
+
+ if self.proc.returncode != 0:
+ raise CmdFailed([''] + result)
+
+ return result
+ except:
+ self.terminate()
+ raise
+
+ def terminate(self):
+ """ Terminate process and cleanup. """
+ if self.alive:
+ if G_IS_WIN:
+ os.kill(self.proc.pid, signal.SIGINT)
+ else:
+ os.killpg(self.proc.pid, signal.SIGTERM)
+ self.clean()
+
+class Plugin(object):
+ def __init__(self, name, args, buf_q, lock):
+ self.name = name
+ self.args = args
+ self.buf_q = buf_q
+ self.lock = lock
+ self.tag = args.get('tag', 0)
+
+ def manage(self):
+ try:
+ if os.path.exists(self.args['dir']):
+ self.update()
+ else:
+ self.install()
+ with self.lock:
+ thread_vim_command("let s:update.new['{0}'] = 1".format(self.name))
+ except PlugError as exc:
+ self.write(Action.ERROR, self.name, exc.msg)
+ except KeyboardInterrupt:
+ G_STOP.set()
+ self.write(Action.ERROR, self.name, ['Interrupted!'])
+ except:
+ # Any exception except those above print stack trace
+ msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip())
+ self.write(Action.ERROR, self.name, msg.split('\n'))
+ raise
+
+ def install(self):
+ target = self.args['dir']
+ if target[-1] == '\\':
+ target = target[0:-1]
+
+ def clean(target):
+ def _clean():
+ try:
+ shutil.rmtree(target)
+ except OSError:
+ pass
+ return _clean
+
+ self.write(Action.INSTALL, self.name, ['Installing ...'])
+ callback = functools.partial(self.write, Action.INSTALL, self.name)
+ cmd = 'git clone {0} {1} {2} {3} 2>&1'.format(
+ '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'],
+ esc(target))
+ com = Command(cmd, None, G_TIMEOUT, callback, clean(target))
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+
+ def repo_uri(self):
+ cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url'
+ command = Command(cmd, self.args['dir'], G_TIMEOUT,)
+ result = command.execute(G_RETRIES)
+ return result[-1]
+
+ def update(self):
+ actual_uri = self.repo_uri()
+ expect_uri = self.args['uri']
+ regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$')
+ ma = regex.match(actual_uri)
+ mb = regex.match(expect_uri)
+ if ma is None or mb is None or ma.groups() != mb.groups():
+ msg = ['',
+ 'Invalid URI: {0}'.format(actual_uri),
+ 'Expected {0}'.format(expect_uri),
+ 'PlugClean required.']
+ raise InvalidURI(msg)
+
+ if G_PULL:
+ self.write(Action.UPDATE, self.name, ['Updating ...'])
+ callback = functools.partial(self.write, Action.UPDATE, self.name)
+ fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else ''
+ cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS)
+ com = Command(cmd, self.args['dir'], G_TIMEOUT, callback)
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+ else:
+ self.write(Action.DONE, self.name, ['Already installed'])
+
+ def write(self, action, name, msg):
+ self.buf_q.put((action, name, msg))
+
+class PlugThread(thr.Thread):
+ def __init__(self, tname, args):
+ super(PlugThread, self).__init__()
+ self.tname = tname
+ self.args = args
+
+ def run(self):
+ thr.current_thread().name = self.tname
+ buf_q, work_q, lock = self.args
+
+ try:
+ while not G_STOP.is_set():
+ name, args = work_q.get_nowait()
+ plug = Plugin(name, args, buf_q, lock)
+ plug.manage()
+ work_q.task_done()
+ except queue.Empty:
+ pass
+
+class RefreshThread(thr.Thread):
+ def __init__(self, lock):
+ super(RefreshThread, self).__init__()
+ self.lock = lock
+ self.running = True
+
+ def run(self):
+ while self.running:
+ with self.lock:
+ thread_vim_command('noautocmd normal! a')
+ time.sleep(0.33)
+
+ def stop(self):
+ self.running = False
+
+if G_NVIM:
+ def thread_vim_command(cmd):
+ vim.session.threadsafe_call(lambda: vim.command(cmd))
+else:
+ def thread_vim_command(cmd):
+ vim.command(cmd)
+
+def esc(name):
+ return '"' + name.replace('"', '\"') + '"'
+
+def nonblock_read(fname):
+ """ Read a file with nonblock flag. Return the last line. """
+ fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK)
+ buf = os.read(fread, 100000).decode('utf-8', 'replace')
+ os.close(fread)
+
+ line = buf.rstrip('\r\n')
+ left = max(line.rfind('\r'), line.rfind('\n'))
+ if left != -1:
+ left += 1
+ line = line[left:]
+
+ return line
+
+def main():
+ thr.current_thread().name = 'main'
+ nthreads = int(vim.eval('s:update.threads'))
+ plugs = vim.eval('s:update.todo')
+ mac_gui = vim.eval('s:mac_gui') == '1'
+
+ lock = thr.Lock()
+ buf = Buffer(lock, len(plugs), G_PULL)
+ buf_q, work_q = queue.Queue(), queue.Queue()
+ for work in plugs.items():
+ work_q.put(work)
+
+ start_cnt = thr.active_count()
+ for num in range(nthreads):
+ tname = 'PlugT-{0:02}'.format(num)
+ thread = PlugThread(tname, (buf_q, work_q, lock))
+ thread.start()
+ if mac_gui:
+ rthread = RefreshThread(lock)
+ rthread.start()
+
+ while not buf_q.empty() or thr.active_count() != start_cnt:
+ try:
+ action, name, msg = buf_q.get(True, 0.25)
+ buf.write(action, name, ['OK'] if not msg else msg)
+ buf_q.task_done()
+ except queue.Empty:
+ pass
+ except KeyboardInterrupt:
+ G_STOP.set()
+
+ if mac_gui:
+ rthread.stop()
+ rthread.join()
+
+main()
+EOF
+endfunction
+
+function! s:update_ruby()
+ ruby << EOF
+ module PlugStream
+ SEP = ["\r", "\n", nil]
+ def get_line
+ buffer = ''
+ loop do
+ char = readchar rescue return
+ if SEP.include? char.chr
+ buffer << $/
+ break
+ else
+ buffer << char
+ end
+ end
+ buffer
+ end
+ end unless defined?(PlugStream)
+
+ def esc arg
+ %["#{arg.gsub('"', '\"')}"]
+ end
+
+ def killall pid
+ pids = [pid]
+ if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil }
+ else
+ unless `which pgrep 2> /dev/null`.empty?
+ children = pids
+ until children.empty?
+ children = children.map { |pid|
+ `pgrep -P #{pid}`.lines.map { |l| l.chomp }
+ }.flatten
+ pids += children
+ end
+ end
+ pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }
+ end
+ end
+
+ def compare_git_uri a, b
+ regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$}
+ regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1)
+ end
+
+ require 'thread'
+ require 'fileutils'
+ require 'timeout'
+ running = true
+ iswin = VIM::evaluate('s:is_win').to_i == 1
+ pull = VIM::evaluate('s:update.pull').to_i == 1
+ base = VIM::evaluate('g:plug_home')
+ all = VIM::evaluate('s:update.todo')
+ limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
+ tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1
+ nthr = VIM::evaluate('s:update.threads').to_i
+ maxy = VIM::evaluate('winheight(".")').to_i
+ vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/
+ cd = iswin ? 'cd /d' : 'cd'
+ tot = VIM::evaluate('len(s:update.todo)') || 0
+ bar = ''
+ skip = 'Already installed'
+ mtx = Mutex.new
+ take1 = proc { mtx.synchronize { running && all.shift } }
+ logh = proc {
+ cnt = bar.length
+ $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"
+ $curbuf[2] = '[' + bar.ljust(tot) + ']'
+ VIM::command('normal! 2G')
+ VIM::command('redraw')
+ }
+ where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } }
+ log = proc { |name, result, type|
+ mtx.synchronize do
+ ing = ![true, false].include?(type)
+ bar += type ? '=' : 'x' unless ing
+ b = case type
+ when :install then '+' when :update then '*'
+ when true, nil then '-' else
+ VIM::command("call add(s:update.errors, '#{name}')")
+ 'x'
+ end
+ result =
+ if type || type.nil?
+ ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"]
+ elsif result =~ /^Interrupted|^Timeout/
+ ["#{b} #{name}: #{result}"]
+ else
+ ["#{b} #{name}"] + result.lines.map { |l| " " << l }
+ end
+ if lnum = where.call(name)
+ $curbuf.delete lnum
+ lnum = 4 if ing && lnum > maxy
+ end
+ result.each_with_index do |line, offset|
+ $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp)
+ end
+ logh.call
+ end
+ }
+ bt = proc { |cmd, name, type, cleanup|
+ tried = timeout = 0
+ begin
+ tried += 1
+ timeout += limit
+ fd = nil
+ data = ''
+ if iswin
+ Timeout::timeout(timeout) do
+ tmp = VIM::evaluate('tempname()')
+ system("(#{cmd}) > #{tmp}")
+ data = File.read(tmp).chomp
+ File.unlink tmp rescue nil
+ end
+ else
+ fd = IO.popen(cmd).extend(PlugStream)
+ first_line = true
+ log_prob = 1.0 / nthr
+ while line = Timeout::timeout(timeout) { fd.get_line }
+ data << line
+ log.call name, line.chomp, type if name && (first_line || rand < log_prob)
+ first_line = false
+ end
+ fd.close
+ end
+ [$? == 0, data.chomp]
+ rescue Timeout::Error, Interrupt => e
+ if fd && !fd.closed?
+ killall fd.pid
+ fd.close
+ end
+ cleanup.call if cleanup
+ if e.is_a?(Timeout::Error) && tried < tries
+ 3.downto(1) do |countdown|
+ s = countdown > 1 ? 's' : ''
+ log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type
+ sleep 1
+ end
+ log.call name, 'Retrying ...', type
+ retry
+ end
+ [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]
+ end
+ }
+ main = Thread.current
+ threads = []
+ watcher = Thread.new {
+ if vim7
+ while VIM::evaluate('getchar(1)')
+ sleep 0.1
+ end
+ else
+ require 'io/console' # >= Ruby 1.9
+ nil until IO.console.getch == 3.chr
+ end
+ mtx.synchronize do
+ running = false
+ threads.each { |t| t.raise Interrupt } unless vim7
+ end
+ threads.each { |t| t.join rescue nil }
+ main.kill
+ }
+ refresh = Thread.new {
+ while true
+ mtx.synchronize do
+ break unless running
+ VIM::command('noautocmd normal! a')
+ end
+ sleep 0.2
+ end
+ } if VIM::evaluate('s:mac_gui') == 1
+
+ clone_opt = VIM::evaluate('s:clone_opt').join(' ')
+ progress = VIM::evaluate('s:progress_opt(1)')
+ nthr.times do
+ mtx.synchronize do
+ threads << Thread.new {
+ while pair = take1.call
+ name = pair.first
+ dir, uri, tag = pair.last.values_at *%w[dir uri tag]
+ exists = File.directory? dir
+ ok, result =
+ if exists
+ chdir = "#{cd} #{iswin ? dir : esc(dir)}"
+ ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil
+ current_uri = data.lines.to_a.last
+ if !ret
+ if data =~ /^Interrupted|^Timeout/
+ [false, data]
+ else
+ [false, [data.chomp, "PlugClean required."].join($/)]
+ end
+ elsif !compare_git_uri(current_uri, uri)
+ [false, ["Invalid URI: #{current_uri}",
+ "Expected: #{uri}",
+ "PlugClean required."].join($/)]
+ else
+ if pull
+ log.call name, 'Updating ...', :update
+ fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : ''
+ bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil
+ else
+ [true, skip]
+ end
+ end
+ else
+ d = esc dir.sub(%r{[\\/]+$}, '')
+ log.call name, 'Installing ...', :install
+ bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc {
+ FileUtils.rm_rf dir
+ }
+ end
+ mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok
+ log.call name, result, ok
+ end
+ } if running
+ end
+ end
+ threads.each { |t| t.join rescue nil }
+ logh.call
+ refresh.kill if refresh
+ watcher.kill
+EOF
+endfunction
+
+function! s:shellesc_cmd(arg, script)
+ let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g')
+ return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g')
+endfunction
+
+function! s:shellesc_ps1(arg)
+ return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'"
+endfunction
+
+function! s:shellesc_sh(arg)
+ return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"
+endfunction
+
+" Escape the shell argument based on the shell.
+" Vim and Neovim's shellescape() are insufficient.
+" 1. shellslash determines whether to use single/double quotes.
+" Double-quote escaping is fragile for cmd.exe.
+" 2. It does not work for powershell.
+" 3. It does not work for *sh shells if the command is executed
+" via cmd.exe (ie. cmd.exe /c sh -c command command_args)
+" 4. It does not support batchfile syntax.
+"
+" Accepts an optional dictionary with the following keys:
+" - shell: same as Vim/Neovim 'shell' option.
+" If unset, fallback to 'cmd.exe' on Windows or 'sh'.
+" - script: If truthy and shell is cmd.exe, escape for batchfile syntax.
+function! plug#shellescape(arg, ...)
+ if a:arg =~# '^[A-Za-z0-9_/:.-]\+$'
+ return a:arg
+ endif
+ let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
+ let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')
+ let script = get(opts, 'script', 1)
+ if shell =~# 'cmd\(\.exe\)\?$'
+ return s:shellesc_cmd(a:arg, script)
+ elseif s:is_powershell(shell)
+ return s:shellesc_ps1(a:arg)
+ endif
+ return s:shellesc_sh(a:arg)
+endfunction
+
+function! s:glob_dir(path)
+ return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
+endfunction
+
+function! s:progress_bar(line, bar, total)
+ call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']')
+endfunction
+
+function! s:compare_git_uri(a, b)
+ " See `git help clone'
+ " https:// [user@] github.com[:port] / junegunn/vim-plug [.git]
+ " [git@] github.com[:port] : junegunn/vim-plug [.git]
+ " file:// / junegunn/vim-plug [/]
+ " / junegunn/vim-plug [/]
+ let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$'
+ let ma = matchlist(a:a, pat)
+ let mb = matchlist(a:b, pat)
+ return ma[1:2] ==# mb[1:2]
+endfunction
+
+function! s:format_message(bullet, name, message)
+ if a:bullet != 'x'
+ return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]
+ else
+ let lines = map(s:lines(a:message), '" ".v:val')
+ return extend([printf('x %s:', a:name)], lines)
+ endif
+endfunction
+
+function! s:with_cd(cmd, dir, ...)
+ let script = a:0 > 0 ? a:1 : 1
+ let pwsh = s:is_powershell(&shell)
+ let cd = s:is_win && !pwsh ? 'cd /d' : 'cd'
+ let sep = pwsh ? ';' : '&&'
+ return printf('%s %s %s %s', cd, plug#shellescape(a:dir, {'script': script, 'shell': &shell}), sep, a:cmd)
+endfunction
+
+function! s:system(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ if type(a:cmd) == s:TYPE.list
+ " Neovim's system() supports list argument to bypass the shell
+ " but it cannot set the working directory for the command.
+ " Assume that the command does not rely on the shell.
+ if has('nvim') && a:0 == 0
+ return system(a:cmd)
+ endif
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ else
+ let cmd = a:cmd
+ endif
+ if a:0 > 0
+ let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)
+ endif
+ if s:is_win && type(a:cmd) != s:TYPE.list
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ return system(cmd)
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+endfunction
+
+function! s:system_chomp(...)
+ let ret = call('s:system', a:000)
+ return v:shell_error ? '' : substitute(ret, '\n$', '', '')
+endfunction
+
+function! s:git_validate(spec, check_branch)
+ let err = ''
+ if isdirectory(a:spec.dir)
+ let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)]
+ let remote = result[-1]
+ if empty(remote)
+ let err = join([remote, 'PlugClean required.'], "\n")
+ elseif !s:compare_git_uri(remote, a:spec.uri)
+ let err = join(['Invalid URI: '.remote,
+ \ 'Expected: '.a:spec.uri,
+ \ 'PlugClean required.'], "\n")
+ elseif a:check_branch && has_key(a:spec, 'commit')
+ let sha = s:git_revision(a:spec.dir)
+ if empty(sha)
+ let err = join(add(result, 'PlugClean required.'), "\n")
+ elseif !s:hash_match(sha, a:spec.commit)
+ let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
+ \ a:spec.commit[:6], sha[:6]),
+ \ 'PlugUpdate required.'], "\n")
+ endif
+ elseif a:check_branch
+ let current_branch = result[0]
+ " Check tag
+ let origin_branch = s:git_origin_branch(a:spec)
+ if has_key(a:spec, 'tag')
+ let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
+ if a:spec.tag !=# tag && a:spec.tag !~ '\*'
+ let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
+ \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
+ endif
+ " Check branch
+ elseif origin_branch !=# current_branch
+ let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
+ \ current_branch, origin_branch)
+ endif
+ if empty(err)
+ let ahead_behind = split(s:lastline(s:system([
+ \ 'git', 'rev-list', '--count', '--left-right',
+ \ printf('HEAD...origin/%s', origin_branch)
+ \ ], a:spec.dir)), '\t')
+ if v:shell_error || len(ahead_behind) != 2
+ let err = "Failed to compare with the origin. The default branch might have changed.\nPlugClean required."
+ else
+ let [ahead, behind] = ahead_behind
+ if ahead && behind
+ " Only mention PlugClean if diverged, otherwise it's likely to be
+ " pushable (and probably not that messed up).
+ let err = printf(
+ \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"
+ \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind)
+ elseif ahead
+ let err = printf("Ahead of origin/%s by %d commit(s).\n"
+ \ .'Cannot update until local changes are pushed.',
+ \ origin_branch, ahead)
+ endif
+ endif
+ endif
+ endif
+ else
+ let err = 'Not found'
+ endif
+ return [err, err =~# 'PlugClean']
+endfunction
+
+function! s:rm_rf(dir)
+ if isdirectory(a:dir)
+ return s:system(s:is_win
+ \ ? 'rmdir /S /Q '.plug#shellescape(a:dir)
+ \ : ['rm', '-rf', a:dir])
+ endif
+endfunction
+
+function! s:clean(force)
+ call s:prepare()
+ call append(0, 'Searching for invalid plugins in '.g:plug_home)
+ call append(1, '')
+
+ " List of valid directories
+ let dirs = []
+ let errs = {}
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ if !s:is_managed(name) || get(spec, 'frozen', 0)
+ call add(dirs, spec.dir)
+ else
+ let [err, clean] = s:git_validate(spec, 1)
+ if clean
+ let errs[spec.dir] = s:lines(err)[0]
+ else
+ call add(dirs, spec.dir)
+ endif
+ endif
+ let cnt += 1
+ call s:progress_bar(2, repeat('=', cnt), total)
+ normal! 2G
+ redraw
+ endfor
+
+ let allowed = {}
+ for dir in dirs
+ let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1
+ let allowed[dir] = 1
+ for child in s:glob_dir(dir)
+ let allowed[child] = 1
+ endfor
+ endfor
+
+ let todo = []
+ let found = sort(s:glob_dir(g:plug_home))
+ while !empty(found)
+ let f = remove(found, 0)
+ if !has_key(allowed, f) && isdirectory(f)
+ call add(todo, f)
+ call append(line('$'), '- ' . f)
+ if has_key(errs, f)
+ call append(line('$'), ' ' . errs[f])
+ endif
+ let found = filter(found, 'stridx(v:val, f) != 0')
+ end
+ endwhile
+
+ 4
+ redraw
+ if empty(todo)
+ call append(line('$'), 'Already clean.')
+ else
+ let s:clean_count = 0
+ call append(3, ['Directories to delete:', ''])
+ redraw!
+ if a:force || s:ask_no_interrupt('Delete all directories?')
+ call s:delete([6, line('$')], 1)
+ else
+ call setline(4, 'Cancelled.')
+ nnoremap <silent> <buffer> d :set opfunc=<sid>delete_op<cr>g@
+ nmap <silent> <buffer> dd d_
+ xnoremap <silent> <buffer> d :<c-u>call <sid>delete_op(visualmode(), 1)<cr>
+ echo 'Delete the lines (d{motion}) to delete the corresponding directories'
+ endif
+ endif
+ 4
+ setlocal nomodifiable
+endfunction
+
+function! s:delete_op(type, ...)
+ call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0)
+endfunction
+
+function! s:delete(range, force)
+ let [l1, l2] = a:range
+ let force = a:force
+ let err_count = 0
+ while l1 <= l2
+ let line = getline(l1)
+ if line =~ '^- ' && isdirectory(line[2:])
+ execute l1
+ redraw!
+ let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1)
+ let force = force || answer > 1
+ if answer
+ let err = s:rm_rf(line[2:])
+ setlocal modifiable
+ if empty(err)
+ call setline(l1, '~'.line[1:])
+ let s:clean_count += 1
+ else
+ delete _
+ call append(l1 - 1, s:format_message('x', line[1:], err))
+ let l2 += len(s:lines(err))
+ let err_count += 1
+ endif
+ let msg = printf('Removed %d directories.', s:clean_count)
+ if err_count > 0
+ let msg .= printf(' Failed to remove %d directories.', err_count)
+ endif
+ call setline(4, msg)
+ setlocal nomodifiable
+ endif
+ endif
+ let l1 += 1
+ endwhile
+endfunction
+
+function! s:upgrade()
+ echo 'Downloading the latest version of vim-plug'
+ redraw
+ let tmp = s:plug_tempname()
+ let new = tmp . '/plug.vim'
+
+ try
+ let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])
+ if v:shell_error
+ return s:err('Error upgrading vim-plug: '. out)
+ endif
+
+ if readfile(s:me) ==# readfile(new)
+ echo 'vim-plug is already up-to-date'
+ return 0
+ else
+ call rename(s:me, s:me . '.old')
+ call rename(new, s:me)
+ unlet g:loaded_plug
+ echo 'vim-plug has been upgraded'
+ return 1
+ endif
+ finally
+ silent! call s:rm_rf(tmp)
+ endtry
+endfunction
+
+function! s:upgrade_specs()
+ for spec in values(g:plugs)
+ let spec.frozen = get(spec, 'frozen', 0)
+ endfor
+endfunction
+
+function! s:status()
+ call s:prepare()
+ call append(0, 'Checking plugins')
+ call append(1, '')
+
+ let ecnt = 0
+ let unloaded = 0
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ let is_dir = isdirectory(spec.dir)
+ if has_key(spec, 'uri')
+ if is_dir
+ let [err, _] = s:git_validate(spec, 1)
+ let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
+ else
+ let [valid, msg] = [0, 'Not found. Try PlugInstall.']
+ endif
+ else
+ if is_dir
+ let [valid, msg] = [1, 'OK']
+ else
+ let [valid, msg] = [0, 'Not found.']
+ endif
+ endif
+ let cnt += 1
+ let ecnt += !valid
+ " `s:loaded` entry can be missing if PlugUpgraded
+ if is_dir && get(s:loaded, name, -1) == 0
+ let unloaded = 1
+ let msg .= ' (not loaded)'
+ endif
+ call s:progress_bar(2, repeat('=', cnt), total)
+ call append(3, s:format_message(valid ? '-' : 'x', name, msg))
+ normal! 2G
+ redraw
+ endfor
+ call setline(1, 'Finished. '.ecnt.' error(s).')
+ normal! gg
+ setlocal nomodifiable
+ if unloaded
+ echo "Press 'L' on each line to load plugin, or 'U' to update"
+ nnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ xnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ end
+endfunction
+
+function! s:extract_name(str, prefix, suffix)
+ return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$')
+endfunction
+
+function! s:status_load(lnum)
+ let line = getline(a:lnum)
+ let name = s:extract_name(line, '-', '(not loaded)')
+ if !empty(name)
+ call plug#load(name)
+ setlocal modifiable
+ call setline(a:lnum, substitute(line, ' (not loaded)$', '', ''))
+ setlocal nomodifiable
+ endif
+endfunction
+
+function! s:status_update() range
+ let lines = getline(a:firstline, a:lastline)
+ let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)')
+ if !empty(names)
+ echo
+ execute 'PlugUpdate' join(names)
+ endif
+endfunction
+
+function! s:is_preview_window_open()
+ silent! wincmd P
+ if &previewwindow
+ wincmd p
+ return 1
+ endif
+endfunction
+
+function! s:find_name(lnum)
+ for lnum in reverse(range(1, a:lnum))
+ let line = getline(lnum)
+ if empty(line)
+ return ''
+ endif
+ let name = s:extract_name(line, '-', '')
+ if !empty(name)
+ return name
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:preview_commit()
+ if b:plug_preview < 0
+ let b:plug_preview = !s:is_preview_window_open()
+ endif
+
+ let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}')
+ if empty(sha)
+ let name = matchstr(getline('.'), '^- \zs[^:]*\ze:$')
+ if empty(name)
+ return
+ endif
+ let title = 'HEAD@{1}..'
+ let command = 'git diff --no-color HEAD@{1}'
+ else
+ let title = sha
+ let command = 'git show --no-color --pretty=medium '.sha
+ let name = s:find_name(line('.'))
+ endif
+
+ if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir)
+ return
+ endif
+
+ if !s:is_preview_window_open()
+ execute get(g:, 'plug_pwindow', 'vertical rightbelow new')
+ execute 'e' title
+ else
+ execute 'pedit' title
+ wincmd P
+ endif
+ setlocal previewwindow filetype=git buftype=nofile bufhidden=wipe nobuflisted modifiable
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && '.command
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ execute 'silent %!' cmd
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ setlocal nomodifiable
+ nnoremap <silent> <buffer> q :q<cr>
+ wincmd p
+endfunction
+
+function! s:section(flags)
+ call search('\(^[x-] \)\@<=[^:]\+:', a:flags)
+endfunction
+
+function! s:format_git_log(line)
+ let indent = ' '
+ let tokens = split(a:line, nr2char(1))
+ if len(tokens) != 5
+ return indent.substitute(a:line, '\s*$', '', '')
+ endif
+ let [graph, sha, refs, subject, date] = tokens
+ let tag = matchstr(refs, 'tag: [^,)]\+')
+ let tag = empty(tag) ? ' ' : ' ('.tag.') '
+ return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date)
+endfunction
+
+function! s:append_ul(lnum, text)
+ call append(a:lnum, ['', a:text, repeat('-', len(a:text))])
+endfunction
+
+function! s:diff()
+ call s:prepare()
+ call append(0, ['Collecting changes ...', ''])
+ let cnts = [0, 0]
+ let bar = ''
+ let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)')
+ call s:progress_bar(2, bar, len(total))
+ for origin in [1, 0]
+ let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))'))))
+ if empty(plugs)
+ continue
+ endif
+ call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
+ for [k, v] in plugs
+ let branch = s:git_origin_branch(v)
+ if len(branch)
+ let range = origin ? '..origin/'.branch : 'HEAD@{1}..'
+ let cmd = ['git', 'log', '--graph', '--color=never']
+ if s:git_version_requirement(2, 10, 0)
+ call add(cmd, '--no-show-signature')
+ endif
+ call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
+ if has_key(v, 'rtp')
+ call extend(cmd, ['--', v.rtp])
+ endif
+ let diff = s:system_chomp(cmd, v.dir)
+ if !empty(diff)
+ let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
+ call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
+ let cnts[origin] += 1
+ endif
+ endif
+ let bar .= '='
+ call s:progress_bar(2, bar, len(total))
+ normal! 2G
+ redraw
+ endfor
+ if !cnts[origin]
+ call append(5, ['', 'N/A'])
+ endif
+ endfor
+ call setline(1, printf('%d plugin(s) updated.', cnts[0])
+ \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : ''))
+
+ if cnts[0] || cnts[1]
+ nnoremap <silent> <buffer> <plug>(plug-preview) :silent! call <SID>preview_commit()<cr>
+ if empty(maparg("\<cr>", 'n'))
+ nmap <buffer> <cr> <plug>(plug-preview)
+ endif
+ if empty(maparg('o', 'n'))
+ nmap <buffer> o <plug>(plug-preview)
+ endif
+ endif
+ if cnts[0]
+ nnoremap <silent> <buffer> X :call <SID>revert()<cr>
+ echo "Press 'X' on each block to revert the update"
+ endif
+ normal! gg
+ setlocal nomodifiable
+endfunction
+
+function! s:revert()
+ if search('^Pending updates', 'bnW')
+ return
+ endif
+
+ let name = s:find_name(line('.'))
+ if empty(name) || !has_key(g:plugs, name) ||
+ \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'
+ return
+ endif
+
+ call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir)
+ setlocal modifiable
+ normal! "_dap
+ setlocal nomodifiable
+ echo 'Reverted'
+endfunction
+
+function! s:snapshot(force, ...) abort
+ call s:prepare()
+ setf vim
+ call append(0, ['" Generated by vim-plug',
+ \ '" '.strftime("%c"),
+ \ '" :source this file in vim to restore the snapshot',
+ \ '" or execute: vim -S snapshot.vim',
+ \ '', '', 'PlugUpdate!'])
+ 1
+ let anchor = line('$') - 3
+ let names = sort(keys(filter(copy(g:plugs),
+ \'has_key(v:val, "uri") && isdirectory(v:val.dir)')))
+ for name in reverse(names)
+ let sha = has_key(g:plugs[name], 'commit') ? g:plugs[name].commit : s:git_revision(g:plugs[name].dir)
+ if !empty(sha)
+ call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
+ redraw
+ endif
+ endfor
+
+ if a:0 > 0
+ let fn = s:plug_expand(a:1)
+ if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?'))
+ return
+ endif
+ call writefile(getline(1, '$'), fn)
+ echo 'Saved as '.a:1
+ silent execute 'e' s:esc(fn)
+ setf vim
+ endif
+endfunction
+
+function! s:split_rtp()
+ return split(&rtp, '\\\@<!,')
+endfunction
+
+let s:first_rtp = s:escrtp(get(s:split_rtp(), 0, ''))
+let s:last_rtp = s:escrtp(get(s:split_rtp(), -1, ''))
+
+if exists('g:plugs')
+ let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs))
+ call s:upgrade_specs()
+ call s:define_commands()
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/.config/nvim/autoload/scratch.vim b/.config/nvim/autoload/scratch.vim
new file mode 100644
index 0000000..0a06cdc
--- /dev/null
+++ b/.config/nvim/autoload/scratch.vim
@@ -0,0 +1,49 @@
+" Source: https://gist.github.com/romainl/eae0a260ab9c135390c30cd370c20cd7
+function! scratch#open(cmd, mods) abort
+ for win in filter(range(1, winnr('$')), 'getwinvar(v:val, "scratch")')
+ execute win . 'windo close'
+ endfor
+ if a:cmd =~# '^!'
+ let cmd = a:cmd =~# ' %' ? substitute(a:cmd, ' %', ' ' . expand('%:p'), '') : a:cmd
+ let output = systemlist(matchstr(cmd, '^!\zs.*'))
+ elseif a:cmd =~# '^@'
+ let output = getreg(a:cmd[1], 1, 1)
+ else
+ let output = split(execute(a:cmd), "\n")
+ endif
+ execute a:mods . ' new'
+ let w:scratch = 1
+ call setline(1, output)
+ nnoremap <buffer> q <C-W>q
+ setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable
+ call s:highlight(a:cmd)
+
+ augroup scratch
+ autocmd BufEnter <buffer> ++nested if winnr('$') < 2 | q | endif
+ augroup END
+endfunction
+
+" Highlight scratch buffer to match native command output for certain commands
+function! s:highlight(cmd) abort
+ let firstline = getline(1)
+ if firstline =~# '^--- Registers ---\|Type Name Content$'
+ call matchaddpos('Title', [1])
+ call matchadd('SpecialKey', '\^\S\|<[^>]\{2}>')
+ elseif firstline =~# '^\%(mark\|change\| jump\) line col \%(file/\)\?text$'
+ call matchaddpos('Title', [1])
+ elseif firstline =~# '^\w\+\s\+xxx \%(links\|cleared\|cterm\|gui\|term\)'
+ syntax match Keyword /\v%(c?term%([fb]g)?|gui%([fb]g)?)\=/
+ syntax keyword Keyword links to
+ for linenr in range(1, line('$'))
+ let line = getline(linenr)
+ let syn = matchstr(line, '^\w\+')
+ let col = match(line, '\<xxx\>')
+ call matchaddpos(syn, [[linenr, col + 1, 3]])
+ endfor
+ elseif search('\v^(E[0-9]+:|line\s+[0-9]+:)', 'cnW')
+ call matchadd('ErrorMsg', '^E[0-9]\+: .\+$')
+ call matchadd('LineNr', '^line\s\+[0-9]\+:$')
+ elseif a:cmd =~# '^dig'
+ call matchadd('SpecialKey', '[A-Za-z0-9[:graph:]]\{2}\s\+\zs\S\+\ze\s\+\d\+')
+ endif
+endfunction
diff --git a/.config/nvim/coc/coc-onload.vim b/.config/nvim/coc/coc-onload.vim
new file mode 100644
index 0000000..c2835cc
--- /dev/null
+++ b/.config/nvim/coc/coc-onload.vim
@@ -0,0 +1,144 @@
+
+" May need for Vim (not Neovim) since coc.nvim calculates byte offset by count
+" utf-8 byte sequence
+set encoding=utf-8
+" Some servers have issues with backup files, see #649
+set nobackup
+set nowritebackup
+
+" Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
+" delays and poor user experience
+set updatetime=1000
+
+" Always show the signcolumn, otherwise it would shift the text each time
+" diagnostics appear/become resolved
+set signcolumn=yes
+
+" Use tab for trigger completion with characters ahead and navigate
+" NOTE: There's always complete item selected by default, you may want to enable
+" no select by `"suggest.noselect": true` in your configuration file
+" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
+" other plugin before putting this into your config
+ inoremap <silent><expr> <TAB>
+ \ coc#pum#visible() ? coc#pum#next(1) :
+ \ CheckBackspace() ? "\<Tab>" :
+ \ coc#refresh()
+ inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
+
+" Make <CR> to accept selected completion item or notify coc.nvim to format
+" <C-g>u breaks current undo, please make your own choice
+inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
+ \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
+
+function! CheckBackspace() abort
+ let col = col('.') - 1
+ return !col || getline('.')[col - 1] =~# '\s'
+endfunction
+
+" Use <c-space> to trigger completion
+if has('nvim')
+ inoremap <silent><expr> <c-space> coc#refresh()
+else
+ inoremap <silent><expr> <c-@> coc#refresh()
+endif
+
+" Use `[g` and `]g` to navigate diagnostics
+" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
+nmap <silent> [g <Plug>(coc-diagnostic-prev)
+nmap <silent> ]g <Plug>(coc-diagnostic-next)
+
+" GoTo code navigation
+nmap <silent> gd <Plug>(coc-definition)
+nmap <silent> gy <Plug>(coc-type-definition)
+nmap <silent> gi <Plug>(coc-implementation)
+nmap <silent> gr <Plug>(coc-references)
+
+" Use K to show documentation in preview window
+nnoremap <silent> <C-k> :call ShowDocumentation()<CR>
+
+function! ShowDocumentation()
+ if CocAction('hasProvider', 'hover')
+ call CocActionAsync('doHover')
+ else
+ call feedkeys('K', 'in')
+ endif
+endfunction
+
+" Highlight the symbol and its references when holding the cursor
+autocmd CursorHold * silent call CocActionAsync('highlight')
+
+" Symbol renaming
+nmap <leader>rn <Plug>(coc-rename)
+
+" Formatting selected code
+xmap <leader>cf <Plug>(coc-format-selected)
+nmap <leader>cf <Plug>(coc-format-selected)
+
+augroup mygroup
+ autocmd!
+ " Setup formatexpr specified filetype(s)
+ autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
+ " Update signature help on jump placeholder
+ autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
+augroup end
+
+" Applying code actions to the selected code block
+" Example: `<leader>aap` for current paragraph
+xmap <leader>aa <Plug>(coc-codeaction-selected)
+nmap <leader>aa <Plug>(coc-codeaction-selected)
+
+" Remap keys for applying code actions at the cursor position
+nmap <leader>ac <Plug>(coc-codeaction-cursor)
+" Remap keys for apply code actions affect whole buffer
+nmap <leader>as <Plug>(coc-codeaction-source)
+" Apply the most preferred quickfix action to fix diagnostic on the current line
+nmap <leader>aq <Plug>(coc-fix-current)
+
+" Remap keys for applying refactor code actions
+nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
+xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
+nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
+
+" Run the Code Lens action on the current line
+nmap <leader>cl <Plug>(coc-codelens-action)
+
+" Map function and class text objects
+" NOTE: Requires 'textDocument.documentSymbol' support from the language server
+xmap if <Plug>(coc-funcobj-i)
+omap if <Plug>(coc-funcobj-i)
+xmap af <Plug>(coc-funcobj-a)
+omap af <Plug>(coc-funcobj-a)
+xmap ic <Plug>(coc-classobj-i)
+omap ic <Plug>(coc-classobj-i)
+xmap ac <Plug>(coc-classobj-a)
+omap ac <Plug>(coc-classobj-a)
+
+" Remap <C-f> and <C-b> to scroll float windows/popups
+if has('nvim-0.4.0') || has('patch-8.2.0750')
+ nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
+ nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
+ inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
+ inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
+ vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
+ vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
+endif
+
+" Use CTRL-S for selections ranges
+" Requires 'textDocument/selectionRange' support of language server
+nmap <silent> <C-s> <Plug>(coc-range-select)
+xmap <silent> <C-s> <Plug>(coc-range-select)
+
+" Add `:Format` command to format current buffer
+command! -nargs=0 Format :call CocActionAsync('format')
+
+" Add `:Fold` command to fold current buffer
+command! -nargs=? Fold :call CocAction('fold', <f-args>)
+
+" Add `:OR` command for organize imports of the current buffer
+command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
+
+" Add (Neo)Vim's native statusline support
+" NOTE: Please see `:h coc-status` for integrations with external plugins that
+" provide custom statusline: lightline.vim, vim-airline
+set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
+
diff --git a/.config/nvim/coc/coc-settings.json b/.config/nvim/coc/coc-settings.json
new file mode 100644
index 0000000..f90bc38
--- /dev/null
+++ b/.config/nvim/coc/coc-settings.json
@@ -0,0 +1,6 @@
+{
+ "suggest.autoTrigger": "always",
+ "diagnostic.enable": true,
+ "python.linting.pycodestyleEnabled": true,
+ "html.autoCreateQuotes": false
+}
diff --git a/.config/nvim/colors/onedark.vim b/.config/nvim/colors/onedark.vim
new file mode 100644
index 0000000..6769d6c
--- /dev/null
+++ b/.config/nvim/colors/onedark.vim
@@ -0,0 +1,713 @@
+" vim:fdm=marker
+" Vim Color File
+" Name: onedark.vim
+" Maintainer: https://github.com/joshdick/onedark.vim/
+" License: The MIT License (MIT)
+" Based On: https://github.com/MaxSt/FlatColor/
+
+" Companion statusline plugin and terminal themes are included with onedark.vim:
+" * https://github.com/joshdick/onedark.vim#lightlinevim-colorscheme
+" * https://github.com/joshdick/onedark.vim#vim-airline-theme
+" * https://github.com/joshdick/onedark.vim/tree/main/term
+
+" Color Reference {{{
+
+" The following colors were measured inside Atom using its built-in inspector.
+
+" +---------------------------------------------+
+" | Color Name | RGB | Hex |
+" |--------------+--------------------+---------|
+" | Black | rgb(40, 44, 52) | #282c34 |
+" |--------------+--------------------+---------|
+" | White | rgb(171, 178, 191) | #abb2bf |
+" |--------------+--------------------+---------|
+" | Light Red | rgb(224, 108, 117) | #e06c75 |
+" |--------------+--------------------+---------|
+" | Dark Red | rgb(190, 80, 70) | #be5046 |
+" |--------------+--------------------+---------|
+" | Green | rgb(152, 195, 121) | #98c379 |
+" |--------------+--------------------+---------|
+" | Light Yellow | rgb(229, 192, 123) | #e5c07b |
+" |--------------+--------------------+---------|
+" | Dark Yellow | rgb(209, 154, 102) | #d19a66 |
+" |--------------+--------------------+---------|
+" | Blue | rgb(97, 175, 239) | #61afef |
+" |--------------+--------------------+---------|
+" | Magenta | rgb(198, 120, 221) | #c678dd |
+" |--------------+--------------------+---------|
+" | Cyan | rgb(86, 182, 194) | #56b6c2 |
+" |--------------+--------------------+---------|
+" | Gutter Grey | rgb(76, 82, 99) | #4b5263 |
+" |--------------+--------------------+---------|
+" | Comment Grey | rgb(92, 99, 112) | #5c6370 |
+" +---------------------------------------------+
+
+" }}}
+
+" Initialization {{{
+
+highlight clear
+
+if exists("syntax_on")
+ syntax reset
+endif
+
+set t_Co=256
+
+let g:colors_name="onedark"
+
+" Set to "256" for 256-color terminals, or
+" set to "16" to use your terminal emulator's native colors
+" (a 16-color palette for this color scheme is available; see
+" < https://github.com/joshdick/onedark.vim/blob/main/README.md >
+" for more information.)
+if !exists("g:onedark_termcolors")
+ let g:onedark_termcolors = 256
+endif
+
+" Not all terminals support italics properly. If yours does, opt-in.
+if !exists("g:onedark_terminal_italics")
+ let g:onedark_terminal_italics = 0
+endif
+
+" This function is based on one from FlatColor: https://github.com/MaxSt/FlatColor/
+" Which in turn was based on one found in hemisu: https://github.com/noahfrederick/vim-hemisu/
+let s:group_colors = {} " Cache of default highlight group settings, for later reference via `onedark#extend_highlight`
+function! s:h(group, style, ...)
+ if (a:0 > 0) " Will be true if we got here from onedark#extend_highlight
+ let s:highlight = s:group_colors[a:group]
+ for style_type in ["fg", "bg", "sp"]
+ if (has_key(a:style, style_type))
+ let l:default_style = (has_key(s:highlight, style_type) ? copy(s:highlight[style_type]) : { "cterm16": "NONE", "cterm": "NONE", "gui": "NONE" })
+ let s:highlight[style_type] = extend(l:default_style, a:style[style_type])
+ endif
+ endfor
+ if (has_key(a:style, "gui"))
+ let s:highlight.gui = a:style.gui
+ endif
+ if (has_key(a:style, "cterm"))
+ let s:highlight.cterm = a:style.cterm
+ endif
+ else
+ let s:highlight = a:style
+ let s:group_colors[a:group] = s:highlight " Cache default highlight group settings
+ endif
+
+ if g:onedark_terminal_italics == 0
+ if has_key(s:highlight, "cterm") && s:highlight["cterm"] == "italic"
+ unlet s:highlight.cterm
+ endif
+ if has_key(s:highlight, "gui") && s:highlight["gui"] == "italic"
+ unlet s:highlight.gui
+ endif
+ endif
+
+ if g:onedark_termcolors == 16
+ let l:ctermfg = (has_key(s:highlight, "fg") ? s:highlight.fg.cterm16 : "NONE")
+ let l:ctermbg = (has_key(s:highlight, "bg") ? s:highlight.bg.cterm16 : "NONE")
+ else
+ let l:ctermfg = (has_key(s:highlight, "fg") ? s:highlight.fg.cterm : "NONE")
+ let l:ctermbg = (has_key(s:highlight, "bg") ? s:highlight.bg.cterm : "NONE")
+ endif
+
+ execute "highlight" a:group
+ \ "guifg=" (has_key(s:highlight, "fg") ? s:highlight.fg.gui : "NONE")
+ \ "guibg=" (has_key(s:highlight, "bg") ? s:highlight.bg.gui : "NONE")
+ \ "guisp=" (has_key(s:highlight, "sp") ? s:highlight.sp.gui : "NONE")
+ \ "gui=" (has_key(s:highlight, "gui") ? s:highlight.gui : "NONE")
+ \ "ctermfg=" . l:ctermfg
+ \ "ctermbg=" . l:ctermbg
+ \ "cterm=" (has_key(s:highlight, "cterm") ? s:highlight.cterm : "NONE")
+endfunction
+
+" public {{{
+
+function! onedark#set_highlight(group, style)
+ call s:h(a:group, a:style)
+endfunction
+
+function! onedark#extend_highlight(group, style)
+ call s:h(a:group, a:style, 1)
+endfunction
+
+" }}}
+
+" }}}
+
+" Color Variables {{{
+
+let s:colors = onedark#GetColors()
+
+let s:red = s:colors.red
+let s:dark_red = s:colors.dark_red
+let s:green = s:colors.green
+let s:yellow = s:colors.yellow
+let s:dark_yellow = s:colors.dark_yellow
+let s:blue = s:colors.blue
+let s:purple = s:colors.purple
+let s:cyan = s:colors.cyan
+let s:white = s:colors.white
+let s:black = s:colors.black
+let s:foreground = s:colors.foreground
+let s:background = s:colors.background
+let s:comment_grey = s:colors.comment_grey
+let s:gutter_fg_grey = s:colors.gutter_fg_grey
+let s:cursor_grey = s:colors.cursor_grey
+let s:visual_grey = s:colors.visual_grey
+let s:menu_grey = s:colors.menu_grey
+let s:special_grey = s:colors.special_grey
+let s:vertsplit = s:colors.vertsplit
+
+" }}}
+
+" Terminal Colors {{{
+
+if has('nvim')
+ let g:terminal_color_0 = s:black.gui
+ let g:terminal_color_1 = s:red.gui
+ let g:terminal_color_2 = s:green.gui
+ let g:terminal_color_3 = s:yellow.gui
+ let g:terminal_color_4 = s:blue.gui
+ let g:terminal_color_5 = s:purple.gui
+ let g:terminal_color_6 = s:cyan.gui
+ let g:terminal_color_7 = s:comment_grey.gui
+ let g:terminal_color_8 = s:visual_grey.gui
+ let g:terminal_color_9 = s:red.gui
+ let g:terminal_color_10 = s:green.gui
+ let g:terminal_color_11 = s:yellow.gui
+ let g:terminal_color_12 = s:blue.gui
+ let g:terminal_color_13 = s:purple.gui
+ let g:terminal_color_14 = s:cyan.gui
+ let g:terminal_color_15 = s:white.gui
+else
+ let g:terminal_ansi_colors = [
+ \ s:black.gui, s:red.gui, s:green.gui, s:yellow.gui,
+ \ s:blue.gui, s:purple.gui, s:cyan.gui, s:comment_grey.gui,
+ \ s:visual_grey.gui, s:red.gui, s:green.gui, s:yellow.gui,
+ \ s:blue.gui, s:purple.gui, s:cyan.gui, s:white.gui
+ \]
+endif
+
+" }}}
+
+" Syntax Groups (descriptions and ordering from `:h w18`) {{{
+
+call s:h("Comment", { "fg": s:comment_grey, "gui": "italic", "cterm": "italic" }) " any comment
+call s:h("Constant", { "fg": s:cyan }) " any constant
+call s:h("String", { "fg": s:green }) " a string constant: "this is a string"
+call s:h("Character", { "fg": s:green }) " a character constant: 'c', '\n'
+call s:h("Number", { "fg": s:dark_yellow }) " a number constant: 234, 0xff
+call s:h("Boolean", { "fg": s:dark_yellow }) " a boolean constant: TRUE, false
+call s:h("Float", { "fg": s:dark_yellow }) " a floating point constant: 2.3e10
+call s:h("Identifier", { "fg": s:red }) " any variable name
+call s:h("Function", { "fg": s:blue }) " function name (also: methods for classes)
+call s:h("Statement", { "fg": s:purple }) " any statement
+call s:h("Conditional", { "fg": s:purple }) " if, then, else, endif, switch, etc.
+call s:h("Repeat", { "fg": s:purple }) " for, do, while, etc.
+call s:h("Label", { "fg": s:purple }) " case, default, etc.
+call s:h("Operator", { "fg": s:purple }) " sizeof", "+", "*", etc.
+call s:h("Keyword", { "fg": s:purple }) " any other keyword
+call s:h("Exception", { "fg": s:purple }) " try, catch, throw
+call s:h("PreProc", { "fg": s:yellow }) " generic Preprocessor
+call s:h("Include", { "fg": s:blue }) " preprocessor #include
+call s:h("Define", { "fg": s:purple }) " preprocessor #define
+call s:h("Macro", { "fg": s:purple }) " same as Define
+call s:h("PreCondit", { "fg": s:yellow }) " preprocessor #if, #else, #endif, etc.
+call s:h("Type", { "fg": s:yellow }) " int, long, char, etc.
+call s:h("StorageClass", { "fg": s:yellow }) " static, register, volatile, etc.
+call s:h("Structure", { "fg": s:yellow }) " struct, union, enum, etc.
+call s:h("Typedef", { "fg": s:yellow }) " A typedef
+call s:h("Special", { "fg": s:blue }) " any special symbol
+call s:h("SpecialChar", { "fg": s:dark_yellow }) " special character in a constant
+call s:h("Tag", {}) " you can use CTRL-] on this
+call s:h("Delimiter", {}) " character that needs attention
+call s:h("SpecialComment", { "fg": s:comment_grey }) " special things inside a comment
+call s:h("Debug", {}) " debugging statements
+call s:h("Underlined", { "gui": "underline", "cterm": "underline" }) " text that stands out, HTML links
+call s:h("Ignore", {}) " left blank, hidden
+call s:h("Error", { "fg": s:red }) " any erroneous construct
+call s:h("Todo", { "fg": s:purple }) " anything that needs extra attention; mostly the keywords TODO FIXME and XXX
+
+" }}}
+
+" Highlighting Groups (descriptions and ordering from `:h highlight-groups`) {{{
+call s:h("ColorColumn", { "bg": s:cursor_grey }) " used for the columns set with 'colorcolumn'
+call s:h("Conceal", {}) " placeholder characters substituted for concealed text (see 'conceallevel')
+call s:h("Cursor", { "fg": s:black, "bg": s:blue }) " the character under the cursor
+call s:h("CursorIM", {}) " like Cursor, but used when in IME mode
+call s:h("CursorColumn", { "bg": s:cursor_grey }) " the screen column that the cursor is in when 'cursorcolumn' is set
+if &diff
+ " Don't change the background color in diff mode
+ call s:h("CursorLine", { "gui": "underline" }) " the screen line that the cursor is in when 'cursorline' is set
+else
+ call s:h("CursorLine", { "bg": s:cursor_grey }) " the screen line that the cursor is in when 'cursorline' is set
+endif
+call s:h("Directory", { "fg": s:blue }) " directory names (and other special names in listings)
+call s:h("DiffAdd", { "bg": s:green, "fg": s:black }) " diff mode: Added line
+call s:h("DiffChange", { "fg": s:yellow, "gui": "underline", "cterm": "underline" }) " diff mode: Changed line
+call s:h("DiffDelete", { "bg": s:red, "fg": s:black }) " diff mode: Deleted line
+call s:h("DiffText", { "bg": s:yellow, "fg": s:black }) " diff mode: Changed text within a changed line
+if get(g:, 'onedark_hide_endofbuffer', 0)
+ " If enabled, will style end-of-buffer filler lines (~) to appear to be hidden.
+ call s:h("EndOfBuffer", { "fg": s:black }) " filler lines (~) after the last line in the buffer
+endif
+call s:h("ErrorMsg", { "fg": s:red }) " error messages on the command line
+call s:h("VertSplit", { "fg": s:vertsplit }) " the column separating vertically split windows
+call s:h("Folded", { "fg": s:comment_grey }) " line used for closed folds
+call s:h("FoldColumn", {}) " 'foldcolumn'
+call s:h("SignColumn", {}) " column where signs are displayed
+call s:h("IncSearch", { "fg": s:yellow, "bg": s:comment_grey }) " 'incsearch' highlighting; also used for the text replaced with ":s///c"
+call s:h("LineNr", { "fg": s:gutter_fg_grey }) " Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set.
+call s:h("CursorLineNr", {}) " Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line.
+call s:h("MatchParen", { "fg": s:blue, "gui": "underline", "cterm": "underline" }) " The character under the cursor or just before it, if it is a paired bracket, and its match.
+call s:h("ModeMsg", {}) " 'showmode' message (e.g., "-- INSERT --")
+call s:h("MoreMsg", {}) " more-prompt
+call s:h("NonText", { "fg": s:special_grey }) " '~' and '@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., ">" displayed when a double-wide character doesn't fit at the end of the line).
+call s:h("Normal", { "fg": s:foreground, "bg": s:background }) " normal text
+call s:h("Pmenu", { "fg": s:white, "bg": s:menu_grey }) " Popup menu: normal item.
+call s:h("PmenuSel", { "fg": s:cursor_grey, "bg": s:blue }) " Popup menu: selected item.
+call s:h("PmenuSbar", { "bg": s:cursor_grey }) " Popup menu: scrollbar.
+call s:h("PmenuThumb", { "bg": s:white }) " Popup menu: Thumb of the scrollbar.
+call s:h("Question", { "fg": s:purple }) " hit-enter prompt and yes/no questions
+call s:h("QuickFixLine", { "fg": s:black, "bg": s:yellow }) " Current quickfix item in the quickfix window.
+call s:h("Search", { "fg": s:black, "bg": s:yellow }) " Last search pattern highlighting (see 'hlsearch'). Also used for similar items that need to stand out.
+call s:h("SpecialKey", { "fg": s:special_grey }) " Meta and special keys listed with ":map", also for text used to show unprintable characters in the text, 'listchars'. Generally: text that is displayed differently from what it really is.
+call s:h("SpellBad", { "fg": s:red, "gui": "underline", "cterm": "underline" }) " Word that is not recognized by the spellchecker. This will be combined with the highlighting used otherwise.
+call s:h("SpellCap", { "fg": s:dark_yellow }) " Word that should start with a capital. This will be combined with the highlighting used otherwise.
+call s:h("SpellLocal", { "fg": s:dark_yellow }) " Word that is recognized by the spellchecker as one that is used in another region. This will be combined with the highlighting used otherwise.
+call s:h("SpellRare", { "fg": s:dark_yellow }) " Word that is recognized by the spellchecker as one that is hardly ever used. spell This will be combined with the highlighting used otherwise.
+call s:h("StatusLine", { "fg": s:white, "bg": s:cursor_grey }) " status line of current window
+call s:h("StatusLineNC", { "fg": s:comment_grey }) " status lines of not-current windows Note: if this is equal to "StatusLine" Vim will use "^^^" in the status line of the current window.
+call s:h("StatusLineTerm", { "fg": s:white, "bg": s:cursor_grey }) " status line of current :terminal window
+call s:h("StatusLineTermNC", { "fg": s:comment_grey }) " status line of non-current :terminal window
+call s:h("TabLine", { "fg": s:comment_grey }) " tab pages line, not active tab page label
+call s:h("TabLineFill", {}) " tab pages line, where there are no labels
+call s:h("TabLineSel", { "fg": s:white }) " tab pages line, active tab page label
+call s:h("Terminal", { "fg": s:white, "bg": s:black }) " terminal window (see terminal-size-color)
+call s:h("Title", { "fg": s:green }) " titles for output from ":set all", ":autocmd" etc.
+call s:h("Visual", { "bg": s:visual_grey }) " Visual mode selection
+call s:h("VisualNOS", { "bg": s:visual_grey }) " Visual mode selection when vim is "Not Owning the Selection". Only X11 Gui's gui-x11 and xterm-clipboard supports this.
+call s:h("WarningMsg", { "fg": s:yellow }) " warning messages
+call s:h("WildMenu", { "fg": s:black, "bg": s:blue }) " current match in 'wildmenu' completion
+
+" }}}
+
+" Termdebug highlighting for Vim 8.1+ {{{
+
+" See `:h hl-debugPC` and `:h hl-debugBreakpoint`.
+call s:h("debugPC", { "bg": s:special_grey }) " the current position
+call s:h("debugBreakpoint", { "fg": s:black, "bg": s:red }) " a breakpoint
+
+" }}}
+
+" Language-Specific Highlighting {{{
+
+" CSS
+call s:h("cssAttrComma", { "fg": s:purple })
+call s:h("cssAttributeSelector", { "fg": s:green })
+call s:h("cssBraces", { "fg": s:white })
+call s:h("cssClassName", { "fg": s:dark_yellow })
+call s:h("cssClassNameDot", { "fg": s:dark_yellow })
+call s:h("cssDefinition", { "fg": s:purple })
+call s:h("cssFontAttr", { "fg": s:dark_yellow })
+call s:h("cssFontDescriptor", { "fg": s:purple })
+call s:h("cssFunctionName", { "fg": s:blue })
+call s:h("cssIdentifier", { "fg": s:blue })
+call s:h("cssImportant", { "fg": s:purple })
+call s:h("cssInclude", { "fg": s:white })
+call s:h("cssIncludeKeyword", { "fg": s:purple })
+call s:h("cssMediaType", { "fg": s:dark_yellow })
+call s:h("cssProp", { "fg": s:white })
+call s:h("cssPseudoClassId", { "fg": s:dark_yellow })
+call s:h("cssSelectorOp", { "fg": s:purple })
+call s:h("cssSelectorOp2", { "fg": s:purple })
+call s:h("cssTagName", { "fg": s:red })
+
+" Fish Shell
+call s:h("fishKeyword", { "fg": s:purple })
+call s:h("fishConditional", { "fg": s:purple })
+
+" Go
+call s:h("goDeclaration", { "fg": s:purple })
+call s:h("goBuiltins", { "fg": s:cyan })
+call s:h("goFunctionCall", { "fg": s:blue })
+call s:h("goVarDefs", { "fg": s:red })
+call s:h("goVarAssign", { "fg": s:red })
+call s:h("goVar", { "fg": s:purple })
+call s:h("goConst", { "fg": s:purple })
+call s:h("goType", { "fg": s:yellow })
+call s:h("goTypeName", { "fg": s:yellow })
+call s:h("goDeclType", { "fg": s:cyan })
+call s:h("goTypeDecl", { "fg": s:purple })
+
+" HTML (keep consistent with Markdown, below)
+call s:h("htmlArg", { "fg": s:dark_yellow })
+call s:h("htmlBold", { "fg": s:dark_yellow, "gui": "bold", "cterm": "bold" })
+call s:h("htmlBoldItalic", { "fg": s:green, "gui": "bold,italic", "cterm": "bold,italic" })
+call s:h("htmlEndTag", { "fg": s:white })
+call s:h("htmlH1", { "fg": s:red })
+call s:h("htmlH2", { "fg": s:red })
+call s:h("htmlH3", { "fg": s:red })
+call s:h("htmlH4", { "fg": s:red })
+call s:h("htmlH5", { "fg": s:red })
+call s:h("htmlH6", { "fg": s:red })
+call s:h("htmlItalic", { "fg": s:purple, "gui": "italic", "cterm": "italic" })
+call s:h("htmlLink", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+call s:h("htmlSpecialChar", { "fg": s:dark_yellow })
+call s:h("htmlSpecialTagName", { "fg": s:red })
+call s:h("htmlTag", { "fg": s:white })
+call s:h("htmlTagN", { "fg": s:red })
+call s:h("htmlTagName", { "fg": s:red })
+call s:h("htmlTitle", { "fg": s:white })
+
+" JavaScript
+call s:h("javaScriptBraces", { "fg": s:white })
+call s:h("javaScriptFunction", { "fg": s:purple })
+call s:h("javaScriptIdentifier", { "fg": s:purple })
+call s:h("javaScriptNull", { "fg": s:dark_yellow })
+call s:h("javaScriptNumber", { "fg": s:dark_yellow })
+call s:h("javaScriptRequire", { "fg": s:cyan })
+call s:h("javaScriptReserved", { "fg": s:purple })
+" https://github.com/pangloss/vim-javascript
+call s:h("jsArrowFunction", { "fg": s:purple })
+call s:h("jsClassKeyword", { "fg": s:purple })
+call s:h("jsClassMethodType", { "fg": s:purple })
+call s:h("jsDocParam", { "fg": s:blue })
+call s:h("jsDocTags", { "fg": s:purple })
+call s:h("jsExport", { "fg": s:purple })
+call s:h("jsExportDefault", { "fg": s:purple })
+call s:h("jsExtendsKeyword", { "fg": s:purple })
+call s:h("jsFrom", { "fg": s:purple })
+call s:h("jsFuncCall", { "fg": s:blue })
+call s:h("jsFunction", { "fg": s:purple })
+call s:h("jsGenerator", { "fg": s:yellow })
+call s:h("jsGlobalObjects", { "fg": s:yellow })
+call s:h("jsImport", { "fg": s:purple })
+call s:h("jsModuleAs", { "fg": s:purple })
+call s:h("jsModuleWords", { "fg": s:purple })
+call s:h("jsModules", { "fg": s:purple })
+call s:h("jsNull", { "fg": s:dark_yellow })
+call s:h("jsOperator", { "fg": s:purple })
+call s:h("jsStorageClass", { "fg": s:purple })
+call s:h("jsSuper", { "fg": s:red })
+call s:h("jsTemplateBraces", { "fg": s:dark_red })
+call s:h("jsTemplateVar", { "fg": s:green })
+call s:h("jsThis", { "fg": s:red })
+call s:h("jsUndefined", { "fg": s:dark_yellow })
+" https://github.com/othree/yajs.vim
+call s:h("javascriptArrowFunc", { "fg": s:purple })
+call s:h("javascriptClassExtends", { "fg": s:purple })
+call s:h("javascriptClassKeyword", { "fg": s:purple })
+call s:h("javascriptDocNotation", { "fg": s:purple })
+call s:h("javascriptDocParamName", { "fg": s:blue })
+call s:h("javascriptDocTags", { "fg": s:purple })
+call s:h("javascriptEndColons", { "fg": s:white })
+call s:h("javascriptExport", { "fg": s:purple })
+call s:h("javascriptFuncArg", { "fg": s:white })
+call s:h("javascriptFuncKeyword", { "fg": s:purple })
+call s:h("javascriptIdentifier", { "fg": s:red })
+call s:h("javascriptImport", { "fg": s:purple })
+call s:h("javascriptMethodName", { "fg": s:white })
+call s:h("javascriptObjectLabel", { "fg": s:white })
+call s:h("javascriptOpSymbol", { "fg": s:cyan })
+call s:h("javascriptOpSymbols", { "fg": s:cyan })
+call s:h("javascriptPropertyName", { "fg": s:green })
+call s:h("javascriptTemplateSB", { "fg": s:dark_red })
+call s:h("javascriptVariable", { "fg": s:purple })
+
+" JSON
+call s:h("jsonCommentError", { "fg": s:white })
+call s:h("jsonKeyword", { "fg": s:red })
+call s:h("jsonBoolean", { "fg": s:dark_yellow })
+call s:h("jsonNumber", { "fg": s:dark_yellow })
+call s:h("jsonQuote", { "fg": s:white })
+call s:h("jsonMissingCommaError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonNoQuotesError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonNumError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonString", { "fg": s:green })
+call s:h("jsonStringSQError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonSemicolonError", { "fg": s:red, "gui": "reverse" })
+
+" LESS
+call s:h("lessVariable", { "fg": s:purple })
+call s:h("lessAmpersandChar", { "fg": s:white })
+call s:h("lessClass", { "fg": s:dark_yellow })
+
+" Markdown (keep consistent with HTML, above)
+call s:h("markdownBlockquote", { "fg": s:comment_grey })
+call s:h("markdownBold", { "fg": s:dark_yellow, "gui": "bold", "cterm": "bold" })
+call s:h("markdownBoldItalic", { "fg": s:green, "gui": "bold,italic", "cterm": "bold,italic" })
+call s:h("markdownCode", { "fg": s:green })
+call s:h("markdownCodeBlock", { "fg": s:green })
+call s:h("markdownCodeDelimiter", { "fg": s:green })
+call s:h("markdownH1", { "fg": s:red })
+call s:h("markdownH2", { "fg": s:red })
+call s:h("markdownH3", { "fg": s:red })
+call s:h("markdownH4", { "fg": s:red })
+call s:h("markdownH5", { "fg": s:red })
+call s:h("markdownH6", { "fg": s:red })
+call s:h("markdownHeadingDelimiter", { "fg": s:red })
+call s:h("markdownHeadingRule", { "fg": s:comment_grey })
+call s:h("markdownId", { "fg": s:purple })
+call s:h("markdownIdDeclaration", { "fg": s:blue })
+call s:h("markdownIdDelimiter", { "fg": s:purple })
+call s:h("markdownItalic", { "fg": s:purple, "gui": "italic", "cterm": "italic" })
+call s:h("markdownLinkDelimiter", { "fg": s:purple })
+call s:h("markdownLinkText", { "fg": s:blue })
+call s:h("markdownListMarker", { "fg": s:red })
+call s:h("markdownOrderedListMarker", { "fg": s:red })
+call s:h("markdownRule", { "fg": s:comment_grey })
+call s:h("markdownUrl", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+
+" Perl
+call s:h("perlFiledescRead", { "fg": s:green })
+call s:h("perlFunction", { "fg": s:purple })
+call s:h("perlMatchStartEnd",{ "fg": s:blue })
+call s:h("perlMethod", { "fg": s:purple })
+call s:h("perlPOD", { "fg": s:comment_grey })
+call s:h("perlSharpBang", { "fg": s:comment_grey })
+call s:h("perlSpecialString",{ "fg": s:dark_yellow })
+call s:h("perlStatementFiledesc", { "fg": s:red })
+call s:h("perlStatementFlow",{ "fg": s:red })
+call s:h("perlStatementInclude", { "fg": s:purple })
+call s:h("perlStatementScalar",{ "fg": s:purple })
+call s:h("perlStatementStorage", { "fg": s:purple })
+call s:h("perlSubName",{ "fg": s:yellow })
+call s:h("perlVarPlain",{ "fg": s:blue })
+
+" PHP
+call s:h("phpVarSelector", { "fg": s:red })
+call s:h("phpOperator", { "fg": s:white })
+call s:h("phpParent", { "fg": s:white })
+call s:h("phpMemberSelector", { "fg": s:white })
+call s:h("phpType", { "fg": s:purple })
+call s:h("phpKeyword", { "fg": s:purple })
+call s:h("phpClass", { "fg": s:yellow })
+call s:h("phpUseClass", { "fg": s:white })
+call s:h("phpUseAlias", { "fg": s:white })
+call s:h("phpInclude", { "fg": s:purple })
+call s:h("phpClassExtends", { "fg": s:green })
+call s:h("phpDocTags", { "fg": s:white })
+call s:h("phpFunction", { "fg": s:blue })
+call s:h("phpFunctions", { "fg": s:cyan })
+call s:h("phpMethodsVar", { "fg": s:dark_yellow })
+call s:h("phpMagicConstants", { "fg": s:dark_yellow })
+call s:h("phpSuperglobals", { "fg": s:red })
+call s:h("phpConstants", { "fg": s:dark_yellow })
+
+" Ruby
+call s:h("rubyBlockParameter", { "fg": s:red})
+call s:h("rubyBlockParameterList", { "fg": s:red })
+call s:h("rubyClass", { "fg": s:purple})
+call s:h("rubyConstant", { "fg": s:yellow})
+call s:h("rubyControl", { "fg": s:purple })
+call s:h("rubyEscape", { "fg": s:red})
+call s:h("rubyFunction", { "fg": s:blue})
+call s:h("rubyGlobalVariable", { "fg": s:red})
+call s:h("rubyInclude", { "fg": s:blue})
+call s:h("rubyIncluderubyGlobalVariable", { "fg": s:red})
+call s:h("rubyInstanceVariable", { "fg": s:red})
+call s:h("rubyInterpolation", { "fg": s:cyan })
+call s:h("rubyInterpolationDelimiter", { "fg": s:red })
+call s:h("rubyInterpolationDelimiter", { "fg": s:red})
+call s:h("rubyRegexp", { "fg": s:cyan})
+call s:h("rubyRegexpDelimiter", { "fg": s:cyan})
+call s:h("rubyStringDelimiter", { "fg": s:green})
+call s:h("rubySymbol", { "fg": s:cyan})
+
+" Sass
+" https://github.com/tpope/vim-haml
+call s:h("sassAmpersand", { "fg": s:red })
+call s:h("sassClass", { "fg": s:dark_yellow })
+call s:h("sassControl", { "fg": s:purple })
+call s:h("sassExtend", { "fg": s:purple })
+call s:h("sassFor", { "fg": s:white })
+call s:h("sassFunction", { "fg": s:cyan })
+call s:h("sassId", { "fg": s:blue })
+call s:h("sassInclude", { "fg": s:purple })
+call s:h("sassMedia", { "fg": s:purple })
+call s:h("sassMediaOperators", { "fg": s:white })
+call s:h("sassMixin", { "fg": s:purple })
+call s:h("sassMixinName", { "fg": s:blue })
+call s:h("sassMixing", { "fg": s:purple })
+call s:h("sassVariable", { "fg": s:purple })
+" https://github.com/cakebaker/scss-syntax.vim
+call s:h("scssExtend", { "fg": s:purple })
+call s:h("scssImport", { "fg": s:purple })
+call s:h("scssInclude", { "fg": s:purple })
+call s:h("scssMixin", { "fg": s:purple })
+call s:h("scssSelectorName", { "fg": s:dark_yellow })
+call s:h("scssVariable", { "fg": s:purple })
+
+" TeX
+call s:h("texStatement", { "fg": s:purple })
+call s:h("texSubscripts", { "fg": s:dark_yellow })
+call s:h("texSuperscripts", { "fg": s:dark_yellow })
+call s:h("texTodo", { "fg": s:dark_red })
+call s:h("texBeginEnd", { "fg": s:purple })
+call s:h("texBeginEndName", { "fg": s:blue })
+call s:h("texMathMatcher", { "fg": s:blue })
+call s:h("texMathDelim", { "fg": s:blue })
+call s:h("texDelimiter", { "fg": s:dark_yellow })
+call s:h("texSpecialChar", { "fg": s:dark_yellow })
+call s:h("texCite", { "fg": s:blue })
+call s:h("texRefZone", { "fg": s:blue })
+
+" TypeScript
+call s:h("typescriptReserved", { "fg": s:purple })
+call s:h("typescriptEndColons", { "fg": s:white })
+call s:h("typescriptBraces", { "fg": s:white })
+
+" XML
+call s:h("xmlAttrib", { "fg": s:dark_yellow })
+call s:h("xmlEndTag", { "fg": s:red })
+call s:h("xmlTag", { "fg": s:red })
+call s:h("xmlTagName", { "fg": s:red })
+
+" }}}
+
+" Plugin Highlighting {{{
+
+" airblade/vim-gitgutter
+call s:h("GitGutterAdd", { "fg": s:green })
+call s:h("GitGutterChange", { "fg": s:yellow })
+call s:h("GitGutterDelete", { "fg": s:red })
+
+" dense-analysis/ale
+call s:h("ALEError", { "fg": s:red, "gui": "underline", "cterm": "underline" })
+call s:h("ALEWarning", { "fg": s:yellow, "gui": "underline", "cterm": "underline" })
+call s:h("ALEInfo", { "gui": "underline", "cterm": "underline" })
+call s:h("ALEErrorSign", { "fg": s:red })
+call s:h("ALEWarningSign", { "fg": s:yellow })
+call s:h("ALEInfoSign", { })
+
+" easymotion/vim-easymotion
+call s:h("EasyMotionTarget", { "fg": s:red, "gui": "bold", "cterm": "bold" })
+call s:h("EasyMotionTarget2First", { "fg": s:yellow, "gui": "bold", "cterm": "bold" })
+call s:h("EasyMotionTarget2Second", { "fg": s:dark_yellow, "gui": "bold", "cterm": "bold" })
+call s:h("EasyMotionShade", { "fg": s:comment_grey })
+
+" lewis6991/gitsigns.nvim
+hi link GitSignsAdd GitGutterAdd
+hi link GitSignsChange GitGutterChange
+hi link GitSignsDelete GitGutterDelete
+
+" mhinz/vim-signify
+hi link SignifySignAdd GitGutterAdd
+hi link SignifySignChange GitGutterChange
+hi link SignifySignDelete GitGutterDelete
+
+" neoclide/coc.nvim
+call s:h("CocErrorSign", { "fg": s:red })
+call s:h("CocWarningSign", { "fg": s:yellow })
+call s:h("CocInfoSign", { "fg": s:blue })
+call s:h("CocHintSign", { "fg": s:cyan })
+call s:h("CocFadeOut", { "fg": s:comment_grey })
+" https://github.com/joshdick/onedark.vim/issues/313
+highlight! link CocMenuSel PmenuSel
+
+" neomake/neomake
+call s:h("NeomakeErrorSign", { "fg": s:red })
+call s:h("NeomakeWarningSign", { "fg": s:yellow })
+call s:h("NeomakeInfoSign", { "fg": s:blue })
+
+" plasticboy/vim-markdown (keep consistent with Markdown, above)
+call s:h("mkdDelimiter", { "fg": s:purple })
+call s:h("mkdHeading", { "fg": s:red })
+call s:h("mkdLink", { "fg": s:blue })
+call s:h("mkdURL", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+
+" prabirshrestha/vim-lsp
+call s:h("LspErrorText", { "fg": s:red })
+call s:h("LspWarningText", { "fg": s:yellow })
+call s:h("LspInformationText", { "fg":s:blue })
+call s:h("LspHintText", { "fg":s:cyan })
+call s:h("LspErrorHighlight", { "fg": s:red, "gui": "underline", "cterm": "underline" })
+call s:h("LspWarningHighlight", { "fg": s:yellow, "gui": "underline", "cterm": "underline" })
+call s:h("LspInformationHighlight", { "fg":s:blue, "gui": "underline", "cterm": "underline" })
+call s:h("LspHintHighlight", { "fg":s:cyan, "gui": "underline", "cterm": "underline" })
+
+" tpope/vim-fugitive
+call s:h("diffAdded", { "fg": s:green })
+call s:h("diffRemoved", { "fg": s:red })
+
+" }}}
+
+" Git Highlighting {{{
+
+call s:h("gitcommitComment", { "fg": s:comment_grey })
+call s:h("gitcommitUnmerged", { "fg": s:green })
+call s:h("gitcommitOnBranch", {})
+call s:h("gitcommitBranch", { "fg": s:purple })
+call s:h("gitcommitDiscardedType", { "fg": s:red })
+call s:h("gitcommitSelectedType", { "fg": s:green })
+call s:h("gitcommitHeader", {})
+call s:h("gitcommitUntrackedFile", { "fg": s:cyan })
+call s:h("gitcommitDiscardedFile", { "fg": s:red })
+call s:h("gitcommitSelectedFile", { "fg": s:green })
+call s:h("gitcommitUnmergedFile", { "fg": s:yellow })
+call s:h("gitcommitFile", {})
+call s:h("gitcommitSummary", { "fg": s:white })
+call s:h("gitcommitOverflow", { "fg": s:red })
+hi link gitcommitNoBranch gitcommitBranch
+hi link gitcommitUntracked gitcommitComment
+hi link gitcommitDiscarded gitcommitComment
+hi link gitcommitSelected gitcommitComment
+hi link gitcommitDiscardedArrow gitcommitDiscardedFile
+hi link gitcommitSelectedArrow gitcommitSelectedFile
+hi link gitcommitUnmergedArrow gitcommitUnmergedFile
+
+" }}}
+
+" Neovim-Specific Highlighting {{{
+
+if has("nvim")
+ " Neovim terminal colors {{{
+ let g:terminal_color_0 = s:black.gui
+ let g:terminal_color_1 = s:red.gui
+ let g:terminal_color_2 = s:green.gui
+ let g:terminal_color_3 = s:yellow.gui
+ let g:terminal_color_4 = s:blue.gui
+ let g:terminal_color_5 = s:purple.gui
+ let g:terminal_color_6 = s:cyan.gui
+ let g:terminal_color_7 = s:white.gui
+ let g:terminal_color_8 = s:visual_grey.gui
+ let g:terminal_color_9 = s:dark_red.gui
+ let g:terminal_color_10 = s:green.gui " No dark version
+ let g:terminal_color_11 = s:dark_yellow.gui
+ let g:terminal_color_12 = s:blue.gui " No dark version
+ let g:terminal_color_13 = s:purple.gui " No dark version
+ let g:terminal_color_14 = s:cyan.gui " No dark version
+ let g:terminal_color_15 = s:comment_grey.gui
+ let g:terminal_color_background = s:background.gui
+ let g:terminal_color_foreground = s:foreground.gui
+ " }}}
+
+ " Neovim Diagnostics {{{
+ call s:h("DiagnosticError", { "fg": s:red })
+ call s:h("DiagnosticWarn", { "fg": s:yellow })
+ call s:h("DiagnosticInfo", { "fg": s:blue })
+ call s:h("DiagnosticHint", { "fg": s:cyan })
+ call s:h("DiagnosticUnderlineError", { "fg": s:red, "gui": "underline", "cterm": "underline" })
+ call s:h("DiagnosticUnderlineWarn", { "fg": s:yellow, "gui": "underline", "cterm": "underline" })
+ call s:h("DiagnosticUnderlineInfo", { "fg": s:blue, "gui": "underline", "cterm": "underline" })
+ call s:h("DiagnosticUnderlineHint", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+ " }}}
+
+ " Neovim LSP (for versions < 0.5.1) {{{
+ hi link LspDiagnosticsDefaultError DiagnosticError
+ hi link LspDiagnosticsDefaultWarning DiagnosticWarn
+ hi link LspDiagnosticsDefaultInformation DiagnosticInfo
+ hi link LspDiagnosticsDefaultHint DiagnosticHint
+ hi link LspDiagnosticsUnderlineError DiagnosticUnderlineError
+ hi link LspDiagnosticsUnderlineWarning DiagnosticUnderlineWarn
+ hi link LspDiagnosticsUnderlineInformation DiagnosticUnderlineInfo
+ hi link LspDiagnosticsUnderlineHint DiagnosticUnderlineHint
+ " }}}
+endif
+
+" }}}
+
+" Must appear at the end of the file to work around this oddity:
+" https://groups.google.com/forum/#!msg/vim_dev/afPqwAFNdrU/nqh6tOM87QUJ
+set background=dark
diff --git a/.config/nvim/dev.vim b/.config/nvim/dev.vim
new file mode 100644
index 0000000..89b8eca
--- /dev/null
+++ b/.config/nvim/dev.vim
@@ -0,0 +1,93 @@
+source ~/.config/nvim/init.vim
+
+packadd! onedark.vim
+
+" --> Zeal docs
+let g:zv_disable_mapping = 1
+nmap <leader>z <Plug>Zeavim
+vmap <leader>z <Plug>ZVVisSelection
+nmap gz <Plug>ZVOperator
+nmap <leader><leader>z <Plug>ZVKeyDocset
+
+" --> COC
+autocmd! User coc.nvim source $HOME/.config/nvim/coc/coc-onload.vim
+let g:coc_config_home = '$HOME/.config/nvim/coc'
+let g:coc_data_home = '$HOME/.local/share/nvim/site/coc'
+let g:coc_global_extensions = [
+ \ 'coc-json',
+ \ 'coc-marketplace',
+ \ 'coc-css',
+ \ 'coc-tsserver',
+ \ 'coc-pyright',
+ \ 'coc-java',
+ \ 'coc-sh',
+ \ ]
+nnoremap <silent><nowait> <leader>ca :<C-u>CocList diagnostics<cr>
+nnoremap <silent><nowait> <leader>ce :<C-u>CocList extensions<cr>
+nnoremap <silent><nowait> <leader>cc :<C-u>CocList commands<cr>
+nnoremap <silent><nowait> <leader>co :<C-u>CocList outline<cr>
+nnoremap <silent><nowait> <leader>cs :<C-u>CocList -I symbols<cr>
+nnoremap <silent><nowait> <leader>cj :<C-u>CocNext<CR>
+nnoremap <silent><nowait> <leader>ck :<C-u>CocPrev<CR>
+nnoremap <silent><nowait> <leader>cp :<C-u>CocListResume<CR>
+nnoremap <leader>cm :CocList marketplace<CR>
+
+" --> Vimspector
+let g:vimspector_base_dir = expand('$HOME/.local/share/nvim/vimspector')
+let g:vimspector_enable_mappings = 'HUMAN'
+nnoremap <leader>dc <Plug>VimspectorContinue
+nnoremap <leader>ds <Plug>VimspectorStop
+nnoremap <leader>dr <Plug>VimspectorRestart
+nnoremap <leader>dp <Plug>VimspectorPause
+nnoremap <leader>dl <Plug>VimspectorBreakpoints
+nnoremap <leader>dd <Plug>VimspectorToggleBreakpoint
+nnoremap <leader>db <Plug>VimspectorToggleConditionalBreakpoint
+nnoremap <leader>df <Plug>VimspectorAddFunctionBreakpoint
+nnoremap <leader>dg <Plug>VimspectorGoToCurrentLine
+nnoremap <leader>dx :call vimspector#ClearBreakpoints()<CR>
+nnoremap <leader>dq :VimspectorReset<CR>
+nnoremap <A-C> <Plug>VimspectorContinue
+nnoremap <A-n> <Plug>VimspectorStepOver
+nnoremap <A-i> <Plug>VimspectorStepInto
+nnoremap <A-o> <Plug>VimspectorStepOut
+nnoremap <A-b> <Plug>VimspectorToggleBreakpoint
+nnoremap <A-c> <Plug>VimspectorRunToCursor
+
+" --> onedark theme
+if exists('+termguicolors')
+ let g:airline_theme = 'onedark'
+ let g:onedark_terminal_italics = 1
+ let g:onedark_color_overrides = {
+ \ "foreground": { "gui": "#BBC2CF", "cterm": "145", "cterm16": "NONE" },
+ \ "background": { "gui": "#181C24", "cterm": "235", "cterm16": "NONE" },
+ \ "comment_grey": { "gui": "#6C7380", "cterm": "59", "cterm16": "7" },
+ \ "gutter_fg_grey": { "gui": "#6272A4", "cterm": "238", "cterm16": "8" },
+ \ "special_grey": { "gui": "#5Ba078", "cterm": "238", "cterm16": "7" },
+ \ }
+ " \ "background": { "gui": "#202426", "cterm": "235", "cterm16": "NONE" },
+ "
+ " \ "red": { "gui": "#E06C75", "cterm": "204", "cterm16": "1" },
+ " \ "dark_red": { "gui": "#BE5046", "cterm": "196", "cterm16": "9" },
+ " \ "green": { "gui": "#98C379", "cterm": "114", "cterm16": "2" },
+ " \ "yellow": { "gui": "#E5C07B", "cterm": "180", "cterm16": "3" },
+ " \ "dark_yellow": { "gui": "#D19A66", "cterm": "173", "cterm16": "11" },
+ " \ "blue": { "gui": "#61AFEF", "cterm": "39", "cterm16": "4" },
+ " \ "purple": { "gui": "#C678DD", "cterm": "170", "cterm16": "5" },
+ " \ "cyan": { "gui": "#56B6C2", "cterm": "38", "cterm16": "6" },
+ " \ "black": { "gui": "#282C34", "cterm": "235", "cterm16": "0" },
+ " \ "white": { "gui": "#ABB2BF", "cterm": "145", "cterm16": "15" },
+ " \ "cursor_grey": { "gui": "#2C323C", "cterm": "236", "cterm16": "0" },
+ " \ "visual_grey": { "gui": "#3E4452", "cterm": "237", "cterm16": "8" },
+ " \ "menu_grey": { "gui": "#3E4452", "cterm": "237", "cterm16": "7" },
+ " \ "vertsplit": { "gui": "#3E4452", "cterm": "59", "cterm16": "7" },
+
+ " autocmd ColorScheme * call onedark#extend_highlight("LineNr", {
+ " \ "fg": { "gui": "#6272A4", "cterm": "238", "cterm16": "8" },
+ " \ })
+ let &t_8f="\<Esc>[38;2;%lu;%lu;%lum"
+ let &t_8b="\<Esc>[48;2;%lu;%lu;%lum"
+ " set termguicolors noshowmode
+ colorscheme onedark
+ " autocmd VimEnter * AirlineTheme
+endif
+
diff --git a/.config/nvim/init.bak.vim b/.config/nvim/init.bak.vim
new file mode 100644
index 0000000..6057fe4
--- /dev/null
+++ b/.config/nvim/init.bak.vim
@@ -0,0 +1,225 @@
+let mapleader=" "
+
+if ! filereadable(system('echo -n "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/plug.vim"'))
+ echo "Downloading junegunn/vim-plug to manage plugins..."
+ silent !mkdir -p ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/
+ silent !curl "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim" > ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/plug.vim
+ autocmd VimEnter * PlugInstall
+endif
+
+call plug#begin(system('echo -n "${XDG_DATA_HOME:-$HOME/.local/share}/nvim/plugged"'))
+Plug 'tpope/vim-surround'
+Plug 'tpope/vim-commentary'
+Plug 'ptzz/lf.vim'
+Plug 'voldikss/vim-floaterm'
+Plug 'KabbAmine/zeavim.vim' ", {'on': ['Zeavim', 'ZeavimV', 'ZVVisSelection', 'ZVOperator', 'ZVKeyDocset']}
+Plug 'neoclide/coc.nvim', {'on': ['CocList', 'CocConfig'], 'branch': 'release'}
+Plug 'ap/vim-css-color' " color code highlighting
+Plug 'xuhdev/vim-latex-live-preview', {'for': 'tex'}
+Plug 'machakann/vim-verdin', {'for': 'vim'}
+Plug 'puremourning/vimspector', {'for': 'python'}
+" Plug 'powerman/vim-plugin-AnsiEsc'
+" Plug 'junegunn/goyo.vim', {'on': 'Goyo'}
+" Plug 'jreybert/vimagit'
+" Plug 'lukesmithxyz/vimling'
+" Plug 'vimwiki/vimwiki'
+Plug 'vim-airline/vim-airline', {'on': 'AirlineTheme'}
+Plug 'vim-airline/vim-airline-themes', {'on': 'AirlineTheme'}
+Plug 'joshdick/onedark.vim'
+call plug#end()
+
+let g:Verdin#autocomplete = 1
+let g:livepreview_previewer = 'zathura'
+
+set title showmatch nowrap
+set mouse=a
+set tabstop=2 shiftwidth=0
+set number relativenumber
+set cursorline cursorcolumn
+set cc=80
+set scrolloff=5
+set splitbelow splitright
+set updatetime=500
+
+syntax on
+filetype plugin indent on
+autocmd FileType text setlocal tabstop=8 shiftwidth=4
+autocmd FileType html setlocal tabstop=2 shiftwidth=2
+autocmd FileType sql setlocal commentstring=--\ %s
+autocmd BufEnter bm-files,bm-dirs setlocal tabstop=8 shiftwidth=8
+autocmd BufWritePost bm-files,bm-dirs silent !shortcuts
+autocmd BufWritePost config.h,config.def.h !cd "%:h"; sudo make clean install
+autocmd BufWritePre * %s/\s\+$//e
+au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
+
+autocmd BufWritePost */Documents/Notes/*.md silent !pandoc % -o "$HOME/Documents/Notes/.out/$(basename % .md).html"
+autocmd BufWritePost .Xresources silent !xrdb "%"
+autocmd BufRead,BufNewFile *.yt* set filetype=conf
+
+autocmd TermOpen * startinsert
+command! -nargs=* T split | terminal <args>
+
+" --> Scratch buffer
+if exists('g:loaded_scratch')
+ finish
+endif
+let g:loaded_scratch = 1
+command! -nargs=1 -complete=command D call scratch#open(<q-args>, <q-mods>)
+
+" --> Zeal docs
+let g:zv_disable_mapping = 1
+nmap <leader>z <Plug>Zeavim
+vmap <leader>z <Plug>ZVVisSelection
+nmap gz <Plug>ZVOperator
+nmap <leader><leader>z <Plug>ZVKeyDocset
+
+" --> COC
+autocmd! User coc.nvim source $HOME/.config/nvim/coc/coc-onload.vim
+let g:coc_config_home = '$HOME/.config/nvim/coc'
+let g:coc_data_home = '$HOME/.local/share/nvim/site/coc'
+let g:coc_global_extensions = [
+ \ 'coc-json',
+ \ 'coc-marketplace',
+ \ 'coc-css',
+ \ 'coc-tsserver',
+ \ 'coc-pyright',
+ \ 'coc-java',
+ \ 'coc-sh',
+ \ ]
+nnoremap <silent><nowait> <leader>ca :<C-u>CocList diagnostics<cr>
+nnoremap <silent><nowait> <leader>ce :<C-u>CocList extensions<cr>
+nnoremap <silent><nowait> <leader>cc :<C-u>CocList commands<cr>
+nnoremap <silent><nowait> <leader>co :<C-u>CocList outline<cr>
+nnoremap <silent><nowait> <leader>cs :<C-u>CocList -I symbols<cr>
+nnoremap <silent><nowait> <leader>cj :<C-u>CocNext<CR>
+nnoremap <silent><nowait> <leader>ck :<C-u>CocPrev<CR>
+nnoremap <silent><nowait> <leader>cp :<C-u>CocListResume<CR>
+nnoremap <leader>cm :CocList marketplace<CR>
+
+" --> Vimspector
+let g:vimspector_base_dir = expand('$HOME/.local/share/nvim/vimspector')
+let g:vimspector_enable_mappings = 'HUMAN'
+nnoremap <leader>dc <Plug>VimspectorContinue
+nnoremap <leader>ds <Plug>VimspectorStop
+nnoremap <leader>dr <Plug>VimspectorRestart
+nnoremap <leader>dp <Plug>VimspectorPause
+nnoremap <leader>dl <Plug>VimspectorBreakpoints
+nnoremap <leader>dd <Plug>VimspectorToggleBreakpoint
+nnoremap <leader>db <Plug>VimspectorToggleConditionalBreakpoint
+nnoremap <leader>df <Plug>VimspectorAddFunctionBreakpoint
+nnoremap <leader>dg <Plug>VimspectorGoToCurrentLine
+nnoremap <leader>dx :call vimspector#ClearBreakpoints()<CR>
+nnoremap <leader>dq :VimspectorReset<CR>
+nnoremap <A-C> <Plug>VimspectorContinue
+nnoremap <A-n> <Plug>VimspectorStepOver
+nnoremap <A-i> <Plug>VimspectorStepInto
+nnoremap <A-o> <Plug>VimspectorStepOut
+nnoremap <A-b> <Plug>VimspectorToggleBreakpoint
+nnoremap <A-c> <Plug>VimspectorRunToCursor
+
+" --> Lf
+" let g:lf_command_override = 'lf -command ...'
+let g:NERDTreeHijackNetrw = 0
+" let g:lf_replace_netrw = 1
+let g:lf_width = 1.0
+let g:lf_height = 1.0
+let g:lf_map_keys = 0
+nnoremap <Esc>o :LfCurrentFile<CR>
+nnoremap <Esc>l :LfWorkingDirectory<CR>
+nnoremap <leader>o :LfCurrentFileNewTab<CR>
+nnoremap <leader>l :LfWorkingDirectoryExistingOrNewTab<CR>
+
+" --> onedark theme
+if exists('+termguicolors') && filereadable(system('echo -n "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/onedark.vim"'))
+ let g:airline_theme = 'onedark'
+ let g:onedark_terminal_italics = 1
+ let g:onedark_color_overrides = {
+ \ "foreground": { "gui": "#BBC2CF", "cterm": "145", "cterm16": "NONE" },
+ \ "background": { "gui": "#181C24", "cterm": "235", "cterm16": "NONE" },
+ \ "comment_grey": { "gui": "#6C7380", "cterm": "59", "cterm16": "7" },
+ \ "gutter_fg_grey": { "gui": "#6272A4", "cterm": "238", "cterm16": "8" },
+ \ "special_grey": { "gui": "#5Ba078", "cterm": "238", "cterm16": "7" },
+ \ }
+ " \ "background": { "gui": "#202426", "cterm": "235", "cterm16": "NONE" },
+ "
+ " \ "red": { "gui": "#E06C75", "cterm": "204", "cterm16": "1" },
+ " \ "dark_red": { "gui": "#BE5046", "cterm": "196", "cterm16": "9" },
+ " \ "green": { "gui": "#98C379", "cterm": "114", "cterm16": "2" },
+ " \ "yellow": { "gui": "#E5C07B", "cterm": "180", "cterm16": "3" },
+ " \ "dark_yellow": { "gui": "#D19A66", "cterm": "173", "cterm16": "11" },
+ " \ "blue": { "gui": "#61AFEF", "cterm": "39", "cterm16": "4" },
+ " \ "purple": { "gui": "#C678DD", "cterm": "170", "cterm16": "5" },
+ " \ "cyan": { "gui": "#56B6C2", "cterm": "38", "cterm16": "6" },
+ " \ "black": { "gui": "#282C34", "cterm": "235", "cterm16": "0" },
+ " \ "white": { "gui": "#ABB2BF", "cterm": "145", "cterm16": "15" },
+ " \ "cursor_grey": { "gui": "#2C323C", "cterm": "236", "cterm16": "0" },
+ " \ "visual_grey": { "gui": "#3E4452", "cterm": "237", "cterm16": "8" },
+ " \ "menu_grey": { "gui": "#3E4452", "cterm": "237", "cterm16": "7" },
+ " \ "vertsplit": { "gui": "#3E4452", "cterm": "59", "cterm16": "7" },
+
+ " autocmd ColorScheme * call onedark#extend_highlight("LineNr", {
+ " \ "fg": { "gui": "#6272A4", "cterm": "238", "cterm16": "8" },
+ " \ })
+ let &t_8f="\<Esc>[38;2;%lu;%lu;%lum"
+ let &t_8b="\<Esc>[48;2;%lu;%lu;%lum"
+ set termguicolors noshowmode
+ colorscheme onedark
+ autocmd VimEnter * AirlineTheme
+endif
+
+if !exists('g:lasttab')
+ let g:lasttab = 1
+endif
+nmap g; :exe "tabn ".g:lasttab<CR>
+au TabLeave * let g:lasttab = tabpagenr()
+nnoremap g1 1gt
+nnoremap g2 2gt
+nnoremap g3 3gt
+nnoremap g4 4gt
+nnoremap g5 5gt
+nnoremap g6 6gt
+nnoremap g7 7gt
+nnoremap g8 8gt
+nnoremap g9 :tablast<CR>
+
+vnoremap <C-c> "*y :let @+=@*<CR>
+vnoremap <C-A-c> "*d :let @+=@*<CR>
+noremap <C-p> "+p
+noremap <C-A-p> "+P
+
+nnoremap c "_c
+inoremap jk <Esc>
+" map ;n /<++><Enter>c4l
+imap ;n <Esc>/<++><Enter>c4l
+
+autocmd FileType html,markdown inoremap ;s ><Esc>bi<<Esc>ea
+autocmd FileType html,markdown inoremap ;c ><Esc>bi</<Esc>ea
+autocmd FileType html,markdown inoremap ;i <Esc>b"tywi<<Esc>ea><++></><CR><++><Esc>k$P2F>i
+autocmd FileType html,markdown inoremap ;l <Esc>b"tywi<<Esc>ea></><CR><++><Esc>k$PF<i
+autocmd FileType html,markdown inoremap ;b <Esc>b"tywi<<Esc>ea><CR><++><CR></><CR><++><Esc>k$P2k$i
+autocmd FileType html,markdown inoremap ;ap <p><CR><++><CR></p><CR><++><Esc>3k$i
+autocmd FileType html,markdown inoremap ;aa <a href=""><CR><++><CR></a><CR><++><Esc>3k$hi
+
+nnoremap <leader>fl :w<CR>:!dev lint "%"<CR>
+nnoremap <leader>fm :w<CR>:!dev format "%"<CR>
+nnoremap <leader>fc :w<CR>:!dev compile "%"<CR>
+nnoremap <leader>fr :w<CR>:!dev run "%"<CR>
+nnoremap <leader>ft :w<CR>:!dev test "%"<CR>
+
+autocmd BufEnter * nmap <leader>t :w<CR>:se nornu<CR>:!dev test "%"<CR>:se rnu<CR>
+autocmd BufEnter * nmap <leader>T :w<CR>:se nornu<CR>:T dev test "%"<CR>
+autocmd BufEnter * imap <F5> <Esc>:w<CR>:se nornu<CR>:T dev test "%"<CR>
+
+nnoremap <leader>w :set wrap!<CR>
+nnoremap <leader>p :!opout "%:p"<CR>
+nnoremap <leader>F :Goyo<CR>
+nnoremap <leader>O :T mimeopen --ask %<CR>
+nnoremap <leader>ec :tabnew ~/.config/nvim/init.vim<CR>
+nnoremap <leader><C-r> :source ~/.config/nvim/init.vim<CR>
+nnoremap <leader>s :%s//gc<Left><Left><Left>
+nnoremap <leader>r :w<CR>:!%:p<CR>
+nnoremap <leader>R :w<CR>:T %:p<CR>
+
+nnoremap <leader>gc :T git add --all && git commit<CR>
+
+source ~/.config/nvim/shortcuts.vim
diff --git a/.config/nvim/init.vim b/.config/nvim/init.vim
new file mode 100644
index 0000000..6583a94
--- /dev/null
+++ b/.config/nvim/init.vim
@@ -0,0 +1,178 @@
+let mapleader=" "
+let config_dir = system('echo -n "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/"')
+
+" if ! filereadable(system('echo -n "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/plug.vim"'))
+" echo "Downloading junegunn/vim-plug to manage plugins..."
+" silent !mkdir -p ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/
+" silent !curl "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim" > ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/plug.vim
+" autocmd VimEnter * PlugInstall
+" endif
+
+if filereadable(config_dir . "autoload/plug.vim")
+ call plug#begin(system('echo -n "${XDG_DATA_HOME:-$HOME/.local/share}/nvim/plugged"'))
+ Plug 'tpope/vim-commentary'
+ Plug 'tpope/vim-surround'
+ Plug 'ptzz/lf.vim'
+ Plug 'voldikss/vim-floaterm'
+ Plug 'xuhdev/vim-latex-live-preview', {'for': 'tex'}
+ Plug 'ap/vim-css-color' " color code highlighting
+ Plug 'neoclide/coc.nvim', {'on': ['CocList', 'CocConfig'], 'branch': 'release'}
+ " Plug 'KabbAmine/zeavim.vim' ", {'on': ['Zeavim', 'ZeavimV', 'ZVVisSelection', 'ZVOperator', 'ZVKeyDocset']}
+ " Plug 'machakann/vim-verdin', {'for': 'vim'}
+ " Plug 'puremourning/vimspector', {'for': 'python'}
+ " Plug 'powerman/vim-plugin-AnsiEsc'
+ " Plug 'junegunn/goyo.vim', {'on': 'Goyo'}
+ " Plug 'jreybert/vimagit'
+ " Plug 'lukesmithxyz/vimling'
+ " Plug 'vimwiki/vimwiki'
+ " Plug 'vim-airline/vim-airline', {'on': 'AirlineTheme'}
+ " Plug 'vim-airline/vim-airline-themes', {'on': 'AirlineTheme'}
+ " Plug 'joshdick/onedark.vim'
+ call plug#end()
+endif
+
+let g:Verdin#autocomplete = 1
+let g:livepreview_previewer = 'zathura'
+let g:tex_flavor = 'latex'
+
+set title showmatch nowrap mouse=a scrolloff=5
+set tabstop=2 shiftwidth=0
+set cursorline linebreak
+set number relativenumber
+set splitbelow splitright
+set updatetime=1000
+set notermguicolors lazyredraw
+set listchars=tab:\┆\ "│
+
+syntax on
+filetype plugin indent on
+colorscheme vim
+highlight NonText ctermfg=242
+highlight ColorColumn ctermbg=238
+highlight! link CursorColumn ColorColumn
+autocmd FileType text,fstab setlocal tabstop=8 shiftwidth=8
+autocmd FileType html setlocal tabstop=2 shiftwidth=2 list nolinebreak
+autocmd FileType sql setlocal commentstring=--\ %s
+autocmd BufEnter bm-files,bm-dirs setlocal tabstop=8 shiftwidth=8
+autocmd BufWritePost bm-files,bm-dirs silent !shortcuts
+autocmd VimLeave *.tex !dev clean "%"
+" autocmd BufWritePost config.h,config.def.h !cd "%:h"; rm -f config.h; sudo make install
+autocmd BufWritePre * %s/\s\+$//e
+au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
+
+autocmd BufWritePost */Documents/Notes/*.md silent !pandoc % -o "$HOME/Documents/Notes/.out/$(basename % .md).html"
+" autocmd BufWritePost */Documents/latex/resume/resume.tex !cd "%:h"; pdflatex resume.tex; cp -v resume.pdf ~/Dev/vikas.rocks/static/dox/
+autocmd BufWritePost *Xresources silent !xrdb "%"
+autocmd BufRead,BufNewFile *.yt* set filetype=conf
+
+function SourceTemplate()
+ let b:template = glob("${XDG_CONFIG_HOME:-$HOME/.config}/nvim/templates/_default." . expand('%:e'))
+ if !empty(b:template)
+ execute('0r' . b:template)
+ endif
+endfunction
+
+autocmd BufNewFile * call SourceTemplate()
+
+autocmd TermOpen * startinsert
+command! -nargs=* T split | terminal <args>
+
+" --> Scratch buffer
+if exists('g:loaded_scratch')
+ finish
+endif
+let g:loaded_scratch = 1
+command! -nargs=1 -complete=command D call scratch#open(<q-args>, <q-mods>)
+
+" --> Lf
+" let g:lf_command_override = 'lf -command ...'
+let g:NERDTreeHijackNetrw = 0
+" let g:lf_replace_netrw = 1
+let g:lf_width = 1.0
+let g:lf_height = 1.0
+let g:lf_map_keys = 0
+nnoremap <Esc>o :LfCurrentFile<CR>
+nnoremap <Esc>l :LfWorkingDirectory<CR>
+nnoremap <leader>o :LfCurrentFileNewTab<CR>
+nnoremap <leader>l :LfWorkingDirectoryExistingOrNewTab<CR>
+
+if !exists('g:lasttab')
+ let g:lasttab = 1
+endif
+nmap g; :exe "tabn ".g:lasttab<CR>
+au TabLeave * let g:lasttab = tabpagenr()
+nnoremap g1 1gt
+nnoremap g2 2gt
+nnoremap g3 3gt
+nnoremap g4 4gt
+nnoremap g5 5gt
+nnoremap g6 6gt
+nnoremap g7 7gt
+nnoremap g8 8gt
+nnoremap g9 :tablast<CR>
+
+vnoremap <C-c> "*y :let @+=@*<CR>
+vnoremap <C-A-c> "*d :let @+=@*<CR>
+noremap <C-p> "+p
+noremap <C-A-p> "+P
+
+nnoremap c "_c
+inoremap jk <Esc>
+" map ;n /<++><Enter>c4l
+inoremap ;n <Esc>/<++><Enter>c4l
+nnoremap <leader>n /<++><Enter>c4l
+
+autocmd FileType html,markdown inoremap ;s ><Esc>bi<<Esc>ea
+autocmd FileType html,markdown inoremap ;c ><Esc>bi</<Esc>ea
+autocmd FileType html,markdown inoremap ;i <Esc>b"tywi<<Esc>ea></><Esc>PF<i
+autocmd FileType html,markdown inoremap ;I <Esc>b"tywi<<Esc>ea><++></><Esc>P2F>i<Space>
+autocmd FileType html,markdown inoremap ;b <Esc>b"tywi<<Esc>ea><CR></<Esc>"tpa><CR><++><Esc>kO
+autocmd FileType html,markdown inoremap ;B <Esc>b"tywi<<Esc>ea><CR><++><CR></<Esc>"tpa><CR><++><Esc>3k$i<Space>
+autocmd FileType html,markdown inoremap ;ap <p><CR><++><CR></p><CR><++><Esc>3k$i
+autocmd FileType html,markdown inoremap ;aa <a href=""><CR><++><CR></a><CR><++><Esc>3k$hi
+
+autocmd FileType tex inoremap ;b <Esc>b"tywi\begin{<Esc>ea}<CR>\end{<Esc>"tpa}<Esc>kA
+autocmd FileType tex inoremap ;s \section{}<Esc>i
+autocmd FileType tex inoremap ;at \begin{tikzpicture}<CR>\end{tikzpicture}<Esc>O
+autocmd FileType tex inoremap ;ap \usepackage{}<Esc>i
+autocmd FileType tex inoremap ;aP \usepackage[]{}<Esc>F[a
+autocmd FileType tex inoremap ;ab \textbf{}<Esc>i
+autocmd FileType tex inoremap ;ai \textit{}<Esc>i
+autocmd FileType tex inoremap ;au \underline{}<Esc>i
+
+autocmd FileType go inoremap ;ae err<Space>:=<Space><++><CR>if<Space>err<Space>!=<Space>nil<Space>{<CR>return<Space>err<CR>}<Esc>3kI
+
+nnoremap <leader>fl :w<CR>:!dev lint "%"<CR>
+nnoremap <leader>fm :w<CR>:%!dev format "%"<CR>
+nnoremap <leader>fc :w<CR>:!dev compile "%"<CR>
+nnoremap <leader>fe :w<CR>:!dev run "%"<CR>
+nnoremap <leader>ft :w<CR>:!dev test "%"<CR>
+nnoremap <leader>fr :w<CR>:!dev clean "%"<CR>
+
+nnoremap <leader>Fl :w<CR>:T dev lint "%"<CR>
+nnoremap <leader>Fm :w<CR>:T dev format "%"<CR>
+nnoremap <leader>Fc :w<CR>:T dev compile "%"<CR>
+nnoremap <leader>Fe :w<CR>:T dev run "%"<CR>
+nnoremap <leader>Ft :w<CR>:T dev test "%"<CR>
+nnoremap <leader>Fr :w<CR>:T dev clean "%"<CR>
+
+autocmd BufEnter * nmap <leader>t :w<CR>:se nornu<CR>:!dev test "%"<CR>:se rnu<CR>
+autocmd BufEnter * nmap <leader>T :w<CR>:se nornu<CR>:T dev test "%"<CR>
+autocmd BufEnter * imap <F5> <Esc>:w<CR>:se nornu<CR>:T dev test "%"<CR>
+
+autocmd BufEnter vartak-results-data.pl nmap <leader>t :w<CR>:se nornu<CR>:!vartak-results-data.pl ~/GDrive/vartak/results/university/1S002557.pdf<CR>:se rnu<CR>
+
+nnoremap <leader>w :set wrap!<CR>
+nnoremap <leader>fo :!opout "%:p"<CR>
+nnoremap <leader>ec :tabnew ~/.config/nvim/init.vim<CR>
+nnoremap <leader><C-r> :source ~/.config/nvim/init.vim<CR>
+nnoremap <leader>s :%s//gc<Left><Left><Left>
+nnoremap <leader>r :w<CR>:!%:p<CR>
+nnoremap <leader>R :w<CR>:T %:p<CR>
+
+nnoremap <leader>gc :T git add --all && git commit<CR>
+
+let shortcuts = config_dir . "shortcuts.vim"
+if filereadable(shortcuts)
+ execute "source " . shortcuts
+endif
diff --git a/.config/nvim/onedark.vim b/.config/nvim/onedark.vim
new file mode 100644
index 0000000..6769d6c
--- /dev/null
+++ b/.config/nvim/onedark.vim
@@ -0,0 +1,713 @@
+" vim:fdm=marker
+" Vim Color File
+" Name: onedark.vim
+" Maintainer: https://github.com/joshdick/onedark.vim/
+" License: The MIT License (MIT)
+" Based On: https://github.com/MaxSt/FlatColor/
+
+" Companion statusline plugin and terminal themes are included with onedark.vim:
+" * https://github.com/joshdick/onedark.vim#lightlinevim-colorscheme
+" * https://github.com/joshdick/onedark.vim#vim-airline-theme
+" * https://github.com/joshdick/onedark.vim/tree/main/term
+
+" Color Reference {{{
+
+" The following colors were measured inside Atom using its built-in inspector.
+
+" +---------------------------------------------+
+" | Color Name | RGB | Hex |
+" |--------------+--------------------+---------|
+" | Black | rgb(40, 44, 52) | #282c34 |
+" |--------------+--------------------+---------|
+" | White | rgb(171, 178, 191) | #abb2bf |
+" |--------------+--------------------+---------|
+" | Light Red | rgb(224, 108, 117) | #e06c75 |
+" |--------------+--------------------+---------|
+" | Dark Red | rgb(190, 80, 70) | #be5046 |
+" |--------------+--------------------+---------|
+" | Green | rgb(152, 195, 121) | #98c379 |
+" |--------------+--------------------+---------|
+" | Light Yellow | rgb(229, 192, 123) | #e5c07b |
+" |--------------+--------------------+---------|
+" | Dark Yellow | rgb(209, 154, 102) | #d19a66 |
+" |--------------+--------------------+---------|
+" | Blue | rgb(97, 175, 239) | #61afef |
+" |--------------+--------------------+---------|
+" | Magenta | rgb(198, 120, 221) | #c678dd |
+" |--------------+--------------------+---------|
+" | Cyan | rgb(86, 182, 194) | #56b6c2 |
+" |--------------+--------------------+---------|
+" | Gutter Grey | rgb(76, 82, 99) | #4b5263 |
+" |--------------+--------------------+---------|
+" | Comment Grey | rgb(92, 99, 112) | #5c6370 |
+" +---------------------------------------------+
+
+" }}}
+
+" Initialization {{{
+
+highlight clear
+
+if exists("syntax_on")
+ syntax reset
+endif
+
+set t_Co=256
+
+let g:colors_name="onedark"
+
+" Set to "256" for 256-color terminals, or
+" set to "16" to use your terminal emulator's native colors
+" (a 16-color palette for this color scheme is available; see
+" < https://github.com/joshdick/onedark.vim/blob/main/README.md >
+" for more information.)
+if !exists("g:onedark_termcolors")
+ let g:onedark_termcolors = 256
+endif
+
+" Not all terminals support italics properly. If yours does, opt-in.
+if !exists("g:onedark_terminal_italics")
+ let g:onedark_terminal_italics = 0
+endif
+
+" This function is based on one from FlatColor: https://github.com/MaxSt/FlatColor/
+" Which in turn was based on one found in hemisu: https://github.com/noahfrederick/vim-hemisu/
+let s:group_colors = {} " Cache of default highlight group settings, for later reference via `onedark#extend_highlight`
+function! s:h(group, style, ...)
+ if (a:0 > 0) " Will be true if we got here from onedark#extend_highlight
+ let s:highlight = s:group_colors[a:group]
+ for style_type in ["fg", "bg", "sp"]
+ if (has_key(a:style, style_type))
+ let l:default_style = (has_key(s:highlight, style_type) ? copy(s:highlight[style_type]) : { "cterm16": "NONE", "cterm": "NONE", "gui": "NONE" })
+ let s:highlight[style_type] = extend(l:default_style, a:style[style_type])
+ endif
+ endfor
+ if (has_key(a:style, "gui"))
+ let s:highlight.gui = a:style.gui
+ endif
+ if (has_key(a:style, "cterm"))
+ let s:highlight.cterm = a:style.cterm
+ endif
+ else
+ let s:highlight = a:style
+ let s:group_colors[a:group] = s:highlight " Cache default highlight group settings
+ endif
+
+ if g:onedark_terminal_italics == 0
+ if has_key(s:highlight, "cterm") && s:highlight["cterm"] == "italic"
+ unlet s:highlight.cterm
+ endif
+ if has_key(s:highlight, "gui") && s:highlight["gui"] == "italic"
+ unlet s:highlight.gui
+ endif
+ endif
+
+ if g:onedark_termcolors == 16
+ let l:ctermfg = (has_key(s:highlight, "fg") ? s:highlight.fg.cterm16 : "NONE")
+ let l:ctermbg = (has_key(s:highlight, "bg") ? s:highlight.bg.cterm16 : "NONE")
+ else
+ let l:ctermfg = (has_key(s:highlight, "fg") ? s:highlight.fg.cterm : "NONE")
+ let l:ctermbg = (has_key(s:highlight, "bg") ? s:highlight.bg.cterm : "NONE")
+ endif
+
+ execute "highlight" a:group
+ \ "guifg=" (has_key(s:highlight, "fg") ? s:highlight.fg.gui : "NONE")
+ \ "guibg=" (has_key(s:highlight, "bg") ? s:highlight.bg.gui : "NONE")
+ \ "guisp=" (has_key(s:highlight, "sp") ? s:highlight.sp.gui : "NONE")
+ \ "gui=" (has_key(s:highlight, "gui") ? s:highlight.gui : "NONE")
+ \ "ctermfg=" . l:ctermfg
+ \ "ctermbg=" . l:ctermbg
+ \ "cterm=" (has_key(s:highlight, "cterm") ? s:highlight.cterm : "NONE")
+endfunction
+
+" public {{{
+
+function! onedark#set_highlight(group, style)
+ call s:h(a:group, a:style)
+endfunction
+
+function! onedark#extend_highlight(group, style)
+ call s:h(a:group, a:style, 1)
+endfunction
+
+" }}}
+
+" }}}
+
+" Color Variables {{{
+
+let s:colors = onedark#GetColors()
+
+let s:red = s:colors.red
+let s:dark_red = s:colors.dark_red
+let s:green = s:colors.green
+let s:yellow = s:colors.yellow
+let s:dark_yellow = s:colors.dark_yellow
+let s:blue = s:colors.blue
+let s:purple = s:colors.purple
+let s:cyan = s:colors.cyan
+let s:white = s:colors.white
+let s:black = s:colors.black
+let s:foreground = s:colors.foreground
+let s:background = s:colors.background
+let s:comment_grey = s:colors.comment_grey
+let s:gutter_fg_grey = s:colors.gutter_fg_grey
+let s:cursor_grey = s:colors.cursor_grey
+let s:visual_grey = s:colors.visual_grey
+let s:menu_grey = s:colors.menu_grey
+let s:special_grey = s:colors.special_grey
+let s:vertsplit = s:colors.vertsplit
+
+" }}}
+
+" Terminal Colors {{{
+
+if has('nvim')
+ let g:terminal_color_0 = s:black.gui
+ let g:terminal_color_1 = s:red.gui
+ let g:terminal_color_2 = s:green.gui
+ let g:terminal_color_3 = s:yellow.gui
+ let g:terminal_color_4 = s:blue.gui
+ let g:terminal_color_5 = s:purple.gui
+ let g:terminal_color_6 = s:cyan.gui
+ let g:terminal_color_7 = s:comment_grey.gui
+ let g:terminal_color_8 = s:visual_grey.gui
+ let g:terminal_color_9 = s:red.gui
+ let g:terminal_color_10 = s:green.gui
+ let g:terminal_color_11 = s:yellow.gui
+ let g:terminal_color_12 = s:blue.gui
+ let g:terminal_color_13 = s:purple.gui
+ let g:terminal_color_14 = s:cyan.gui
+ let g:terminal_color_15 = s:white.gui
+else
+ let g:terminal_ansi_colors = [
+ \ s:black.gui, s:red.gui, s:green.gui, s:yellow.gui,
+ \ s:blue.gui, s:purple.gui, s:cyan.gui, s:comment_grey.gui,
+ \ s:visual_grey.gui, s:red.gui, s:green.gui, s:yellow.gui,
+ \ s:blue.gui, s:purple.gui, s:cyan.gui, s:white.gui
+ \]
+endif
+
+" }}}
+
+" Syntax Groups (descriptions and ordering from `:h w18`) {{{
+
+call s:h("Comment", { "fg": s:comment_grey, "gui": "italic", "cterm": "italic" }) " any comment
+call s:h("Constant", { "fg": s:cyan }) " any constant
+call s:h("String", { "fg": s:green }) " a string constant: "this is a string"
+call s:h("Character", { "fg": s:green }) " a character constant: 'c', '\n'
+call s:h("Number", { "fg": s:dark_yellow }) " a number constant: 234, 0xff
+call s:h("Boolean", { "fg": s:dark_yellow }) " a boolean constant: TRUE, false
+call s:h("Float", { "fg": s:dark_yellow }) " a floating point constant: 2.3e10
+call s:h("Identifier", { "fg": s:red }) " any variable name
+call s:h("Function", { "fg": s:blue }) " function name (also: methods for classes)
+call s:h("Statement", { "fg": s:purple }) " any statement
+call s:h("Conditional", { "fg": s:purple }) " if, then, else, endif, switch, etc.
+call s:h("Repeat", { "fg": s:purple }) " for, do, while, etc.
+call s:h("Label", { "fg": s:purple }) " case, default, etc.
+call s:h("Operator", { "fg": s:purple }) " sizeof", "+", "*", etc.
+call s:h("Keyword", { "fg": s:purple }) " any other keyword
+call s:h("Exception", { "fg": s:purple }) " try, catch, throw
+call s:h("PreProc", { "fg": s:yellow }) " generic Preprocessor
+call s:h("Include", { "fg": s:blue }) " preprocessor #include
+call s:h("Define", { "fg": s:purple }) " preprocessor #define
+call s:h("Macro", { "fg": s:purple }) " same as Define
+call s:h("PreCondit", { "fg": s:yellow }) " preprocessor #if, #else, #endif, etc.
+call s:h("Type", { "fg": s:yellow }) " int, long, char, etc.
+call s:h("StorageClass", { "fg": s:yellow }) " static, register, volatile, etc.
+call s:h("Structure", { "fg": s:yellow }) " struct, union, enum, etc.
+call s:h("Typedef", { "fg": s:yellow }) " A typedef
+call s:h("Special", { "fg": s:blue }) " any special symbol
+call s:h("SpecialChar", { "fg": s:dark_yellow }) " special character in a constant
+call s:h("Tag", {}) " you can use CTRL-] on this
+call s:h("Delimiter", {}) " character that needs attention
+call s:h("SpecialComment", { "fg": s:comment_grey }) " special things inside a comment
+call s:h("Debug", {}) " debugging statements
+call s:h("Underlined", { "gui": "underline", "cterm": "underline" }) " text that stands out, HTML links
+call s:h("Ignore", {}) " left blank, hidden
+call s:h("Error", { "fg": s:red }) " any erroneous construct
+call s:h("Todo", { "fg": s:purple }) " anything that needs extra attention; mostly the keywords TODO FIXME and XXX
+
+" }}}
+
+" Highlighting Groups (descriptions and ordering from `:h highlight-groups`) {{{
+call s:h("ColorColumn", { "bg": s:cursor_grey }) " used for the columns set with 'colorcolumn'
+call s:h("Conceal", {}) " placeholder characters substituted for concealed text (see 'conceallevel')
+call s:h("Cursor", { "fg": s:black, "bg": s:blue }) " the character under the cursor
+call s:h("CursorIM", {}) " like Cursor, but used when in IME mode
+call s:h("CursorColumn", { "bg": s:cursor_grey }) " the screen column that the cursor is in when 'cursorcolumn' is set
+if &diff
+ " Don't change the background color in diff mode
+ call s:h("CursorLine", { "gui": "underline" }) " the screen line that the cursor is in when 'cursorline' is set
+else
+ call s:h("CursorLine", { "bg": s:cursor_grey }) " the screen line that the cursor is in when 'cursorline' is set
+endif
+call s:h("Directory", { "fg": s:blue }) " directory names (and other special names in listings)
+call s:h("DiffAdd", { "bg": s:green, "fg": s:black }) " diff mode: Added line
+call s:h("DiffChange", { "fg": s:yellow, "gui": "underline", "cterm": "underline" }) " diff mode: Changed line
+call s:h("DiffDelete", { "bg": s:red, "fg": s:black }) " diff mode: Deleted line
+call s:h("DiffText", { "bg": s:yellow, "fg": s:black }) " diff mode: Changed text within a changed line
+if get(g:, 'onedark_hide_endofbuffer', 0)
+ " If enabled, will style end-of-buffer filler lines (~) to appear to be hidden.
+ call s:h("EndOfBuffer", { "fg": s:black }) " filler lines (~) after the last line in the buffer
+endif
+call s:h("ErrorMsg", { "fg": s:red }) " error messages on the command line
+call s:h("VertSplit", { "fg": s:vertsplit }) " the column separating vertically split windows
+call s:h("Folded", { "fg": s:comment_grey }) " line used for closed folds
+call s:h("FoldColumn", {}) " 'foldcolumn'
+call s:h("SignColumn", {}) " column where signs are displayed
+call s:h("IncSearch", { "fg": s:yellow, "bg": s:comment_grey }) " 'incsearch' highlighting; also used for the text replaced with ":s///c"
+call s:h("LineNr", { "fg": s:gutter_fg_grey }) " Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set.
+call s:h("CursorLineNr", {}) " Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line.
+call s:h("MatchParen", { "fg": s:blue, "gui": "underline", "cterm": "underline" }) " The character under the cursor or just before it, if it is a paired bracket, and its match.
+call s:h("ModeMsg", {}) " 'showmode' message (e.g., "-- INSERT --")
+call s:h("MoreMsg", {}) " more-prompt
+call s:h("NonText", { "fg": s:special_grey }) " '~' and '@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., ">" displayed when a double-wide character doesn't fit at the end of the line).
+call s:h("Normal", { "fg": s:foreground, "bg": s:background }) " normal text
+call s:h("Pmenu", { "fg": s:white, "bg": s:menu_grey }) " Popup menu: normal item.
+call s:h("PmenuSel", { "fg": s:cursor_grey, "bg": s:blue }) " Popup menu: selected item.
+call s:h("PmenuSbar", { "bg": s:cursor_grey }) " Popup menu: scrollbar.
+call s:h("PmenuThumb", { "bg": s:white }) " Popup menu: Thumb of the scrollbar.
+call s:h("Question", { "fg": s:purple }) " hit-enter prompt and yes/no questions
+call s:h("QuickFixLine", { "fg": s:black, "bg": s:yellow }) " Current quickfix item in the quickfix window.
+call s:h("Search", { "fg": s:black, "bg": s:yellow }) " Last search pattern highlighting (see 'hlsearch'). Also used for similar items that need to stand out.
+call s:h("SpecialKey", { "fg": s:special_grey }) " Meta and special keys listed with ":map", also for text used to show unprintable characters in the text, 'listchars'. Generally: text that is displayed differently from what it really is.
+call s:h("SpellBad", { "fg": s:red, "gui": "underline", "cterm": "underline" }) " Word that is not recognized by the spellchecker. This will be combined with the highlighting used otherwise.
+call s:h("SpellCap", { "fg": s:dark_yellow }) " Word that should start with a capital. This will be combined with the highlighting used otherwise.
+call s:h("SpellLocal", { "fg": s:dark_yellow }) " Word that is recognized by the spellchecker as one that is used in another region. This will be combined with the highlighting used otherwise.
+call s:h("SpellRare", { "fg": s:dark_yellow }) " Word that is recognized by the spellchecker as one that is hardly ever used. spell This will be combined with the highlighting used otherwise.
+call s:h("StatusLine", { "fg": s:white, "bg": s:cursor_grey }) " status line of current window
+call s:h("StatusLineNC", { "fg": s:comment_grey }) " status lines of not-current windows Note: if this is equal to "StatusLine" Vim will use "^^^" in the status line of the current window.
+call s:h("StatusLineTerm", { "fg": s:white, "bg": s:cursor_grey }) " status line of current :terminal window
+call s:h("StatusLineTermNC", { "fg": s:comment_grey }) " status line of non-current :terminal window
+call s:h("TabLine", { "fg": s:comment_grey }) " tab pages line, not active tab page label
+call s:h("TabLineFill", {}) " tab pages line, where there are no labels
+call s:h("TabLineSel", { "fg": s:white }) " tab pages line, active tab page label
+call s:h("Terminal", { "fg": s:white, "bg": s:black }) " terminal window (see terminal-size-color)
+call s:h("Title", { "fg": s:green }) " titles for output from ":set all", ":autocmd" etc.
+call s:h("Visual", { "bg": s:visual_grey }) " Visual mode selection
+call s:h("VisualNOS", { "bg": s:visual_grey }) " Visual mode selection when vim is "Not Owning the Selection". Only X11 Gui's gui-x11 and xterm-clipboard supports this.
+call s:h("WarningMsg", { "fg": s:yellow }) " warning messages
+call s:h("WildMenu", { "fg": s:black, "bg": s:blue }) " current match in 'wildmenu' completion
+
+" }}}
+
+" Termdebug highlighting for Vim 8.1+ {{{
+
+" See `:h hl-debugPC` and `:h hl-debugBreakpoint`.
+call s:h("debugPC", { "bg": s:special_grey }) " the current position
+call s:h("debugBreakpoint", { "fg": s:black, "bg": s:red }) " a breakpoint
+
+" }}}
+
+" Language-Specific Highlighting {{{
+
+" CSS
+call s:h("cssAttrComma", { "fg": s:purple })
+call s:h("cssAttributeSelector", { "fg": s:green })
+call s:h("cssBraces", { "fg": s:white })
+call s:h("cssClassName", { "fg": s:dark_yellow })
+call s:h("cssClassNameDot", { "fg": s:dark_yellow })
+call s:h("cssDefinition", { "fg": s:purple })
+call s:h("cssFontAttr", { "fg": s:dark_yellow })
+call s:h("cssFontDescriptor", { "fg": s:purple })
+call s:h("cssFunctionName", { "fg": s:blue })
+call s:h("cssIdentifier", { "fg": s:blue })
+call s:h("cssImportant", { "fg": s:purple })
+call s:h("cssInclude", { "fg": s:white })
+call s:h("cssIncludeKeyword", { "fg": s:purple })
+call s:h("cssMediaType", { "fg": s:dark_yellow })
+call s:h("cssProp", { "fg": s:white })
+call s:h("cssPseudoClassId", { "fg": s:dark_yellow })
+call s:h("cssSelectorOp", { "fg": s:purple })
+call s:h("cssSelectorOp2", { "fg": s:purple })
+call s:h("cssTagName", { "fg": s:red })
+
+" Fish Shell
+call s:h("fishKeyword", { "fg": s:purple })
+call s:h("fishConditional", { "fg": s:purple })
+
+" Go
+call s:h("goDeclaration", { "fg": s:purple })
+call s:h("goBuiltins", { "fg": s:cyan })
+call s:h("goFunctionCall", { "fg": s:blue })
+call s:h("goVarDefs", { "fg": s:red })
+call s:h("goVarAssign", { "fg": s:red })
+call s:h("goVar", { "fg": s:purple })
+call s:h("goConst", { "fg": s:purple })
+call s:h("goType", { "fg": s:yellow })
+call s:h("goTypeName", { "fg": s:yellow })
+call s:h("goDeclType", { "fg": s:cyan })
+call s:h("goTypeDecl", { "fg": s:purple })
+
+" HTML (keep consistent with Markdown, below)
+call s:h("htmlArg", { "fg": s:dark_yellow })
+call s:h("htmlBold", { "fg": s:dark_yellow, "gui": "bold", "cterm": "bold" })
+call s:h("htmlBoldItalic", { "fg": s:green, "gui": "bold,italic", "cterm": "bold,italic" })
+call s:h("htmlEndTag", { "fg": s:white })
+call s:h("htmlH1", { "fg": s:red })
+call s:h("htmlH2", { "fg": s:red })
+call s:h("htmlH3", { "fg": s:red })
+call s:h("htmlH4", { "fg": s:red })
+call s:h("htmlH5", { "fg": s:red })
+call s:h("htmlH6", { "fg": s:red })
+call s:h("htmlItalic", { "fg": s:purple, "gui": "italic", "cterm": "italic" })
+call s:h("htmlLink", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+call s:h("htmlSpecialChar", { "fg": s:dark_yellow })
+call s:h("htmlSpecialTagName", { "fg": s:red })
+call s:h("htmlTag", { "fg": s:white })
+call s:h("htmlTagN", { "fg": s:red })
+call s:h("htmlTagName", { "fg": s:red })
+call s:h("htmlTitle", { "fg": s:white })
+
+" JavaScript
+call s:h("javaScriptBraces", { "fg": s:white })
+call s:h("javaScriptFunction", { "fg": s:purple })
+call s:h("javaScriptIdentifier", { "fg": s:purple })
+call s:h("javaScriptNull", { "fg": s:dark_yellow })
+call s:h("javaScriptNumber", { "fg": s:dark_yellow })
+call s:h("javaScriptRequire", { "fg": s:cyan })
+call s:h("javaScriptReserved", { "fg": s:purple })
+" https://github.com/pangloss/vim-javascript
+call s:h("jsArrowFunction", { "fg": s:purple })
+call s:h("jsClassKeyword", { "fg": s:purple })
+call s:h("jsClassMethodType", { "fg": s:purple })
+call s:h("jsDocParam", { "fg": s:blue })
+call s:h("jsDocTags", { "fg": s:purple })
+call s:h("jsExport", { "fg": s:purple })
+call s:h("jsExportDefault", { "fg": s:purple })
+call s:h("jsExtendsKeyword", { "fg": s:purple })
+call s:h("jsFrom", { "fg": s:purple })
+call s:h("jsFuncCall", { "fg": s:blue })
+call s:h("jsFunction", { "fg": s:purple })
+call s:h("jsGenerator", { "fg": s:yellow })
+call s:h("jsGlobalObjects", { "fg": s:yellow })
+call s:h("jsImport", { "fg": s:purple })
+call s:h("jsModuleAs", { "fg": s:purple })
+call s:h("jsModuleWords", { "fg": s:purple })
+call s:h("jsModules", { "fg": s:purple })
+call s:h("jsNull", { "fg": s:dark_yellow })
+call s:h("jsOperator", { "fg": s:purple })
+call s:h("jsStorageClass", { "fg": s:purple })
+call s:h("jsSuper", { "fg": s:red })
+call s:h("jsTemplateBraces", { "fg": s:dark_red })
+call s:h("jsTemplateVar", { "fg": s:green })
+call s:h("jsThis", { "fg": s:red })
+call s:h("jsUndefined", { "fg": s:dark_yellow })
+" https://github.com/othree/yajs.vim
+call s:h("javascriptArrowFunc", { "fg": s:purple })
+call s:h("javascriptClassExtends", { "fg": s:purple })
+call s:h("javascriptClassKeyword", { "fg": s:purple })
+call s:h("javascriptDocNotation", { "fg": s:purple })
+call s:h("javascriptDocParamName", { "fg": s:blue })
+call s:h("javascriptDocTags", { "fg": s:purple })
+call s:h("javascriptEndColons", { "fg": s:white })
+call s:h("javascriptExport", { "fg": s:purple })
+call s:h("javascriptFuncArg", { "fg": s:white })
+call s:h("javascriptFuncKeyword", { "fg": s:purple })
+call s:h("javascriptIdentifier", { "fg": s:red })
+call s:h("javascriptImport", { "fg": s:purple })
+call s:h("javascriptMethodName", { "fg": s:white })
+call s:h("javascriptObjectLabel", { "fg": s:white })
+call s:h("javascriptOpSymbol", { "fg": s:cyan })
+call s:h("javascriptOpSymbols", { "fg": s:cyan })
+call s:h("javascriptPropertyName", { "fg": s:green })
+call s:h("javascriptTemplateSB", { "fg": s:dark_red })
+call s:h("javascriptVariable", { "fg": s:purple })
+
+" JSON
+call s:h("jsonCommentError", { "fg": s:white })
+call s:h("jsonKeyword", { "fg": s:red })
+call s:h("jsonBoolean", { "fg": s:dark_yellow })
+call s:h("jsonNumber", { "fg": s:dark_yellow })
+call s:h("jsonQuote", { "fg": s:white })
+call s:h("jsonMissingCommaError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonNoQuotesError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonNumError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonString", { "fg": s:green })
+call s:h("jsonStringSQError", { "fg": s:red, "gui": "reverse" })
+call s:h("jsonSemicolonError", { "fg": s:red, "gui": "reverse" })
+
+" LESS
+call s:h("lessVariable", { "fg": s:purple })
+call s:h("lessAmpersandChar", { "fg": s:white })
+call s:h("lessClass", { "fg": s:dark_yellow })
+
+" Markdown (keep consistent with HTML, above)
+call s:h("markdownBlockquote", { "fg": s:comment_grey })
+call s:h("markdownBold", { "fg": s:dark_yellow, "gui": "bold", "cterm": "bold" })
+call s:h("markdownBoldItalic", { "fg": s:green, "gui": "bold,italic", "cterm": "bold,italic" })
+call s:h("markdownCode", { "fg": s:green })
+call s:h("markdownCodeBlock", { "fg": s:green })
+call s:h("markdownCodeDelimiter", { "fg": s:green })
+call s:h("markdownH1", { "fg": s:red })
+call s:h("markdownH2", { "fg": s:red })
+call s:h("markdownH3", { "fg": s:red })
+call s:h("markdownH4", { "fg": s:red })
+call s:h("markdownH5", { "fg": s:red })
+call s:h("markdownH6", { "fg": s:red })
+call s:h("markdownHeadingDelimiter", { "fg": s:red })
+call s:h("markdownHeadingRule", { "fg": s:comment_grey })
+call s:h("markdownId", { "fg": s:purple })
+call s:h("markdownIdDeclaration", { "fg": s:blue })
+call s:h("markdownIdDelimiter", { "fg": s:purple })
+call s:h("markdownItalic", { "fg": s:purple, "gui": "italic", "cterm": "italic" })
+call s:h("markdownLinkDelimiter", { "fg": s:purple })
+call s:h("markdownLinkText", { "fg": s:blue })
+call s:h("markdownListMarker", { "fg": s:red })
+call s:h("markdownOrderedListMarker", { "fg": s:red })
+call s:h("markdownRule", { "fg": s:comment_grey })
+call s:h("markdownUrl", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+
+" Perl
+call s:h("perlFiledescRead", { "fg": s:green })
+call s:h("perlFunction", { "fg": s:purple })
+call s:h("perlMatchStartEnd",{ "fg": s:blue })
+call s:h("perlMethod", { "fg": s:purple })
+call s:h("perlPOD", { "fg": s:comment_grey })
+call s:h("perlSharpBang", { "fg": s:comment_grey })
+call s:h("perlSpecialString",{ "fg": s:dark_yellow })
+call s:h("perlStatementFiledesc", { "fg": s:red })
+call s:h("perlStatementFlow",{ "fg": s:red })
+call s:h("perlStatementInclude", { "fg": s:purple })
+call s:h("perlStatementScalar",{ "fg": s:purple })
+call s:h("perlStatementStorage", { "fg": s:purple })
+call s:h("perlSubName",{ "fg": s:yellow })
+call s:h("perlVarPlain",{ "fg": s:blue })
+
+" PHP
+call s:h("phpVarSelector", { "fg": s:red })
+call s:h("phpOperator", { "fg": s:white })
+call s:h("phpParent", { "fg": s:white })
+call s:h("phpMemberSelector", { "fg": s:white })
+call s:h("phpType", { "fg": s:purple })
+call s:h("phpKeyword", { "fg": s:purple })
+call s:h("phpClass", { "fg": s:yellow })
+call s:h("phpUseClass", { "fg": s:white })
+call s:h("phpUseAlias", { "fg": s:white })
+call s:h("phpInclude", { "fg": s:purple })
+call s:h("phpClassExtends", { "fg": s:green })
+call s:h("phpDocTags", { "fg": s:white })
+call s:h("phpFunction", { "fg": s:blue })
+call s:h("phpFunctions", { "fg": s:cyan })
+call s:h("phpMethodsVar", { "fg": s:dark_yellow })
+call s:h("phpMagicConstants", { "fg": s:dark_yellow })
+call s:h("phpSuperglobals", { "fg": s:red })
+call s:h("phpConstants", { "fg": s:dark_yellow })
+
+" Ruby
+call s:h("rubyBlockParameter", { "fg": s:red})
+call s:h("rubyBlockParameterList", { "fg": s:red })
+call s:h("rubyClass", { "fg": s:purple})
+call s:h("rubyConstant", { "fg": s:yellow})
+call s:h("rubyControl", { "fg": s:purple })
+call s:h("rubyEscape", { "fg": s:red})
+call s:h("rubyFunction", { "fg": s:blue})
+call s:h("rubyGlobalVariable", { "fg": s:red})
+call s:h("rubyInclude", { "fg": s:blue})
+call s:h("rubyIncluderubyGlobalVariable", { "fg": s:red})
+call s:h("rubyInstanceVariable", { "fg": s:red})
+call s:h("rubyInterpolation", { "fg": s:cyan })
+call s:h("rubyInterpolationDelimiter", { "fg": s:red })
+call s:h("rubyInterpolationDelimiter", { "fg": s:red})
+call s:h("rubyRegexp", { "fg": s:cyan})
+call s:h("rubyRegexpDelimiter", { "fg": s:cyan})
+call s:h("rubyStringDelimiter", { "fg": s:green})
+call s:h("rubySymbol", { "fg": s:cyan})
+
+" Sass
+" https://github.com/tpope/vim-haml
+call s:h("sassAmpersand", { "fg": s:red })
+call s:h("sassClass", { "fg": s:dark_yellow })
+call s:h("sassControl", { "fg": s:purple })
+call s:h("sassExtend", { "fg": s:purple })
+call s:h("sassFor", { "fg": s:white })
+call s:h("sassFunction", { "fg": s:cyan })
+call s:h("sassId", { "fg": s:blue })
+call s:h("sassInclude", { "fg": s:purple })
+call s:h("sassMedia", { "fg": s:purple })
+call s:h("sassMediaOperators", { "fg": s:white })
+call s:h("sassMixin", { "fg": s:purple })
+call s:h("sassMixinName", { "fg": s:blue })
+call s:h("sassMixing", { "fg": s:purple })
+call s:h("sassVariable", { "fg": s:purple })
+" https://github.com/cakebaker/scss-syntax.vim
+call s:h("scssExtend", { "fg": s:purple })
+call s:h("scssImport", { "fg": s:purple })
+call s:h("scssInclude", { "fg": s:purple })
+call s:h("scssMixin", { "fg": s:purple })
+call s:h("scssSelectorName", { "fg": s:dark_yellow })
+call s:h("scssVariable", { "fg": s:purple })
+
+" TeX
+call s:h("texStatement", { "fg": s:purple })
+call s:h("texSubscripts", { "fg": s:dark_yellow })
+call s:h("texSuperscripts", { "fg": s:dark_yellow })
+call s:h("texTodo", { "fg": s:dark_red })
+call s:h("texBeginEnd", { "fg": s:purple })
+call s:h("texBeginEndName", { "fg": s:blue })
+call s:h("texMathMatcher", { "fg": s:blue })
+call s:h("texMathDelim", { "fg": s:blue })
+call s:h("texDelimiter", { "fg": s:dark_yellow })
+call s:h("texSpecialChar", { "fg": s:dark_yellow })
+call s:h("texCite", { "fg": s:blue })
+call s:h("texRefZone", { "fg": s:blue })
+
+" TypeScript
+call s:h("typescriptReserved", { "fg": s:purple })
+call s:h("typescriptEndColons", { "fg": s:white })
+call s:h("typescriptBraces", { "fg": s:white })
+
+" XML
+call s:h("xmlAttrib", { "fg": s:dark_yellow })
+call s:h("xmlEndTag", { "fg": s:red })
+call s:h("xmlTag", { "fg": s:red })
+call s:h("xmlTagName", { "fg": s:red })
+
+" }}}
+
+" Plugin Highlighting {{{
+
+" airblade/vim-gitgutter
+call s:h("GitGutterAdd", { "fg": s:green })
+call s:h("GitGutterChange", { "fg": s:yellow })
+call s:h("GitGutterDelete", { "fg": s:red })
+
+" dense-analysis/ale
+call s:h("ALEError", { "fg": s:red, "gui": "underline", "cterm": "underline" })
+call s:h("ALEWarning", { "fg": s:yellow, "gui": "underline", "cterm": "underline" })
+call s:h("ALEInfo", { "gui": "underline", "cterm": "underline" })
+call s:h("ALEErrorSign", { "fg": s:red })
+call s:h("ALEWarningSign", { "fg": s:yellow })
+call s:h("ALEInfoSign", { })
+
+" easymotion/vim-easymotion
+call s:h("EasyMotionTarget", { "fg": s:red, "gui": "bold", "cterm": "bold" })
+call s:h("EasyMotionTarget2First", { "fg": s:yellow, "gui": "bold", "cterm": "bold" })
+call s:h("EasyMotionTarget2Second", { "fg": s:dark_yellow, "gui": "bold", "cterm": "bold" })
+call s:h("EasyMotionShade", { "fg": s:comment_grey })
+
+" lewis6991/gitsigns.nvim
+hi link GitSignsAdd GitGutterAdd
+hi link GitSignsChange GitGutterChange
+hi link GitSignsDelete GitGutterDelete
+
+" mhinz/vim-signify
+hi link SignifySignAdd GitGutterAdd
+hi link SignifySignChange GitGutterChange
+hi link SignifySignDelete GitGutterDelete
+
+" neoclide/coc.nvim
+call s:h("CocErrorSign", { "fg": s:red })
+call s:h("CocWarningSign", { "fg": s:yellow })
+call s:h("CocInfoSign", { "fg": s:blue })
+call s:h("CocHintSign", { "fg": s:cyan })
+call s:h("CocFadeOut", { "fg": s:comment_grey })
+" https://github.com/joshdick/onedark.vim/issues/313
+highlight! link CocMenuSel PmenuSel
+
+" neomake/neomake
+call s:h("NeomakeErrorSign", { "fg": s:red })
+call s:h("NeomakeWarningSign", { "fg": s:yellow })
+call s:h("NeomakeInfoSign", { "fg": s:blue })
+
+" plasticboy/vim-markdown (keep consistent with Markdown, above)
+call s:h("mkdDelimiter", { "fg": s:purple })
+call s:h("mkdHeading", { "fg": s:red })
+call s:h("mkdLink", { "fg": s:blue })
+call s:h("mkdURL", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+
+" prabirshrestha/vim-lsp
+call s:h("LspErrorText", { "fg": s:red })
+call s:h("LspWarningText", { "fg": s:yellow })
+call s:h("LspInformationText", { "fg":s:blue })
+call s:h("LspHintText", { "fg":s:cyan })
+call s:h("LspErrorHighlight", { "fg": s:red, "gui": "underline", "cterm": "underline" })
+call s:h("LspWarningHighlight", { "fg": s:yellow, "gui": "underline", "cterm": "underline" })
+call s:h("LspInformationHighlight", { "fg":s:blue, "gui": "underline", "cterm": "underline" })
+call s:h("LspHintHighlight", { "fg":s:cyan, "gui": "underline", "cterm": "underline" })
+
+" tpope/vim-fugitive
+call s:h("diffAdded", { "fg": s:green })
+call s:h("diffRemoved", { "fg": s:red })
+
+" }}}
+
+" Git Highlighting {{{
+
+call s:h("gitcommitComment", { "fg": s:comment_grey })
+call s:h("gitcommitUnmerged", { "fg": s:green })
+call s:h("gitcommitOnBranch", {})
+call s:h("gitcommitBranch", { "fg": s:purple })
+call s:h("gitcommitDiscardedType", { "fg": s:red })
+call s:h("gitcommitSelectedType", { "fg": s:green })
+call s:h("gitcommitHeader", {})
+call s:h("gitcommitUntrackedFile", { "fg": s:cyan })
+call s:h("gitcommitDiscardedFile", { "fg": s:red })
+call s:h("gitcommitSelectedFile", { "fg": s:green })
+call s:h("gitcommitUnmergedFile", { "fg": s:yellow })
+call s:h("gitcommitFile", {})
+call s:h("gitcommitSummary", { "fg": s:white })
+call s:h("gitcommitOverflow", { "fg": s:red })
+hi link gitcommitNoBranch gitcommitBranch
+hi link gitcommitUntracked gitcommitComment
+hi link gitcommitDiscarded gitcommitComment
+hi link gitcommitSelected gitcommitComment
+hi link gitcommitDiscardedArrow gitcommitDiscardedFile
+hi link gitcommitSelectedArrow gitcommitSelectedFile
+hi link gitcommitUnmergedArrow gitcommitUnmergedFile
+
+" }}}
+
+" Neovim-Specific Highlighting {{{
+
+if has("nvim")
+ " Neovim terminal colors {{{
+ let g:terminal_color_0 = s:black.gui
+ let g:terminal_color_1 = s:red.gui
+ let g:terminal_color_2 = s:green.gui
+ let g:terminal_color_3 = s:yellow.gui
+ let g:terminal_color_4 = s:blue.gui
+ let g:terminal_color_5 = s:purple.gui
+ let g:terminal_color_6 = s:cyan.gui
+ let g:terminal_color_7 = s:white.gui
+ let g:terminal_color_8 = s:visual_grey.gui
+ let g:terminal_color_9 = s:dark_red.gui
+ let g:terminal_color_10 = s:green.gui " No dark version
+ let g:terminal_color_11 = s:dark_yellow.gui
+ let g:terminal_color_12 = s:blue.gui " No dark version
+ let g:terminal_color_13 = s:purple.gui " No dark version
+ let g:terminal_color_14 = s:cyan.gui " No dark version
+ let g:terminal_color_15 = s:comment_grey.gui
+ let g:terminal_color_background = s:background.gui
+ let g:terminal_color_foreground = s:foreground.gui
+ " }}}
+
+ " Neovim Diagnostics {{{
+ call s:h("DiagnosticError", { "fg": s:red })
+ call s:h("DiagnosticWarn", { "fg": s:yellow })
+ call s:h("DiagnosticInfo", { "fg": s:blue })
+ call s:h("DiagnosticHint", { "fg": s:cyan })
+ call s:h("DiagnosticUnderlineError", { "fg": s:red, "gui": "underline", "cterm": "underline" })
+ call s:h("DiagnosticUnderlineWarn", { "fg": s:yellow, "gui": "underline", "cterm": "underline" })
+ call s:h("DiagnosticUnderlineInfo", { "fg": s:blue, "gui": "underline", "cterm": "underline" })
+ call s:h("DiagnosticUnderlineHint", { "fg": s:cyan, "gui": "underline", "cterm": "underline" })
+ " }}}
+
+ " Neovim LSP (for versions < 0.5.1) {{{
+ hi link LspDiagnosticsDefaultError DiagnosticError
+ hi link LspDiagnosticsDefaultWarning DiagnosticWarn
+ hi link LspDiagnosticsDefaultInformation DiagnosticInfo
+ hi link LspDiagnosticsDefaultHint DiagnosticHint
+ hi link LspDiagnosticsUnderlineError DiagnosticUnderlineError
+ hi link LspDiagnosticsUnderlineWarning DiagnosticUnderlineWarn
+ hi link LspDiagnosticsUnderlineInformation DiagnosticUnderlineInfo
+ hi link LspDiagnosticsUnderlineHint DiagnosticUnderlineHint
+ " }}}
+endif
+
+" }}}
+
+" Must appear at the end of the file to work around this oddity:
+" https://groups.google.com/forum/#!msg/vim_dev/afPqwAFNdrU/nqh6tOM87QUJ
+set background=dark
diff --git a/.config/nvim/other/fzf.vim b/.config/nvim/other/fzf.vim
new file mode 100644
index 0000000..32cb18b
--- /dev/null
+++ b/.config/nvim/other/fzf.vim
@@ -0,0 +1,19 @@
+" --> Fzf
+let g:fzf_layout = { 'window': { 'width': 1, 'height': 1 } }
+command! -bang -nargs=? -complete=dir Files
+ \ call fzf#vim#files(<q-args>, {'options': ['--info=inline', '--preview', 'preview {}']}, <bang>0)
+
+" Mapping selecting mappings
+nmap <leader><tab> <plug>(fzf-maps-n)
+xmap <leader><tab> <plug>(fzf-maps-x)
+omap <leader><tab> <plug>(fzf-maps-o)
+
+" Insert mode completion
+imap <c-x><c-k> <plug>(fzf-complete-word)
+imap <c-x><c-f> <plug>(fzf-complete-path)
+imap <c-x><c-l> <plug>(fzf-complete-line)
+
+" Fzf keybindings
+nnoremap <leader>ff :Files<CR>
+nnoremap <leader>. :Files %:p:h<CR>
+
diff --git a/.config/nvim/other/learn.vim b/.config/nvim/other/learn.vim
new file mode 100644
index 0000000..c3272d9
--- /dev/null
+++ b/.config/nvim/other/learn.vim
@@ -0,0 +1,649 @@
+" ##############
+" Introduction
+" ##############
+"
+" Vim script (also called VimL) is the subset of Vim's ex-commands which
+" supplies a number of features one would expect from a scripting language,
+" such as values, variables, functions or loops. Always keep in the back of
+" your mind that a Vim script file is just a sequence of ex-commands. It is
+" very common for a script to mix programming-language features and raw
+" ex-commands.
+"
+" You can run Vim script directly by entering the commands in command-line mode
+" (press `:` to enter command-line mode), or you can write them to a file
+" (without the leading `:`) and source it in a running Vim instance (`:source
+" path/to/file`). Some files are sourced automatically as part of your
+" configuration (see |startup|). This guide assumes that you are familiar
+" with ex-commands and will only cover the scripting. Help topics to the
+" relevant manual sections are included.
+"
+" See |usr_41.txt| for the official introduction to Vim script. A comment is
+" anything following an unmatched `"` until the end of the line, and `|`
+" separates instructions (what `;` does in most other languages). References to
+" the manual as surrounded with `|`, such as |help.txt|.
+
+" This is a comment
+
+" The vertical line '|' (pipe) separates commands
+echo 'Hello' | echo 'world!'
+
+" Putting a comment after a command usually works
+pwd " Displays the current working directory
+
+" Except for some commands it does not; use the command delimiter before the
+" comment (echo assumes that the quotation mark begins a string)
+echo 'Hello world!' | " Displays a message
+
+" Line breaks can be escaped by placing a backslash as the first non-whitespace
+" character on the *following* line. Only works in script files, not on the
+" command line
+echo " Hello
+ \ world "
+
+echo [1,
+ \ 2]
+
+echo {
+ \ 'a': 1,
+ \ 'b': 2
+\}
+
+
+" #######
+" Types
+" #######
+"
+" For an overview of types see |E712|. For an overview of operators see
+" |expression-syntax|
+
+" Numbers (|expr-number|)
+" #######
+
+echo 123 | " Decimal
+echo 0b1111011 | " Binary
+echo 0173 | " Octal
+echo 0x7B | " Hexadecimal
+echo 123.0 | " Floating-point
+echo 1.23e2 | " Floating-point (scientific notation)
+
+" Note that an *integer* number with a leading `0` is in octal notation. The
+" usual arithmetic operations are supported.
+
+echo 1 + 2 | " Addition
+echo 1 - 2 | " Subtraction
+echo - 1 | " Negation (unary minus)
+echo + 1 | " Unary plus (does nothing really, but still legal)
+echo 1 * 2 | " Multiplication
+echo 1 / 2 | " Division
+echo 1 % 2 | " Modulo (remainder)
+
+" Booleans (|Boolean|)
+" ########
+"
+" The number 0 is false, every other number is true. Strings are implicitly
+" converted to numbers (see below). There are two pre-defined semantic
+" constants.
+
+echo v:true | " Evaluates to 1 or the string 'v:true'
+echo v:false | " Evaluates to 0 or the string 'v:false'
+
+" Boolean values can result from comparison of two objects.
+
+echo x == y | " Equality by value
+echo x != y | " Inequality
+echo x > y | " Greater than
+echo x >= y | " Greater than or equal
+echo x < y | " Smaller than
+echo x <= y | " Smaller than or equal
+echo x is y | " Instance identity (lists and dictionaries)
+echo x isnot y | " Instance non-identity (lists and dictionaries)
+
+" Strings are compared based on their alphanumerical ordering
+" echo 'a' < 'b'. Case sensitivity depends on the setting of 'ignorecase'
+"
+" Explicit case-sensitivity is specified by appending '#' (match case) or '?'
+" (ignore case) to the operator. Prefer explicitly case sensitivity when writing
+" portable scripts.
+
+echo 'a' < 'B' | " True or false depending on 'ignorecase'
+echo 'a' <? 'B' | " True
+echo 'a' <# 'B' | " False
+
+" Regular expression matching
+echo "hi" =~ "hello" | " Regular expression match, uses 'ignorecase'
+echo "hi" =~# "hello" | " Regular expression match, case sensitive
+echo "hi" =~? "hello" | " Regular expression match, case insensitive
+echo "hi" !~ "hello" | " Regular expression unmatch, use 'ignorecase'
+echo "hi" !~# "hello" | " Regular expression unmatch, case sensitive
+echo "hi" !~? "hello" | " Regular expression unmatch, case insensitive
+
+" Boolean operations are possible.
+
+echo v:true && v:false | " Logical AND
+echo v:true || v:false | " Logical OR
+echo ! v:true | " Logical NOT
+echo v:true ? 'yes' : 'no' | " Ternary operator
+
+
+" Strings (|String|)
+" #######
+"
+" An ordered zero-indexed sequence of bytes. The encoding of text into bytes
+" depends on the option |'encoding'|.
+
+" Literal constructors
+echo "Hello world\n" | " The last two characters stand for newline
+echo 'Hello world\n' | " The last two characters are literal
+echo 'Let''s go!' | " Two single quotes become one quote character
+
+" Single-quote strings take all characters are literal, except two single
+" quotes, which are taken to be a single quote in the string itself. See
+" |expr-quote| for all possible escape sequences.
+
+" String concatenation
+" The .. operator is preferred, but only supported in since Vim 8.1.1114
+echo 'Hello ' . 'world' | " String concatenation
+echo 'Hello ' .. 'world' | " String concatenation (new variant)
+
+" String indexing
+echo 'Hello'[0] | " First byte
+echo 'Hello'[1] | " Second byte
+echo 'Hellö'[4] | " Returns a byte, not the character 'ö'
+
+" Substrings (second index is inclusive)
+echo 'Hello'[:] | " Copy of entire string
+echo 'Hello'[1:3] | " Substring, second to fourth byte
+echo 'Hello'[1:-2] | " Substring until second to last byte
+echo 'Hello'[1:] | " Substring with starting index
+echo 'Hello'[:2] | " Substring with ending index
+echo 'Hello'[-2:] | " Substring relative to end of string
+
+" A negative index is relative to the end of the string. See
+" |string-functions| for all string-related functions.
+
+" Lists (|List|)
+" #####
+"
+" An ordered zero-indexed heterogeneous sequence of arbitrary Vim script
+" objects.
+
+" Literal constructor
+echo [] | " Empty list
+echo [1, 2, 'Hello'] | " List with elements
+echo [1, 2, 'Hello', ] | " Trailing comma permitted
+echo [[1, 2], 'Hello'] | " Lists can be nested arbitrarily
+
+" List concatenation
+echo [1, 2] + [3, 4] | " Creates a new list
+
+" List indexing, negative is relative to end of list (|list-index|)
+echo [1, 2, 3, 4][2] | " Third element
+echo [1, 2, 3, 4][-1] | " Last element
+
+" List slicing (|sublist|)
+echo [1, 2, 3, 4][:] | " Shallow copy of entire list
+echo [1, 2, 3, 4][:2] | " Sublist until third item (inclusive)
+echo [1, 2, 3, 4][2:] | " Sublist from third item (inclusive)
+echo [1, 2, 3, 4][:-2] | " Sublist until second-to-last item (inclusive)
+
+" All slicing operations create new lists. To modify a list in-place use list
+" functions (|list-functions|) or assign directly to an item (see below about
+" variables).
+
+
+" Dictionaries (|Dictionary|)
+" ############
+"
+" An unordered sequence of key-value pairs, keys are always strings (numbers
+" are implicitly converted to strings).
+
+" Dictionary literal
+echo {} | " Empty dictionary
+echo {'a': 1, 'b': 2} | " Dictionary literal
+echo {'a': 1, 'b': 2, } | " Trailing comma permitted
+echo {'x': {'a': 1, 'b': 2}} | " Nested dictionary
+
+" Indexing a dictionary
+echo {'a': 1, 'b': 2}['a'] | " Literal index
+echo {'a': 1, 'b': 2}.a | " Syntactic sugar for simple keys
+
+" See |dict-functions| for dictionary manipulation functions.
+
+
+" Funcref (|Funcref|)
+" #######
+"
+" Reference to a function, uses the function name as a string for construction.
+" When stored in a variable the name of the variable has the same restrictions
+" as a function name (see below).
+
+echo function('type') | " Reference to function type()
+" Note that `funcref('type')` will throw an error because the argument must be
+" a user-defined function; see further below for defining your own functions.
+echo funcref('type') | " Reference by identity, not name
+" A lambda (|lambda|) is an anonymous function; it can only contain one
+" expression in its body, which is also its implicit return value.
+echo {x -> x * x} | " Anonymous function
+echo function('substitute', ['hello']) | " Partial function
+
+
+" Regular expression (|regular-expression|)
+" ##################
+"
+" A regular expression pattern is generally a string, but in some cases you can
+" also use a regular expression between a pair of delimiters (usually `/`, but
+" you can choose anything).
+
+" Substitute 'hello' for 'Hello'
+substitute/hello/Hello/
+
+
+" ###########################
+" Implicit type conversions
+" ###########################
+"
+" Strings are converted to numbers, and numbers to strings when necessary. A
+" number becomes its decimal notation as a string. A string becomes its
+" numerical value if it can be parsed to a number, otherwise it becomes zero.
+
+echo "1" + 1 | " Number
+echo "1" .. 1 | " String
+echo "0xA" + 1 | " Number
+
+" Strings are treated like numbers when used as booleans
+echo "true" ? 1 : 0 | " This string is parsed to 0, which is false
+
+" ###########
+" Variables
+" ###########
+"
+" Variables are bound within a scope; if no scope is provided a default is
+" chosen by Vim. Use `:let` and `:const` to bind a value and `:unlet` to unbind
+" it.
+
+let b:my_var = 1 | " Local to current buffer
+let w:my_var = 1 | " Local to current window
+let t:my_var = 1 | " Local to current tab page
+let g:my_var = 1 | " Global variable
+let l:my_var = 1 | " Local to current function (see functions below)
+let s:my_var = 1 | " Local to current script file
+let a:my_arg = 1 | " Function argument (see functions below)
+
+" The Vim scope is read-only
+echo v:true | " Special built-in Vim variables (|v:var|)
+
+" Access special Vim memory like variables
+let @a = 'Hello' | " Register
+let $PATH='' | " Environment variable
+let &textwidth = 79 | " Option
+let &l:textwidth = 79 | " Local option
+let &g:textwidth = 79 | " Global option
+
+" Access scopes as dictionaries (can be modified like all dictionaries)
+" See the |dict-functions|, especially |get()|, for access and manipulation
+echo b: | " All buffer variables
+echo w: | " All window variables
+echo t: | " All tab page variables
+echo g: | " All global variables
+echo l: | " All local variables
+echo s: | " All script variables
+echo a: | " All function arguments
+echo v: | " All Vim variables
+
+" Constant variables
+const x = 10 | " See |:const|, |:lockvar|
+
+" Function reference variables have the same restrictions as function names
+let IsString = {x -> type(x) == type('')} | " Global: capital letter
+let s:isNumber = {x -> type(x) == type(0)} | " Local: any name allowed
+
+" When omitted the scope `g:` is implied, except in functions, there `l:` is
+" implied.
+
+
+" Multiple value binding (list unpacking)
+" #######################################
+"
+" Assign values of list to multiple variables (number of items must match)
+let [x, y] = [1, 2]
+
+" Assign the remainder to a rest variable (note the semicolon)
+let [mother, father; children] = ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
+
+
+" ##############
+" Flow control
+" ##############
+
+" Conditional (|:if|, |:elseif|, |:else|, |:endif|)
+" ###########
+"
+" Conditions are set between `if` and `endif`. They can be nested.
+
+let condition = v:true
+
+if condition
+ echo 'First condition'
+elseif another_condition
+ echo 'Second condition'
+else
+ echo 'Fail'
+endif
+
+" Loops (|:for|, |:endfor|, |:while|, |:endwhile|, |:break|, |:continue|)
+" #####
+"
+" Two types of loops: `:for` and `:while`. Use `:continue` to skip to the next
+" iteration, `:break` to break out of the loop.
+
+" For-loop (|:for|, |:endfor|)
+" ========
+"
+" For-loops iterate over lists and nothing else. If you want to iterate over
+" another sequence you need to use a function which will create a list.
+
+" Iterate over a list
+for person in ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
+ echo 'Hello ' .. person
+endfor
+
+" Iterate over a nested list by unpacking it
+for [x, y] in [[1, 0], [0, 1], [-1, 0], [0, -1]]
+ echo 'Position: x =' .. x .. ', y = ' .. y
+endfor
+
+" Iterate over a range of numbers
+for i in range(10, 0, -1) " Count down from 10
+ echo 'T minus' .. i
+endfor
+
+" Iterate over the keys of a dictionary
+for symbol in keys({'π': 3.14, 'e': 2.71})
+ echo 'The constant ' .. symbol .. ' is a transcendent number'
+endfor
+
+" Iterate over the values of a dictionary
+for value in values({'π': 3.14, 'e': 2.71})
+ echo 'The value ' .. value .. ' approximates a transcendent number'
+endfor
+
+" Iterate over the keys and values of a dictionary
+for [symbol, value] in items({'π': 3.14, 'e': 2.71})
+ echo 'The number ' .. symbol .. ' is approximately ' .. value
+endfor
+
+" While-loops (|:while|, |:endwhile|)
+
+let there_yet = v:true
+while !there_yet
+ echo 'Are we there yet?'
+endwhile
+
+
+" Exception handling (|exception-handling|)
+" ##################
+"
+" Throw new exceptions as strings, catch them by pattern-matching a regular
+" expression against the string
+
+" Throw new exception
+throw "Wrong arguments"
+
+" Guard against an exception (the second catch matches any exception)
+try
+ source path/to/file
+catch /Cannot open/
+ echo 'Looks like that file does not exist'
+catch /.*/
+ echo 'Something went wrong, but I do not know what'
+finally
+ echo 'I am done trying'
+endtry
+
+
+" ##########
+" Functions
+" ##########
+
+" Defining functions (|:function|, |:endfunction|)
+" ##################
+
+" Unscoped function names have to start with a capital letter
+function! AddNumbersLoudly(x, y)
+ " Use a: scope to access arguments
+ echo 'Adding' .. a:x .. 'and' .. a:y | " A side effect
+ return a:x + a:y | " A return value
+endfunction
+
+" Scoped function names may start with a lower-case letter
+function! s:addNumbersLoudly(x, y)
+ echo 'Adding' .. a:x .. 'and' .. a:y
+ return a:x + a:y
+endfunction
+
+" Without the exclamation mark it would be an error to re-define a function,
+" with the exclamation mark the new definition can replace the old one. Since
+" Vim script files can be reloaded several times over the course of a session
+" it is best to use the exclamation mark unless you really know what you are
+" doing.
+
+" Function definitions can have special qualifiers following the argument list.
+
+" Range functions define two implicit arguments, which will be set to the range
+" of the ex-command
+function! FirstAndLastLine() range
+ echo [a:firstline, a:lastline]
+endfunction
+
+" Prints the first and last line that match a pattern (|cmdline-ranges|)
+/^#!/,/!#$/call FirstAndLastLine()
+
+" Aborting functions, abort once error occurs (|:func-abort|)
+function! SourceMyFile() abort
+ source my-file.vim | " Try sourcing non-existing file
+ echo 'This will never be printed'
+endfunction
+
+" Closures, functions carrying values from outer scope (|:func-closure|)
+function! MakeAdder(x)
+ function! Adder(n) closure
+ return a:n + a:x
+ endfunction
+ return funcref('Adder')
+endfunction
+let AddFive = MakeAdder(5)
+echo AddFive(3) | " Prints 8
+
+" Dictionary functions, poor man's OOP methods (|Dictionary-function|)
+function! Mylen() dict
+ return len(self.data) | " Implicit variable self
+endfunction
+let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
+echo mydict.len()
+
+" Alternatively, more concise
+let mydict = {'data': [0, 1, 2, 3]}
+function! mydict.len()
+ return len(self.data)
+endfunction
+
+" Calling functions (|:call|)
+" #################
+
+" Call a function for its return value, and possibly for its side effects
+let animals = keys({'cow': 'moo', 'dog': 'woof', 'cat': 'meow'})
+
+" Call a function for its side effects only, ignore potential return value
+call sign_undefine()
+
+" The call() function calls a function reference and passes parameters as a
+" list, and returns the function's result.
+echo call(function('get'), [{'a': 1, 'b': 2}, 'c', 3]) | " Prints 3
+
+" Recall that Vim script is embedded within the ex-commands, that is why we
+" cannot just call a function directly, we have to use the `:call` ex-command.
+
+" Function namespaces (|write-library-script|, |autoload|)
+" ###################
+
+" Must be defined in autoload/foo/bar.vim
+" Namspaced function names do not have to start with a capital letter
+function! foo#bar#log(value)
+ echomsg value
+endfunction
+
+call foo#bar#log('Hello')
+
+
+" #############################
+" Frequently used ex-commands
+" #############################
+
+
+" Sourcing runtime files (|'runtimepath'|)
+" ######################
+
+" Source first match among runtime paths
+runtime plugin/my-plugin.vim
+
+
+" Defining new ex-commands (|40.2|, |:command|)
+" ########################
+
+" First argument here is the name of the command, rest is the command body
+command! SwapAdjacentLines normal! ddp
+
+" The exclamation mark works the same as with `:function`. User-defined
+" commands must start with a capital letter. The `:command` command can take a
+" number of attributes (some of which have their own parameters with `=`), such
+" as `-nargs`, all of them start with a dash to set them apart from the command
+" name.
+
+command! -nargs=1 Error echoerr <args>
+
+
+" Defining auto-commands (|40.3|, |autocmd|, |autocommand-events|)
+" ######################
+
+" The arguments are "events", "patterns", rest is "commands"
+autocmd BufWritePost $MYVIMRC source $MYVIMRC
+
+" Events and patterns are separated by commas with no space between. See
+" |autocmd-events| for standard events, |User| for custom events. Everything
+" else are the ex-commands which will be executed.
+
+" Auto groups
+" ===========
+"
+" When a file is sourced multiple times the auto-commands are defined anew,
+" without deleting the old ones, causing auto-commands to pile up over time.
+" Use auto-groups and the following ritual to guard against this.
+
+augroup auto-source | " The name of the group is arbitrary
+ autocmd! | " Deletes all auto-commands in the current group
+ autocmd BufWritePost $MYVIMRC source $MYVIMRC
+augroup END | " Switch back to default auto-group
+
+" It is also possible to assign a group directly. This is useful if the
+" definition of the group is in one script and the definition of the
+" auto-command is in another script.
+
+" In one file
+augroup auto-source
+ autocmd!
+augroup END
+
+" In another file
+autocmd auto-source BufWritePost $MYVIMRC source $MYVIMRC
+
+" Executing (run-time macros of sorts)
+" ####################################
+
+" Sometimes we need to construct an ex-command where part of the command is not
+" known until runtime.
+
+let line = 3 | " Line number determined at runtime
+execute line .. 'delete' | " Delete a line
+
+" Executing normal-mode commands
+" ##############################
+"
+" Use `:normal` to play back a sequence of normal mode commands from the
+" command-line. Add an exclamation mark to ignore user mappings.
+
+normal! ggddGp | " Transplant first line to end of buffer
+
+" Window commands can be used with :normal, or with :wincmd if :normal would
+" not work
+wincmd L | " Move current window all the way to the right
+
+
+" ###########################
+" Frequently used functions
+" ###########################
+
+" Feature check
+echo has('nvim') | " Running Neovim
+echo has('python3') | " Support for Python 3 plugins
+echo has('unix') | " Running on a Unix system
+echo has('win32') | " Running on a Windows system
+
+
+" Test if something exists
+echo exists('&mouse') | " Option (exists only)
+echo exists('+mouse') | " Option (exists and works)
+echo exists('$HOSTNAME') | " Environment variable
+echo exists('*strftime') | " Built-in function
+echo exists('**s:MyFunc') | " User-defined function
+echo exists('bufcount') | " Variable (scope optional)
+echo exists('my_dict["foo"]') | " Variable (dictionary entry)
+echo exists('my_dict["foo"]') | " Variable (dictionary entry)
+echo exists(':Make') | " Command
+echo exists("#CursorHold") | " Auto-command defined for event
+echo exists("#BufReadPre#*.gz") | " Event and pattern
+echo exists("#filetypeindent") | " Auto-command group
+echo exists("##ColorScheme") | " Auto-command supported for event
+
+" Various dynamic values (see |expand()|)
+echo expand('%') | " Current file name
+echo expand('<cword>') | " Current word under cursor
+echo expand('%:p') | " Modifier are possible
+
+" Type tests
+" There are unique constants defined for the following types. Older versions
+" of Vim lack the type variables, see the reference " documentation for a
+" workaround
+echo type(my_var) == v:t_number | " Number
+echo type(my_var) == v:t_string | " String
+echo type(my_var) == v:t_func | " Funcref
+echo type(my_var) == v:t_list | " List
+echo type(my_var) == v:t_dict | " Dictionary
+echo type(my_var) == v:t_float | " Float
+echo type(my_var) == v:t_bool | " Explicit Boolean
+" For the null object should compare it against itself
+echo my_var is v:null
+
+" Format strings
+echo printf('%d in hexadecimal is %X', 123, 123)
+
+
+" #####################
+" Tricks of the trade
+" #####################
+
+" Source guard
+" ############
+
+" Prevent a file from being sourced multiple times; users can set the variable
+" in their configuration to prevent the plugin from loading at all.
+if exists('g:loaded_my_plugin')
+ finish
+endif
+let g:loaded_my_plugin = v:true
+
+" Default values
+" ##############
+
+" Get a default value: if the user defines a variable use it, otherwise use a
+" hard-coded default. Uses the fact that a scope is also a dictionary.
+let s:greeting = get(g:, 'my_plugin_greeting', 'Hello')
diff --git a/.config/nvim/out.vim b/.config/nvim/out.vim
new file mode 100644
index 0000000..6e4e1f1
--- /dev/null
+++ b/.config/nvim/out.vim
@@ -0,0 +1,36 @@
+" capture (dump) the (somewhat long) ouput of the commands like `:digraph`, `:map', `:highlight`, `:scripnames` etc.
+
+function! s:dump(cmd) abort
+
+ " Start a new split or maybe a buffer or a tab
+ " enew | " open a new buffer
+ 10split | enew | " open a new split (with 10% height (?))
+ " tabnew | " open a new tab
+
+ " Make it a scratch buffer ( `:help special-buffers`)
+ setlocal
+ \ bufhidden=wipe
+ \ buftype=nofile
+ \ nobuflisted
+ \ nolist
+ \ noswapfile
+ \ norelativenumber
+ \ nonumber
+
+ " Write the cmd output to the buffer
+ put =execute(a:cmd)
+ " There are 2 empty line at the beginning of the buffer before the ouput of
+ " the cmd. Not sure from where they are comning from. Anyhow I will delete
+ " them.
+ norm gg2dd
+
+ " No modifications to this buffer
+ setlocal readonly nomodifiable nomodified
+
+ " Press escape to close when you're done
+ nnoremap <buffer><silent> <Esc> :bd<CR>
+
+endfunction
+
+" Define a command to use the function easier
+command! -nargs=1 Dump execute "call s:dump(" string(<q-args>) ")"
diff --git a/.config/nvim/pack/colors/opt/onedark.vim b/.config/nvim/pack/colors/opt/onedark.vim
new file mode 160000
+Subproject 390b893d361c356ac1b00778d849815f2aa44ae
diff --git a/.config/nvim/templates/_default.c b/.config/nvim/templates/_default.c
new file mode 100644
index 0000000..6d8e7c1
--- /dev/null
+++ b/.config/nvim/templates/_default.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+int main() {
+ <++>
+}
diff --git a/.config/nvim/templates/_default.html b/.config/nvim/templates/_default.html
new file mode 100644
index 0000000..4201ee8
--- /dev/null
+++ b/.config/nvim/templates/_default.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title><++></title>
+ <link rel="stylesheet" href="/style.css">
+</head>
+
+<body>
+ <++>
+</body>
+
+</html>
diff --git a/.config/nvim/templates/_default.tex b/.config/nvim/templates/_default.tex
new file mode 100644
index 0000000..397e28e
--- /dev/null
+++ b/.config/nvim/templates/_default.tex
@@ -0,0 +1,7 @@
+\documentclass{article}
+
+\begin{document}
+
+<++>
+
+\end{document}
diff --git a/.config/nvim/templates/article.tex b/.config/nvim/templates/article.tex
new file mode 100644
index 0000000..a821909
--- /dev/null
+++ b/.config/nvim/templates/article.tex
@@ -0,0 +1,11 @@
+\documentclass{article}
+
+\title{<++>}
+\author{<++>}
+
+\begin{document}
+\maketitle
+
+<++>
+
+\end{document}
diff --git a/.config/nvim/vim.log b/.config/nvim/vim.log
new file mode 100644
index 0000000..67ecb5b
--- /dev/null
+++ b/.config/nvim/vim.log
@@ -0,0 +1,170 @@
+
+
+times in msec
+ clock self+sourced self: sourced script
+ clock elapsed: other lines
+
+000.009 000.009: --- NVIM STARTING ---
+000.119 000.110: event init
+000.186 000.067: early init
+000.230 000.043: locale set
+000.260 000.030: init first window
+000.469 000.209: inits 1
+000.483 000.014: window checked
+000.484 000.001: parsing arguments
+000.872 000.051 000.051: require('vim.shared')
+000.971 000.034 000.034: require('vim._meta')
+000.973 000.095 000.061: require('vim._editor')
+000.974 000.190 000.044: require('vim._init_packages')
+000.975 000.301: init lua interpreter
+001.027 000.053: expanding arguments
+001.058 000.031: inits 2
+001.316 000.258: init highlight
+001.317 000.001: waiting for UI
+001.475 000.157: done waiting for UI
+001.481 000.007: clear screen
+001.588 000.107: init default mappings & autocommands
+001.883 000.041 000.041: sourcing /usr/share/nvim/runtime/ftplugin.vim
+001.936 000.022 000.022: sourcing /usr/share/nvim/runtime/indent.vim
+001.982 000.009 000.009: sourcing /usr/share/nvim/archlinux.vim
+001.985 000.030 000.021: sourcing /etc/xdg/nvim/sysinit.vim
+006.183 000.919 000.919: sourcing /home/master/.config/nvim/autoload/plug.vim
+012.319 000.007 000.007: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/filetype.vim
+012.437 000.007 000.007: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/ftdetect/polyglot.vim
+012.556 000.010 000.010: sourcing /usr/share/vim/vimfiles/ftdetect/PKGBUILD.vim
+012.580 000.008 000.008: sourcing /usr/share/vim/vimfiles/ftdetect/SRCINFO.vim
+012.604 000.007 000.007: sourcing /usr/share/vim/vimfiles/ftdetect/augeas.vim
+012.634 000.014 000.014: sourcing /usr/share/vim/vimfiles/ftdetect/conkyrc.vim
+012.672 000.022 000.022: sourcing /usr/share/vim/vimfiles/ftdetect/espeakfiletype.vim
+012.703 000.015 000.015: sourcing /usr/share/vim/vimfiles/ftdetect/lf.vim
+012.755 000.024 000.024: sourcing /usr/share/vim/vimfiles/ftdetect/nginx.vim
+023.697 011.642 011.528: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/autoload/polyglot/init.vim
+023.708 011.710 000.068: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/filetype.vim
+023.840 000.085 000.085: sourcing /usr/share/nvim/runtime/filetype.lua
+024.243 000.011 000.011: sourcing /usr/share/nvim/runtime/ftplugin.vim
+024.319 000.007 000.007: sourcing /usr/share/nvim/runtime/indent.vim
+024.499 000.063 000.063: sourcing /usr/share/nvim/runtime/syntax/synload.vim
+024.563 000.201 000.137: sourcing /usr/share/nvim/runtime/syntax/syntax.vim
+024.947 000.306 000.306: sourcing /usr/share/nvim/runtime/syntax/nosyntax.vim
+025.066 000.054 000.054: sourcing /usr/share/nvim/runtime/syntax/synload.vim
+025.118 000.505 000.145: sourcing /usr/share/nvim/runtime/syntax/syntax.vim
+025.229 000.008 000.008: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/filetype.vim
+025.302 000.053 000.053: sourcing /usr/share/nvim/runtime/filetype.lua
+025.391 000.008 000.008: sourcing /usr/share/nvim/runtime/ftplugin.vim
+025.499 000.007 000.007: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/filetype.vim
+025.566 000.048 000.048: sourcing /usr/share/nvim/runtime/filetype.lua
+025.652 000.008 000.008: sourcing /usr/share/nvim/runtime/ftplugin.vim
+025.723 000.006 000.006: sourcing /usr/share/nvim/runtime/indent.vim
+025.809 023.804 010.228: sourcing /home/master/.config/nvim/init.vim
+025.815 000.331: sourcing vimrc file(s)
+026.068 000.043 000.043: sourcing /home/master/.config/nvim/plugin/coc.vim
+026.166 000.080 000.080: sourcing /home/master/.config/nvim/plugin/debug.vim
+026.202 000.018 000.018: sourcing /home/master/.config/nvim/plugin/docs.vim
+026.303 000.082 000.082: sourcing /home/master/.config/nvim/plugin/fzf.vim
+026.366 000.041 000.041: sourcing /home/master/.config/nvim/plugin/scratch.vim
+026.863 000.071 000.071: sourcing /home/master/.config/nvim/autoload/onedark.vim
+039.423 012.982 012.912: sourcing /home/master/.config/nvim/colors/onedark.vim
+039.454 013.068 000.086: sourcing /home/master/.config/nvim/plugin/ui.vim
+039.812 000.227 000.227: sourcing /home/master/.local/share/nvim/plugged/vim-surround/plugin/surround.vim
+039.967 000.084 000.084: sourcing /home/master/.local/share/nvim/plugged/vim-commentary/plugin/commentary.vim
+040.116 000.063 000.063: sourcing /home/master/.local/share/nvim/plugged/lf.vim/plugin/lf.vim
+040.371 000.185 000.185: sourcing /home/master/.local/share/nvim/plugged/vim-floaterm/plugin/floaterm.vim
+040.855 000.418 000.418: sourcing /home/master/.local/share/nvim/plugged/fzf/plugin/fzf.vim
+041.550 000.617 000.617: sourcing /home/master/.local/share/nvim/plugged/fzf.vim/plugin/fzf.vim
+041.693 000.073 000.073: sourcing /home/master/.local/share/nvim/plugged/zeavim.vim/plugin/zeavim.vim
+042.133 000.339 000.339: sourcing /home/master/.local/share/nvim/plugged/vim-polyglot/plugin/polyglot.vim
+042.506 000.152 000.152: sourcing /usr/share/nvim/runtime/plugin/gzip.vim
+042.533 000.007 000.007: sourcing /usr/share/nvim/runtime/plugin/health.vim
+042.939 000.118 000.118: sourcing /usr/share/nvim/runtime/pack/dist/opt/matchit/plugin/matchit.vim
+043.016 000.466 000.348: sourcing /usr/share/nvim/runtime/plugin/matchit.vim
+043.131 000.099 000.099: sourcing /usr/share/nvim/runtime/plugin/matchparen.vim
+043.494 000.345 000.345: sourcing /usr/share/nvim/runtime/plugin/netrwPlugin.vim
+044.073 000.113 000.113: sourcing /usr/share/nvim/runtime/autoload/remote/host.vim
+044.305 000.089 000.089: sourcing /usr/share/nvim/runtime/autoload/remote/define.vim
+044.761 001.141 000.938: sourcing /home/master/.local/share/nvim/rplugin.vim
+044.768 001.244 000.103: sourcing /usr/share/nvim/runtime/plugin/rplugin.vim
+044.886 000.091 000.091: sourcing /usr/share/nvim/runtime/plugin/shada.vim
+044.928 000.017 000.017: sourcing /usr/share/nvim/runtime/plugin/spellfile.vim
+045.070 000.121 000.121: sourcing /usr/share/nvim/runtime/plugin/tarPlugin.vim
+045.154 000.058 000.058: sourcing /usr/share/nvim/runtime/plugin/tohtml.vim
+045.193 000.013 000.013: sourcing /usr/share/nvim/runtime/plugin/tutor.vim
+045.365 000.151 000.151: sourcing /usr/share/nvim/runtime/plugin/zipPlugin.vim
+045.471 000.012 000.012: sourcing /usr/share/vim/vimfiles/plugin/fzf.vim
+045.579 000.089 000.089: sourcing /usr/share/vim/vimfiles/plugin/redact_pass.vim
+046.186 000.100 000.100: sourcing /usr/share/nvim/runtime/plugin/editorconfig.lua
+046.313 000.104 000.104: sourcing /usr/share/nvim/runtime/plugin/man.lua
+046.371 000.037 000.037: sourcing /usr/share/nvim/runtime/plugin/nvim.lua
+046.425 002.166: loading rtp plugins
+046.501 000.075: loading packages
+046.527 000.027: loading after plugins
+046.535 000.007: inits 3
+049.346 002.812: reading ShaDa
+049.563 000.216: opening buffers
+049.592 000.029: BufEnter autocommands
+049.594 000.002: editing files in windows
+051.092 000.064 000.064: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/init.vim
+051.660 000.278 000.278: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/parts.vim
+051.828 000.011 000.011: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/formatter/short_path.vim
+052.601 000.102 000.102: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/util.vim
+052.898 000.159 000.159: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions.vim
+053.025 000.030 000.030: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/quickfix.vim
+053.204 000.108 000.108: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline.vim
+053.349 000.020 000.020: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/netrw.vim
+053.463 000.021 000.021: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/fzf.vim
+053.692 000.064 000.064: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/term.vim
+055.576 000.118 000.118: require('vim.lsp.log')
+056.062 000.483 000.483: require('vim.lsp.protocol')
+057.439 000.324 000.324: require('vim.lsp._snippet')
+057.532 000.090 000.090: require('vim.highlight')
+057.538 000.004 000.004: require('vim.F')
+057.556 001.459 001.041: require('vim.lsp.util')
+057.570 002.492 000.432: require('vim.lsp.handlers')
+057.977 000.405 000.405: require('vim.lsp.rpc')
+058.150 000.171 000.171: require('vim.lsp.sync')
+058.648 000.496 000.496: require('vim.lsp.semantic_tokens')
+059.000 000.349 000.349: require('vim.lsp.buf')
+059.135 000.133 000.133: require('vim.lsp.diagnostic')
+059.350 000.213 000.213: require('vim.lsp.codelens')
+059.382 005.520 001.261: require('vim.lsp')
+059.504 000.044 000.044: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/nvimlsp.vim
+059.696 000.071 000.071: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/whitespace.vim
+059.933 000.037 000.037: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/po.vim
+060.085 000.056 000.056: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/wordcount.vim
+060.283 000.019 000.019: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/keymap.vim
+060.481 000.028 000.028: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/searchcount.vim
+064.384 000.073 000.073: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/section.vim
+064.878 000.238 000.238: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/highlighter.vim
+068.911 000.072 000.072: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/themes.vim
+069.476 000.931 000.859: sourcing /home/master/.config/nvim/autoload/airline/themes/onedark.vim
+072.884 000.370 000.370: sourcing /home/master/.config/nvim/autoload/airline/themes/onedark.vim
+085.154 000.083 000.083: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/builder.vim
+085.516 000.050 000.050: sourcing /home/master/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/default.vim
+102.172 051.614 043.237: sourcing /home/master/.local/share/nvim/plugged/vim-airline/plugin/airline.vim
+102.485 000.031 000.031: sourcing /home/master/.local/share/nvim/plugged/vim-airline-themes/plugin/airline-themes.vim
+103.232 001.993: VimEnter autocommands
+103.235 000.003: UIEnter autocommands
+103.236 000.001: before starting main loop
+103.996 000.760: first screen update
+103.998 000.002: --- NVIM STARTED ---
+
+
+times in msec
+ clock self+sourced self: sourced script
+ clock elapsed: other lines
+
+000.009 000.009: --- NVIM STARTING ---
+000.188 000.179: event init
+000.251 000.063: early init
+000.292 000.041: locale set
+000.329 000.036: init first window
+000.545 000.217: inits 1
+000.551 000.006: window checked
+000.553 000.002: parsing arguments
+000.937 000.026 000.026: require('vim.shared')
+001.012 000.032 000.032: require('vim._meta')
+001.014 000.073 000.041: require('vim._editor')
+001.015 000.160 000.061: require('vim._init_packages')
+001.016 000.302: init lua interpreter
+001.515 000.500: expanding arguments
+001.559 000.044: inits 2
+001.793 000.233: init highlight
diff --git a/.config/nvim/vimspector/python.json b/.config/nvim/vimspector/python.json
new file mode 100644
index 0000000..7fff9ab
--- /dev/null
+++ b/.config/nvim/vimspector/python.json
@@ -0,0 +1,31 @@
+{
+ "configurations": {
+ "Python: Launch": {
+ "adapter": "debugpy",
+ "filetypes": [ "python" ],
+ "configuration": {
+ "name": "python: Launch",
+ "type": "python",
+ "request": "launch",
+ "python": "$HOME/Others/virtualenvs/main/bin/python",
+ "program": "$file",
+ "stopOnEntry": true,
+ "debugOptions": []
+ }
+ },
+ "Python: Launch interactive": {
+ "adapter": "debugpy",
+ "filetypes": [ "python" ],
+ "configuration": {
+ "name": "python: Launch",
+ "type": "python",
+ "request": "launch",
+ "python": "$HOME/Others/virtualenvs/main/bin/python",
+ "program": "$file",
+ "console": "externalTerminal",
+ "stopOnEntry": true,
+ "debugOptions": []
+ }
+ }
+ }
+}
diff --git a/.config/python/pythonrc b/.config/python/pythonrc
new file mode 100644
index 0000000..9ab457e
--- /dev/null
+++ b/.config/python/pythonrc
@@ -0,0 +1,22 @@
+import os
+import atexit
+import readline
+
+state_home = os.environ.get("XDG_STATE_HOME")
+if state_home is None:
+ state_home = os.path.join(os.path.expanduser('~'), ".local", "state")
+
+history = os.path.join(state_home, "python_history")
+
+try:
+ readline.read_history_file(history)
+except OSError:
+ pass
+
+def write_history():
+ try:
+ readline.write_history_file(history)
+ except OSError:
+ pass
+
+atexit.register(write_history)
diff --git a/.config/shell/aliasrc b/.config/shell/aliasrc
new file mode 100644
index 0000000..1c4c7fc
--- /dev/null
+++ b/.config/shell/aliasrc
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+# Common operations
+alias xx='chmod u+x'
+alias x-='chmod -x'
+alias th='touch'
+alias md='mkdir'
+alias s='sudo'
+alias l='ls -A'
+alias ll='ls -al'
+# open
+alias o='${OPENER:-xdg-open}'
+alias e='${EDITOR:-vi}'
+alias se='sudoedit'
+alias lf='lfcd'
+alias rs='exec $SHELL'
+alias sr='e "$(ff -L ~/.config ~/.local/bin ~/bin)"'
+alias fh='fzf --tac < "${XDG_DATA_HOME:-$HOME/.local/share}/openhist"'
+
+alias uc='cd ~ && gitpush'
+
+lt() { tree -aC "$@" | less -rF; }
+dul() { du -ahd 1 "$@" | sort -h | less -FX; }
+v() { LESSOPEN="|preview %s" less -r -F "${1:-.}"; }
+ff() { find "$@" ! -wholename '*.git*' \( -type d -printf '%p/\n' , ! -type d -print \) |
+ FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS $fo" fzf -m; }
+senv() { source "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/${1:-main}/bin/activate"; }
+
+sudoedit() {
+ if command -V vim >/dev/null; then
+ [ -f "$HOME/.vim/vimrc" ] && VIMRC="$HOME/.vim/vimrc"
+ sudo vim -u "${VIMRC:-$HOME/.vimrc}" "$@"
+ elif command -V nvim >/dev/null; then
+ sudo nvim -u "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/init.vim" "$@"
+ else
+ command sudoedit "$@"
+ fi
+}
+
+lfcd () {
+ [ $# -gt 0 ] && [ -z "$1" ] && return 2
+ # cd "$(command lf -print-last-dir "$@")"
+
+ tmp="$(mktemp)"
+ command lf -last-dir-path="$tmp" "$@"
+ if [ -f "$tmp" ]; then
+ dir="$(cat "$tmp")"
+ rm -f "$tmp"
+ [ -d "$dir" ] || return
+ [ "$dir" != "$PWD" ] || return
+ cd "$dir"
+ fi
+}
+
+# Dirs
+alias ..='cd ..'
+alias ...='cd ../..'
+alias ....='cd ../../..'
+alias .....='cd ../../../..'
+alias ......='cd ../../../../..'
+
+alias 1='pushd -1'
+alias 2='pushd -2'
+alias 3='pushd -3'
+alias 4='pushd -4'
+alias 5='pushd -5'
+alias 6='pushd -6'
+alias 7='pushd -7'
+alias 8='pushd -8'
+alias 9='pushd -9'
+
+## Default options
+alias rm='rm -Iv'
+alias cp='cp -iv'
+alias mv='mv -iv'
+alias du='du -h'
+alias mkdir='mkdir -pv'
+alias watch='watch -c -n 1 '
+alias wget='wget -c'
+alias fzf='fzf --ansi'
+alias diff='diff --color=auto'
+alias grep='grep --color=auto'
+alias tree='tree -C'
+alias ls='ls -h --group-directories-first --color=auto --classify=auto'
+alias info='info --vi-keys --init-file ~/.config/infokey'
diff --git a/.config/shell/bm-dirs b/.config/shell/bm-dirs
new file mode 100644
index 0000000..4918a18
--- /dev/null
+++ b/.config/shell/bm-dirs
@@ -0,0 +1,51 @@
+# You can add comments to these files with #
+cac ${XDG_CACHE_HOME:-$HOME/.cache}
+cg ${XDG_CONFIG_HOME:-$HOME/.config}
+lsh ${XDG_DATA_DIR:-$HOME/.local/share}
+vnv ${XDG_DATA_DIR:-$HOME/.local/share}/virtualenvs
+lsr ${XDG_DATA_DIR:-$HOME/.local/src}
+lst ${XDG_DATA_DIR:-$HOME/.local/state}
+dn ${XDG_DOWNLOAD_DIR:-$HOME/Downloads}
+dx ${XDG_DOCUMENTS_DIR:-$HOME/Documents}
+dl ${XDG_DOCUMENTS_DIR:-$HOME/Documents}/latex
+nt ${XDG_DOCUMENTS_DIR:-$HOME/Documents}/Notes
+ms ${XDG_MUSIC_DIR:-$HOME/Music}
+px ${XDG_PICTURES_DIR:-$HOME/Pictures}
+vd ${XDG_VIDEOS_DIR:-$HOME/Videos}
+
+lb ~/.local/bin
+bn ~/bin
+sd ~/sdcard
+rp ~/repos
+ap ~/Applications
+ad ~/Arduino
+dv ~/Dev
+cm ~/Dev/cloud-maker
+cs ~/Dev/sites/csstudent41.github.io
+vr ~/Dev/sites/vikas.rocks
+vrc ~/Dev/sites/vikas.rocks/content
+vrl ~/Dev/sites/vikas.rocks/layouts
+vrp ~/Dev/sites/vikas.rocks/public
+td ~/Dev/test
+gd ~/GDrive/vartak/CS
+gf ~/GDrive/vartak/CS/practical-files/sem5
+gp ~/GDrive/vartak/CS/practical-notes/sem5
+gz ~/GDrive/vartak/CS/practical-zip/sem5
+gn ~/GDrive/vartak/CS/notes/sem5
+rs ~/GDrive/vartak/results
+ph ~/Phone
+stv ~/Phone/.stversions
+pw ~/Phone/Android/media/com.whatsapp/WhatsApp/Media/WhatsApp\ Documents
+
+mn /mnt
+stg ${STORAGE:-/mnt/storage}
+lr ${STORAGE:-/mnt/storage}/Library
+med ${STORAGE:-/mnt/storage}/Media
+sts ${STORAGE:-/mnt/storage}/sites
+sd /sdcard
+mp /run/media/$USER/
+mtp /run/user/1000/gvfs
+usr ${PREFIX:-/usr}
+ush /usr/share
+usd /usr/share/doc
+usha /usr/share/applications
diff --git a/.config/shell/bm-files b/.config/shell/bm-files
new file mode 100644
index 0000000..46723a5
--- /dev/null
+++ b/.config/shell/bm-files
@@ -0,0 +1,28 @@
+# These files automatically update when edited/saved in vim:
+
+# keys filename description
+bf ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-files
+bd ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs
+
+pf ~/.profile
+zp ~/.zprofile
+xp ~/.xprofile
+gi ~/.gitignore
+zc ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/.zshrc
+zh ${XDG_DATA_HOME:-$HOME/.config}/zsh/history
+za ${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc
+arc ${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc
+spf ${XDG_CONFIG_HOME:-$HOME/.config}/shell/server.profile
+lc ${XDG_CONFIG_HOME:-$HOME/.config}/lf/lfrc
+sx ${XDG_CONFIG_HOME:-$HOME/.config}/sxiv/exec/key-handler
+in ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/init.vim
+ac ${XDG_CONFIG_HOME:-$HOME/.config}/alacritty/alacritty.toml
+xr ${XDG_CONFIG_HOME:-$HOME/.config}/X11/Xresources
+xi ${XDG_CONFIG_HOME:-$HOME/.config}/X11/xinitrc
+mm ${XDG_CONFIG_HOME:-$HOME/.config}/mimeapps.list
+ssc ~/.ssh/config
+csh ~/Dev/csstudent41.github.io/layouts/_default/home.html
+qn ${XDG_DOCUMENTS_HOME:-$HOME/Documents}/Notes/QuickNote.md
+bm ${XDG_DOCUMENTS_HOME:-$HOME/Documents}/Notes/bookmarks.txt
+akn ${XDG_DOCUMENTS_HOME:-$HOME/Documents}/Notes/ak47.txt
+li ${XDG_DOCUMENTS_HOME:-$HOME/Documents}/latex/lorem-ipsum.txt
diff --git a/.config/shell/inputrc b/.config/shell/inputrc
new file mode 100644
index 0000000..4f7c652
--- /dev/null
+++ b/.config/shell/inputrc
@@ -0,0 +1,38 @@
+set editing-mode vi
+set keymap vi-insert
+RETURN: "\e\n"
+# set vi-ins-mode-string "+"
+# set vi-cmd-mode-string ":"
+# Add colorful command mode string
+# set vi-cmd-mode-string "\1\e[1;31m\2:\1\e[0m\2"
+# Change cursor bar -> insert mode block -> command mode
+set vi-ins-mode-string \1\e[6 q\2
+set vi-cmd-mode-string \1\e[2 q\2
+
+
+set show-mode-in-prompt on
+set show-all-if-ambiguous on
+set completion-ignore-case on
+set menu-complete-display-prefix on
+
+"\C-a": beginning-of-line
+"\C-b": backward-char
+"\C-d": delete-char
+"\C-e": end-of-line
+"\C-f": forward-char
+"\C-h": backward-delete-char
+"\C-k": kill-line
+"\C-l": clear-screen
+"\C-n": history-search-forward
+"\C-p": history-search-backward
+
+# "\e-b": backward-word
+# "\e-f": forward-word
+
+# "(": "\C-v()\C-b"
+# "[": "\C-v[]\C-b"
+# "{": "\C-v{}\C-b"
+# "\"": "\C-v\"\C-v\"\C-b"
+# Single quote (')
+# "\047": "\C-v\047\C-v\047\C-b"
+"jk": vi-movement-mode
diff --git a/.config/shell/profile b/.config/shell/profile
new file mode 100644
index 0000000..1393c45
--- /dev/null
+++ b/.config/shell/profile
@@ -0,0 +1,268 @@
+#!/bin/sh
+
+export OPENER="open"
+export PAGER="less"
+export EDITOR="nvim"
+export BROWSER="w3m"
+export FILES="lf"
+export TERMINAL="st"
+export PREVIEWER="preview"
+
+XDG_CONFIG_HOME="$HOME/.config"
+XDG_DATA_HOME="$HOME/.local/share"
+XDG_STATE_HOME="$HOME/.local/state"
+XDG_CACHE_HOME="$HOME/.cache"
+
+export MOUNTPATH="/run/media/$USER"
+export JUPYTER_CONFIG_DIR="$XDG_CONFIG_HOME/jupyter"
+export W3M_DIR="$XDG_CONFIG_HOME/w3m"
+export NCFTPDIR="$XDG_DATA_HOME/ncftp"
+export PASSWORD_STORE_DIR="$HOME/Phone/Backup/pass"
+export ANDROID_USER_HOME="$XDG_DATA_HOME/android"
+export __GL_SHADER_DISK_CACHE_PATH="$HOME/.cache/nv"
+
+export XINITRC="$XDG_CONFIG_HOME/X11/xinitrc"
+export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
+export INPUTRC="$XDG_CONFIG_HOME/shell/inputrc"
+export WGETRC="$XDG_CONFIG_HOME/wget/wgetrc"
+export PYTHONSTARTUP="$XDG_CONFIG_HOME/python/pythonrc"
+export IPYTHONDIR="$XDG_CONFIG_HOME/ipython"
+export NOTMUCH_CONFIG="$XDG_CONFIG_HOME/notmuch/config"
+export MBSYNCRC="$XDG_CONFIG_HOME/isyncrc"
+
+export LESSHISTFILE="$XDG_DATA_HOME/less/history"
+export FZF_HIST_FILE="$XDG_DATA_HOME/fzf/history"
+export SDCV_HISTFILE="$XDG_DATA_HOME/sdcv"
+export R_ENVIRON_USER="$XDG_DATA_HOME/R/.Renviron"
+export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
+export GOPATH="$XDG_DATA_HOME/go"
+export SQLITE_HISTORY="$XDG_DATA_HOME/sqlite_history"
+
+# program configuration
+export LESS='-Rf --mouse --use-color -Dd+r$Du+b$'
+export LESSOPEN='|lessopen.sh %s'
+export GROFF_NO_SGR=1
+export GTK_IM_MODULE='fcitx'
+export QT_IM_MODULE='fcitx'
+export SDL_IM_MODULE='fcitx'
+export XMODIFIERS='@im=fcitx'
+export QT_QPA_PLATFORMTHEME='qt5ct'
+export QT_FONT_DPI=112
+export SDCV_PAGER='less -R --quit-if-one-screen'
+export HTTP_HOME='https://www.duckduckgo.com'
+export CHROME_EXECUTABLE='chromium'
+export FZF_DEFAULT_COMMAND="find -L . ! -wholename '*.git*' \( -type d -printf '%p/\n' , ! -type d -print \)"
+export FZF_DEFAULT_OPTS="
+ --history='$XDG_DATA_HOME/fzf/history'
+ --preview='\$PREVIEWER {}' --preview-window=hidden
+ --bind 'ctrl-s:toggle-sort'
+ --bind 'ctrl-y:execute-silent(printf \"%s\\\n\" {+} | xsel --clipboard)'
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview'
+ --bind 'alt-space:toggle-preview,alt-w:toggle-preview-wrap'
+ --bind 'alt-enter:print-query'
+ --bind 'ctrl-alt-c:change-preview-window(up|left:50%|down|right:50%)'
+ --bind 'ctrl-alt-a:select-all,ctrl-alt-d:deselect-all'
+ --bind 'alt-n:half-page-down,alt-p:half-page-up'
+ --bind 'alt-N:page-down,alt-P:page-up'
+ --bind 'alt-<:first,alt->:last'
+ --bind 'alt-J:preview-down,alt-K:preview-up'
+ --bind 'alt-j:preview-half-page-down,alt-k:preview-half-page-up'
+ --bind 'alt-l:preview-page-down,alt-h:preview-page-up'
+ --bind 'alt-H:preview-top,alt-L:preview-bottom'
+ --bind 'alt-g:preview-top,alt-G:preview-bottom'
+ --bind 'alt-s:execute(dmenu-send {})'
+ --bind 'alt-0:change-preview(echo {})'
+ --bind 'alt-1:change-preview(highlight --out-format=ansi -- {} 2>/dev/null ||
+ ls -Als --group-directories-first --color=always --classify=always -- {})'
+ --bind 'alt-2:change-preview(\$PREVIEWER {})'
+ --bind 'alt-9:change-preview(printf \"%s\\\n\" {+})'
+ --bind 'alt-!:execute(less {})'
+ --bind 'alt-@:execute(\$PREVIEWER {} | less)'
+ --bind 'alt-v:execute(echo {q} >> \"$FZF_HIST_FILE\"; LESSOPEN=\"|preview %s\" less {})'
+ --bind 'alt-e:execute(echo {q} >> \"$FZF_HIST_FILE\"; eval \"\${EDITOR:-vi} {}\")'
+ --bind 'ctrl-o:execute(echo {q} >> \"$FZF_HIST_FILE\"; eval \"\${OPENER:-xdg-open} {}\")'
+ --bind 'alt-O:execute(echo {q} >> \"$FZF_HIST_FILE\"; mimeopen --ask {})'
+ --bind 'alt-o:execute(echo {q} >> \"$FZF_HIST_FILE\"; eval \"\${FILES:-lf} {}\")'
+ --bind 'alt-D:become(echo {q} >> \"$FZF_HIST_FILE\"; dirname {} )'
+ "
+
+## Custom themes for GTypist
+# export GTYPIST_OPTS="--color 3,0 --banner-color 0,1,2,3" # red-yellow
+# export GTYPIST_OPTS="--color 3,0 --banner-colors 0,2,4,1" # green-yellow
+export GTYPIST_OPTS="--color 6,0 --banner-color 0,4,5,1" # blue-cyan
+
+
+# # path
+# find -L ~/.local/share/gem/ruby/3.0.0/bin ~/.local/bin ~/bin \
+# -type d ! -wholename '*/.st*' |
+# while read -r dir; do
+# [ "$PATH" = "${PATH#*"$dir"}" ] && export PATH="$dir:$PATH"
+# done
+
+if [ "$PATH" = "${PATH#*"$HOME/.local/bin"}" ]; then
+ _build_path() { find -L "$@" -type d ! -wholename '*/.st*' ! -wholename '*.git*' -printf '%p:'; }
+ [ -d ~/bin ] && export PATH="$(_build_path ~/bin)$PATH"
+ [ -d ~/.local/bin ] && export PATH="$(_build_path ~/.local/bin)$PATH"
+ export PATH="$PATH:$XDG_DATA_HOME/gem/ruby/3.0.0/bin"
+ export PATH="$PATH:$HOME/Applications/flutter/bin"
+fi
+
+[ -n "$TERMUX_VERSION" ] && {
+ export STORAGE="$HOME/storage"
+}
+
+export BLOCK_COLOR_LEVEL1="#66FF99"
+export BLOCK_COLOR_LEVEL2="#AAEE66"
+export BLOCK_COLOR_LEVEL3="#CCCC33"
+export BLOCK_COLOR_LEVEL4="#FF7733"
+export BLOCK_COLOR_LEVEL5="#FF3333"
+
+LS_COLORS='rs=0:\
+di=01;34:\
+ln=01;36:\
+mh=00:\
+pi=40;33:\
+so=01;35:\
+do=01;35:\
+bd=40;33;01:\
+cd=40;33;01:\
+or=40;31;01:\
+mi=00:\
+su=37;41:\
+sg=30;43:\
+ca=00:\
+tw=30;42:\
+ow=34;42:\
+st=37;44:\
+ex=01;32:\
+*.tar=01;31:\
+*.tgz=01;31:\
+*.arc=01;31:\
+*.arj=01;31:\
+*.taz=01;31:\
+*.lha=01;31:\
+*.lz4=01;31:\
+*.lzh=01;31:\
+*.lzma=01;31:\
+*.tlz=01;31:\
+*.txz=01;31:\
+*.tzo=01;31:\
+*.t7z=01;31:\
+*.zip=01;31:\
+*.z=01;31:\
+*.dz=01;31:\
+*.gz=01;31:\
+*.lrz=01;31:\
+*.lz=01;31:\
+*.lzo=01;31:\
+*.xz=01;31:\
+*.zst=01;31:\
+*.tzst=01;31:\
+*.bz2=01;31:\
+*.bz=01;31:\
+*.tbz=01;31:\
+*.tbz2=01;31:\
+*.tz=01;31:\
+*.deb=01;31:\
+*.rpm=01;31:\
+*.jar=01;31:\
+*.war=01;31:\
+*.ear=01;31:\
+*.sar=01;31:\
+*.rar=01;31:\
+*.alz=01;31:\
+*.ace=01;31:\
+*.zoo=01;31:\
+*.cpio=01;31:\
+*.7z=01;31:\
+*.rz=01;31:\
+*.cab=01;31:\
+*.wim=01;31:\
+*.swm=01;31:\
+*.dwm=01;31:\
+*.esd=01;31:\
+*.avif=01;35:\
+*.jpg=01;35:\
+*.jpeg=01;35:\
+*.mjpg=01;35:\
+*.mjpeg=01;35:\
+*.gif=01;35:\
+*.bmp=01;35:\
+*.pbm=01;35:\
+*.pgm=01;35:\
+*.ppm=01;35:\
+*.tga=01;35:\
+*.xbm=01;35:\
+*.xpm=01;35:\
+*.tif=01;35:\
+*.tiff=01;35:\
+*.png=01;35:\
+*.svg=01;35:\
+*.svgz=01;35:\
+*.mng=01;35:\
+*.pcx=01;35:\
+*.mov=01;35:\
+*.mpg=01;35:\
+*.mpeg=01;35:\
+*.m2v=01;35:\
+*.mkv=01;35:\
+*.webm=01;35:\
+*.webp=01;35:\
+*.ogm=01;35:\
+*.mp4=01;35:\
+*.m4v=01;35:\
+*.mp4v=01;35:\
+*.vob=01;35:\
+*.qt=01;35:\
+*.nuv=01;35:\
+*.wmv=01;35:\
+*.asf=01;35:\
+*.rm=01;35:\
+*.rmvb=01;35:\
+*.flc=01;35:\
+*.avi=01;35:\
+*.fli=01;35:\
+*.flv=01;35:\
+*.gl=01;35:\
+*.dl=01;35:\
+*.xcf=01;35:\
+*.xwd=01;35:\
+*.yuv=01;35:\
+*.cgm=01;35:\
+*.emf=01;35:\
+*.ogv=01;35:\
+*.ogx=01;35:\
+*.aac=00;36:\
+*.au=00;36:\
+*.flac=00;36:\
+*.m4a=00;36:\
+*.mid=00;36:\
+*.midi=00;36:\
+*.mka=00;36:\
+*.mp3=00;36:\
+*.mpc=00;36:\
+*.ogg=00;36:\
+*.ra=00;36:\
+*.wav=00;36:\
+*.oga=00;36:\
+*.opus=00;36:\
+*.spx=00;36:\
+*.xspf=00;36:\
+*~=00;90:\
+*#=00;90:\
+*.bak=00;90:\
+*.old=00;90:\
+*.orig=00;90:\
+*.part=00;90:\
+*.rej=00;90:\
+*.swp=00;90:\
+*.tmp=00;90:\
+*.dpkg-dist=00;90:\
+*.dpkg-old=00;90:\
+*.ucf-dist=00;90:\
+*.ucf-new=00;90:\
+*.ucf-old=00;90:\
+*.rpmnew=00;90:\
+*.rpmorig=00;90:\
+*.rpmsave=00;90:\
+';
diff --git a/.config/terminal-colors.d/cal.scheme b/.config/terminal-colors.d/cal.scheme
new file mode 100644
index 0000000..5d04f39
--- /dev/null
+++ b/.config/terminal-colors.d/cal.scheme
@@ -0,0 +1,5 @@
+today 30;43
+weeknumber 30;43
+header 30;44
+workday lightgreen
+weekend yellow
diff --git a/.config/tmux/tmux-gruvbox-dark.conf b/.config/tmux/tmux-gruvbox-dark.conf
new file mode 100644
index 0000000..0c3a4f9
--- /dev/null
+++ b/.config/tmux/tmux-gruvbox-dark.conf
@@ -0,0 +1,53 @@
+## COLORSCHEME: gruvbox dark (medium)
+set-option -g status "on"
+
+# default statusbar color
+set-option -g status-style bg=colour237,fg=colour223 # bg=bg1, fg=fg1
+
+# default window title colors
+set-window-option -g window-status-style bg=colour214,fg=colour237 # bg=yellow, fg=bg1
+
+# default window with an activity alert
+set-window-option -g window-status-activity-style bg=colour237,fg=colour248 # bg=bg1, fg=fg3
+
+# active window title colors
+set-window-option -g window-status-current-style bg=red,fg=colour237 # fg=bg1
+
+# pane border
+set-option -g pane-active-border-style fg=colour250 #fg2
+set-option -g pane-border-style fg=colour237 #bg1
+
+# message infos
+set-option -g message-style bg=colour239,fg=colour223 # bg=bg2, fg=fg1
+
+# writing commands inactive
+set-option -g message-command-style bg=colour239,fg=colour223 # bg=fg3, fg=bg1
+
+# pane number display
+set-option -g display-panes-active-colour colour250 #fg2
+set-option -g display-panes-colour colour237 #bg1
+
+# clock
+set-window-option -g clock-mode-colour colour109 #blue
+
+# bell
+set-window-option -g window-status-bell-style bg=colour167,fg=colour235 # bg=red, fg=bg
+
+## Theme settings mixed with colors (unfortunately, but there is no cleaner way)
+set-option -g status-justify "left"
+set-option -g status-left-style none
+set-option -g status-left-length "80"
+set-option -g status-right-style none
+set-option -g status-right-length "80"
+set-window-option -g window-status-separator ""
+
+set-option -g status-left "#[bg=colour241,fg=colour248] #S #[bg=colour237,fg=colour241,nobold,noitalics,nounderscore]"
+# set-option -g status-right "#[bg=colour237,fg=colour239 nobold, nounderscore, noitalics]#[bg=colour239,fg=colour246] %Y-%m-%d  %H:%M #[bg=colour239,fg=colour248,nobold,noitalics,nounderscore]#[bg=colour248,fg=colour237] #h "
+
+set-window-option -g window-status-current-format "#[bg=colour214,fg=colour237,nobold,noitalics,nounderscore]#[bg=colour214,fg=colour239] #I #[bg=colour214,fg=colour239,bold] #W#{?window_zoomed_flag,*Z,} #[bg=colour237,fg=colour214,nobold,noitalics,nounderscore]"
+set-window-option -g window-status-format "#[bg=colour239,fg=colour237,noitalics]#[bg=colour239,fg=colour223] #I #[bg=colour239,fg=colour223] #W #[bg=colour237,fg=colour239,noitalics]"
+
+# vim: set ft=tmux tw=0 nowrap:
+
+# user configuration
+set-option -g status-right "#[bg=colour237,fg=colour248 nobold, nounderscore, noitalics]#[bg=colour248,fg=colour237] #h "
diff --git a/.config/tmux/tmux-gruvbox-light.conf b/.config/tmux/tmux-gruvbox-light.conf
new file mode 100644
index 0000000..8761966
--- /dev/null
+++ b/.config/tmux/tmux-gruvbox-light.conf
@@ -0,0 +1,56 @@
+## COLORSCHEME: gruvbox light (medium)
+#
+# Some colors are not used by gruvbox light medium theme.
+# The main idea is to find best version of colors that fit
+# the spirit of gruvbox light theme with limited numbers of
+# 256 color palette.
+
+set-option -g status "on"
+
+# default statusbar colors
+set-option -g status-style bg=colour252,fg=colour239 # bg=notInGruvboxPallete, #fg=fg1
+
+# default window title colors
+set-window-option -g window-status-style bg=colour66,fg=colour229 # bg=aqua, fg=bg5
+
+# default window with an activity alert
+set-window-option -g window-status-activity-style bg=colour237,fg=colour241 # bg=bg1, fg=notInGruvboxPallete
+
+# active window title colors
+set-window-option -g window-status-current-style bg=default,fg=colour237 # bg=default, fg=bg1
+
+# pane border
+set-option -g pane-active-border-style fg=colour241 # fg=notInGruvboxPallete
+set-option -g pane-border-style fg=colour252 # bg1=notInGruvboxPallete
+
+# message infos (visible while writing command)
+set-option -g message-style bg=colour252,fg=colour241 # bg=notInGruvboxPallete, fg=notInGruvboxPallete
+
+# writing commands inactive
+set-option -g message-command-style bg=colour124,fg=colour241 # bg=notInGruvboxPallete, fg=notInGruvboxPallete
+
+# pane number display
+set-option -g display-panes-active-colour colour241 # notInGruvboxPallete
+set-option -g display-panes-colour colour248 # notInGruvboxPallete
+
+# clock
+set-window-option -g clock-mode-colour colour172 # orange
+
+# bell
+set-window-option -g window-status-bell-style bg=colour124,fg=colour229 # bg=red, fg=bg
+
+## Theme settings mixed with colors (unfortunately, but there is no cleaner way)
+set-option -g status-justify "left"
+set-option -g status-left-style none
+set-option -g status-left-length "80"
+set-option -g status-right-style none
+set-option -g status-right-length "80"
+set-window-option -g window-status-separator ""
+
+set-option -g status-left "#[bg=colour243,fg=colour255] #S #[bg=colour252,fg=colour243,nobold,noitalics,nounderscore]"
+set-option -g status-right "#[bg=colour252,fg=colour243,nobold,nounderscore,noitalics]#[bg=colour243,fg=colour255] %Y-%m-%d  %H:%M #[bg=colour243,fg=colour237,nobold,noitalics,nounderscore]#[bg=colour237,fg=colour255] #h "
+
+set-window-option -g window-status-current-format "#[bg=colour215,fg=colour252,nobold,noitalics,nounderscore]#[bg=colour215,fg=colour239] #I #[bg=colour215,fg=colour239,bold] #W#{?window_zoomed_flag,*Z,} #[bg=colour252,fg=colour215,nobold,noitalics,nounderscore]"
+set-window-option -g window-status-format "#[bg=colour249,fg=colour252,noitalics]#[bg=colour249,fg=colour241] #I #[bg=colour249,fg=colour241] #W #[bg=colour252,fg=colour249,noitalics]"
+
+# vim: set ft=tmux tw=0 nowrap:
diff --git a/.config/tmux/tmux-onedark-theme.tmux b/.config/tmux/tmux-onedark-theme.tmux
new file mode 100644
index 0000000..8150357
--- /dev/null
+++ b/.config/tmux/tmux-onedark-theme.tmux
@@ -0,0 +1,95 @@
+#!/bin/bash
+onedark_black="#282c34"
+onedark_blue="#61afef"
+onedark_yellow="#e5c07b"
+onedark_red="#e06c75"
+onedark_white="#aab2bf"
+onedark_green="#98c379"
+onedark_visual_grey="#3e4452"
+onedark_comment_grey="#5c6370"
+
+if [ -z "$SSH_CONNECTION" ] && [ -n "$TERMUX_VERSION" ]; then
+ onedark_white="#dddddd"
+fi
+
+get() {
+ local option=$1
+ local default_value=$2
+ local option_value="$(tmux show-option -gqv "$option")"
+
+ if [ -z "$option_value" ]; then
+ echo "$default_value"
+ else
+ echo "$option_value"
+ fi
+}
+
+set() {
+ local option=$1
+ local value=$2
+ tmux set-option -gq "$option" "$value"
+}
+
+setw() {
+ local option=$1
+ local value=$2
+ tmux set-window-option -gq "$option" "$value"
+}
+
+set "status" "on"
+set "status-justify" "left"
+
+set "status-left-length" "100"
+set "status-right-length" "100"
+set "status-right-attr" "none"
+
+set "message-fg" "$onedark_white"
+set "message-bg" "$onedark_black"
+
+set "message-command-fg" "$onedark_white"
+set "message-command-bg" "$onedark_black"
+
+set "status-attr" "none"
+set "status-left-attr" "none"
+
+setw "window-status-fg" "$onedark_black"
+setw "window-status-bg" "$onedark_black"
+setw "window-status-attr" "none"
+
+setw "window-status-activity-bg" "$onedark_black"
+setw "window-status-activity-fg" "$onedark_black"
+setw "window-status-activity-attr" "none"
+
+setw "window-status-separator" ""
+
+set "window-style" "fg=$onedark_comment_grey"
+set "window-active-style" "fg=$onedark_white"
+
+set "pane-border-fg" "$onedark_white"
+set "pane-border-bg" "$onedark_black"
+set "pane-active-border-fg" "$onedark_green"
+set "pane-active-border-bg" "$onedark_black"
+
+set "display-panes-active-colour" "$onedark_yellow"
+set "display-panes-colour" "$onedark_blue"
+
+set "status-bg" "$onedark_black"
+set "status-fg" "$onedark_white"
+
+set "@prefix_highlight_fg" "$onedark_black"
+set "@prefix_highlight_bg" "$onedark_green"
+set "@prefix_highlight_copy_mode_attr" "fg=$onedark_black,bg=$onedark_green"
+set "@prefix_highlight_output_prefix" "  "
+
+status_widgets=$(get "@onedark_widgets")
+time_format=$(get "@onedark_time_format" "%R")
+date_format=$(get "@onedark_date_format" "%d/%m/%Y")
+
+# set "status-right" "#[fg=$onedark_white,bg=$onedark_black,nounderscore,noitalics]${time_format}  ${date_format} #[fg=$onedark_visual_grey,bg=$onedark_black]#[fg=$onedark_visual_grey,bg=$onedark_visual_grey]#[fg=$onedark_white, bg=$onedark_visual_grey]${status_widgets} #[fg=$onedark_green,bg=$onedark_visual_grey,nobold,nounderscore,noitalics]#[fg=$onedark_black,bg=$onedark_green,bold] #h #[fg=$onedark_yellow, bg=$onedark_green]#[fg=$onedark_red,bg=$onedark_yellow]"
+set "status-left" "#[fg=$onedark_black,bg=$onedark_green,bold] #S #{prefix_highlight}#[fg=$onedark_green,bg=$onedark_black,nobold,nounderscore,noitalics]"
+
+set "window-status-format" "#[fg=$onedark_black,bg=$onedark_black,nobold,nounderscore,noitalics]#[fg=$onedark_white,bg=$onedark_black] #I  #W #[fg=$onedark_black,bg=$onedark_black,nobold,nounderscore,noitalics]"
+set "window-status-current-format" "#[fg=$onedark_black,bg=$onedark_visual_grey,nobold,nounderscore,noitalics]#[fg=$onedark_white,bg=$onedark_visual_grey,nobold] #I  #W #[fg=$onedark_visual_grey,bg=$onedark_black,nobold,nounderscore,noitalics]"
+
+# user configuration
+set "status-right" "#[bg=colour236,fg=colour248,nobold,noitalics,nounderscore]#[bg=colour248,fg=colour237] #h "
diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf
new file mode 100644
index 0000000..cc53fde
--- /dev/null
+++ b/.config/tmux/tmux.conf
@@ -0,0 +1,77 @@
+if-shell '[ "$COLORTERM" != "${COLORTERM#*truecolor}" ]' {
+ set -g default-terminal "tmux-256color"
+ set -ga terminal-overrides ',*256col*:Tc'
+ source ~/.config/tmux/tmux-gruvbox-dark.conf
+ # run 'bash ~/.config/tmux/tmux-onedark-theme.tmux'
+}
+
+if-shell '[ -z "$SSH_CONNECTION" ] && [ -n "$TERMUX_VERSION" ]' {
+ set -g status-right ""
+}
+
+# if-shell '[ -n "$TERMUX_VERSION" ]' {
+# set -g status-right ""
+# }
+
+if-shell '[ -z "$EDITOR" ]' 'EDITOR=vi'
+
+unbind C-b
+set -g prefix `
+bind ` send-prefix
+
+set-window-option -g mode-keys vi
+set -g status-keys vi
+bind h select-pane -L
+bind j select-pane -D
+bind k select-pane -U
+bind l select-pane -R
+bind -r C-h resize-pane -L
+bind -r C-j resize-pane -D
+bind -r C-k resize-pane -U
+bind -r C-l resize-pane -R
+bind -r M-h resize-pane -L 5
+bind -r M-j resize-pane -D 5
+bind -r M-k resize-pane -U 5
+bind -r M-l resize-pane -R 5
+
+bind -T copy-mode-vi u send -X halfpage-up
+bind -T copy-mode-vi d send -X halfpage-down
+bind -T copy-mode-vi i send -X cancel
+bind -T copy-mode-vi V send -X select-line
+bind -T copy-mode-vi v send -X rectangle-off \; send -X begin-selection
+bind -T copy-mode-vi C-v send -X rectangle-on \; send -X begin-selection
+bind -T copy-mode-vi p send -X copy-pipe \; paste-buffer
+bind -T copy-mode-vi y send -X copy-pipe
+bind -T copy-mode-vi Y send -X copy-pipe 'xclip -in -selection clipboard'
+bind -T copy-mode-vi MouseDragEnd1Pane send -X begin-selection -x
+
+bind -r \" split-window -c '#{pane_current_path}'
+bind -r % split-window -c '#{pane_current_path}' -h
+bind -r c new-window -c '#{pane_current_path}'
+bind -r \; last-window
+bind -r J rotate-window -D
+bind -r K rotate-window -U
+
+bind E new-window -t9 -n tmux.conf '$EDITOR ~/.config/tmux/tmux.conf'
+bind R source ~/.config/tmux/tmux.conf \; display "sourced config"
+bind H new-window -n tmux.help 'man tmux'
+bind G new-window -t0 gotop
+
+set -g base-index 1
+set -g escape-time 20
+set -g mouse on
+set -g display-time 0
+set -g history-limit 1000000
+
+set -g lock-command vlock
+# set -g lock-after-time 300
+bind Home lock-server
+bind End lock-session
+bind Delete lock-client
+
+bind -r C-u run -b 'brightness up'
+bind -r C-d run -b 'brightness down'
+
+# if -F "#{==:#{session_windows},1}" "set status off" "set status on"
+ set-hook -g window-linked 'if -F "#{==:#{session_windows},1}" "set status off" "set status on"'
+ set-hook -g window-unlinked 'if -F "#{==:#{session_windows},1}" "set status off" "set status on"'
diff --git a/.config/wget/wgetrc b/.config/wget/wgetrc
new file mode 100644
index 0000000..4fd7999
--- /dev/null
+++ b/.config/wget/wgetrc
@@ -0,0 +1 @@
+hsts-file=~/.cache/wget-hsts
diff --git a/.config/yt-dlp/channel.conf b/.config/yt-dlp/channel.conf
new file mode 100644
index 0000000..c742d18
--- /dev/null
+++ b/.config/yt-dlp/channel.conf
@@ -0,0 +1,12 @@
+--config videos.conf
+
+--output '%(channel)s/%(title)s.%(ext)s'
+--output 'thumbnail:%(channel)s/.thumbnail/%(title)s.%(ext)s'
+--output 'description:%(channel)s/.description/%(title)s.txt'
+
+--print-to-file %(title)s.%(ext)s %(channel)s/%(channel)s.channel.pl.txt
+# --playlist-items ::-1
+
+--write-thumbnail
+--write-playlist-metafiles
+--download-archive .info/archive.txt
diff --git a/.config/yt-dlp/config b/.config/yt-dlp/config
new file mode 100644
index 0000000..3c9c2e1
--- /dev/null
+++ b/.config/yt-dlp/config
@@ -0,0 +1,14 @@
+--output %(title)s.%(ext)s
+--restrict-filenames
+
+--format bestvideo*[height<=1080][fps<=30]+bestaudio
+--prefer-free-format
+
+--write-subs
+--write-auto-subs
+--convert-subs srt
+--embed-subs
+
+--write-description
+--embed-metadata
+--embed-chapters
diff --git a/.config/yt-dlp/playlist.conf b/.config/yt-dlp/playlist.conf
new file mode 100644
index 0000000..26adc67
--- /dev/null
+++ b/.config/yt-dlp/playlist.conf
@@ -0,0 +1,12 @@
+--config videos.conf
+
+--output '%(playlist)s/%(title)s.%(ext)s'
+--output 'thumbnail:%(playlist)s/.thumbnail/%(title)s.%(ext)s'
+--output 'description:%(playlist)s/.description/%(title)s.txt'
+
+--print-to-file %(title)s %(playlist)s/%(playlist)s.pl.txt
+--playlist-items ::-1
+
+--write-thumbnail
+--write-playlist-metafiles
+--download-archive archive.txt
diff --git a/.config/yt-dlp/sequenced-playlist.conf b/.config/yt-dlp/sequenced-playlist.conf
new file mode 100644
index 0000000..7d3f88e
--- /dev/null
+++ b/.config/yt-dlp/sequenced-playlist.conf
@@ -0,0 +1,7 @@
+--config playlist.conf
+
+--output '%(playlist)s/%(playlist_autonumber)s %(title)s.%(ext)s'
+--output 'thumbnail:%(playlist)s/.thumbnail/%(playlist_autonumber)s %(title)s.%(ext)s'
+--output 'description:%(playlist)s/.description/%(playlist_autonumber)s %(title)s'
+
+--playlist-items ::1
diff --git a/.config/yt-dlp/videos.conf b/.config/yt-dlp/videos.conf
new file mode 100644
index 0000000..cecd1bb
--- /dev/null
+++ b/.config/yt-dlp/videos.conf
@@ -0,0 +1,2 @@
+--config config
+--format bestvideo*[height<=720][fps<=30]+bestaudio
diff --git a/.config/zathura/zathurarc b/.config/zathura/zathurarc
new file mode 100644
index 0000000..064e442
--- /dev/null
+++ b/.config/zathura/zathurarc
@@ -0,0 +1,10 @@
+map u scroll half-up
+map d scroll half-down
+map D toggle_page_mode
+
+map > rotate rotate-cw
+map < rotate rotate-ccw
+
+set selection-notification false
+set selection-clipboard clipboard
+set font 'monospace normal 14'
diff --git a/.config/zsh/.zshrc b/.config/zsh/.zshrc
new file mode 100644
index 0000000..3f7ed30
--- /dev/null
+++ b/.config/zsh/.zshrc
@@ -0,0 +1,293 @@
+#############################
+## SHELL CONFIGURATION ##
+#############################
+
+bindkey -e
+alias find="2> >(grep -v 'Permission denied' >&2) find"
+
+source ~/.profile
+[ -n "$SDOTDIR" ] || SDOTDIR="${XDG_CONFIG_HOME:-$HOME/.config}/shell"
+[ -n "$ZDOTDIR" ] || ZDOTDIR="${XDG_CONFIG_HOME:-HOME/.config}/zsh"
+
+source "$ZDOTDIR/command-tools.zsh"
+source "$ZDOTDIR/plugins/fzf-completion.zsh"
+# source "$ZDOTDIR/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
+source "$ZDOTDIR/plugins/zsh-autosuggestions.zsh"
+
+setopt correct # Auto correct mistakes
+setopt extended_glob # Allows using regular expressions with *
+setopt rc_expand_param # Array expension with parameters
+setopt no_check_jobs # Don't warn about running processes when exiting
+setopt rm_star_silent # Don't warn when using glob with rm
+setopt numeric_glob_sort # Sort filenames numerically when it makes sense
+setopt no_beep # No beep
+setopt append_history # Immediately append history instead of overwriting
+setopt extended_history # Add timestamps to history
+setopt hist_ignore_all_dups # If a new command is a duplicate, remove the older one
+setopt auto_cd # if only directory path is entered, cd there.
+setopt auto_pushd # pushd on cd
+setopt pushd_ignore_dups # truncate duplicate directories
+setopt pushd_minus
+setopt interactive_comments # enable comments on the command line
+setopt histignorespace # ignore lines starting with a space
+
+# Enable colors and change prompt:
+autoload -U colors && colors
+PS1="%B%{$fg[red]%}[%{$fg[yellow]%}%n%{$fg[green]%}@%{$fg[blue]%}%M %{$fg[magenta]%}%1~%{$fg[red]%}]%{$reset_color%}$%b "
+#PS1="%B%{$fg[red]%} %~ >%{$fg[yellow]%}%{$reset_color%}%b "
+[ -n "$LF_LEVEL" ] && PS1="$PS1(lf: $LF_LEVEL) "
+
+# Change cursor shape for different vi modes.
+function zle-keymap-select {
+ case $KEYMAP in
+ vicmd) echo -ne '\e[1 q';; # block
+ viins|main) echo -ne '\e[5 q';; # beam
+ esac
+}
+zle -N zle-keymap-select
+zle-line-init() { echo -ne "\e[5 q"; }
+zle -N zle-line-init
+# echo -ne '\e[5 q' # Use beam shape cursor on startup.
+preexec() { echo -ne '\e[5 q' ;} # Use beam shape cursor for each new prompt.
+
+# Completion.
+autoload -Uz compinit
+compinit -d ~/.cache/zshcompdump-$ZSH_VERSION
+zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # Case insensitive tab completion
+zstyle ':completion:*' rehash true # automatically find new executables in path
+zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" # Colored completion (different colors for dirs/files/etc)
+zstyle ':completion:*' completer _expand _complete _ignored _approximate
+zstyle ':completion:*' menu select
+zstyle ':completion:*' select-prompt '%SScrolling active: current selection at %p%s'
+zstyle ':completion:*:descriptions' format '%U%F{cyan}%d%f%u'
+
+# Speed up completions
+zstyle ':completion:*' accept-exact '*(N)'
+zstyle ':completion:*' use-cache on
+zstyle ':completion:*' cache-path ~/.cache/zsh
+
+# automatically load bash completion functions
+autoload -U +X bashcompinit && bashcompinit
+source "$ZDOTDIR/completion/arduino-cli.zsh"
+
+ZSH_AUTOSUGGEST_STRATEGY=(history completion)
+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(end-of-line vi-end-of-line vi-add-eol)
+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS+=(forward-char vi-forward-char)
+
+HISTFILE="${XDG_DATA_HOME:=$HOME/.local/share}/zsh/history"
+HISTSIZE=100000
+SAVEHIST=50000
+
+unset WORDCHARS
+stty -ixon
+
+# Angular
+# _ng_yargs_completions()
+# {
+# local reply
+# local si=$IFS
+# IFS=$'
+# ' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" ng --get-yargs-completions "${words[@]}"))
+# IFS=$si
+# _describe 'values' reply
+# }
+# compdef _ng_yargs_completions ng
+
+
+_command_fail_hook() {
+ [ $? != 1 ] && return
+ if [ -n "$TMUX" ]; then
+ tmux send-keys C-p
+ elif [ -n "$XDOTOOL_WINDOW_ID" ]; then
+ xdotool key --window "$XDOTOOL_WINDOW_ID" ctrl+p
+ fi
+}
+add-zsh-hook precmd _command_fail_hook
+
+_cd_history_hook() {
+ sed -i "\|^$PWD$|d" "${XDG_DATA_HOME:-$HOME/.local/share}/cdhist"
+ echo "$PWD" >> "${XDG_DATA_HOME:-$HOME/.local/share}/cdhist"
+}
+add-zsh-hook -Uz chpwd _cd_history_hook
+
+
+autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
+zle -N up-line-or-beginning-search
+zle -N down-line-or-beginning-search
+
+bindkey -s '^[o' '^[q lfcd^M'
+bindkey -s '^[j' '^[q lfcd "$(ff)"^M'
+bindkey -s '^[l' '^[q l^M'
+bindkey -s '^[L' '^[q lsblk^M'
+bindkey -s '^[D' '^[q dirs -v^M'
+bindkey -s '^[i' '^[q pushd -1^M'
+bindkey -s '^[-' '^[q cd -^M'
+bindkey -s '^[B' '^[q bindkey | less^M'
+
+bindkey jk vi-cmd-mode
+bindkey "^j" autosuggest-execute
+bindkey '^P' up-line-or-beginning-search
+bindkey '^N' down-line-or-beginning-search
+bindkey '^[p' up-line-or-history
+bindkey '^[n' down-line-or-history
+bindkey '^[w' backward-kill-word
+
+autoload -U edit-command-line; zle -N edit-command-line
+bindkey '^[E' edit-command-line
+
+typeset -g -A key
+if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
+ autoload -Uz add-zle-hook-widget
+ function zle_application_mode_start { echoti smkx }
+ function zle_application_mode_stop { echoti rmkx }
+ add-zle-hook-widget -Uz zle-line-init zle_application_mode_start
+ add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop
+fi
+
+
+[ -n "$DISPLAY" ] && command -V xdotool >/dev/null &&
+ XDOTOOL_WINDOW_ID="$(xdotool getactivewindow)"
+
+[ -f "$BUFFER_CACHE" ] && {
+ {
+ if [ -n "$TMUX" ]; then
+ tmux send-keys -l "$(cat "$BUFFER_CACHE")"
+ elif [ -z "$TERMUX_VERSION" ]; then
+ xdotool type --window "$XDOTOOL_WINDOW_ID" "$(cat "$BUFFER_CACHE")"
+ fi
+ rm -f "$BUFFER_CACHE"
+ } & disown
+}
+
+BUFFER_CACHE="${ZCACHEDIR:=$HOME/.cache/zsh}/previous-command-buffer-$$.tmp"
+_exec-zsh() {
+ echo "$BUFFER" > "$BUFFER_CACHE"
+ BUFFER=' exec zsh'
+ zle accept-line
+}
+zle -N exec-zsh _exec-zsh
+bindkey '^[r' exec-zsh
+
+backward-delete-word-to-slash() {
+ local WORDCHARS=${WORDCHARS/\//}
+ zle backward-delete-word
+}
+zle -N backward-delete-word-to-slash
+bindkey '^W' backward-delete-word-to-slash
+
+_fzf-file-history() {
+ LBUFFER="${LBUFFER}$(sed "s|$HOME|~|" "${XDG_DATA_HOME:-$HOME/.local/share}/openhist" | fzf --tac --reverse --height 40% | sed "s/ /\\\ /")"
+ zle reset-prompt
+}
+zle -N fzf-file-history _fzf-file-history
+bindkey '^T' fzf-file-history
+
+_fzf-cd-widget() {
+ cdpath="$(eval "${FZF_CD_COMMAND:-find -L . -type d ! -wholename '*.git*' -printf '%p/\n'}" |
+ FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --reverse --height 40% $FZF_CD_OPTS" fzf |
+ sed 's/"/\\\"/')"
+ [ -z "$cdpath" ] && { zle reset-prompt; return; }
+ zle push-line
+ BUFFER="cd -- \"$cdpath\""
+ zle reset-prompt
+ zle accept-line
+}
+zle -N fzf-cd-widget _fzf-cd-widget
+bindkey '^[c' fzf-cd-widget
+
+_cd-path-history() {
+ FZF_CD_COMMAND="< ${XDG_DATA_HOME:-$HOME/.local/share}/cdhist" \
+ FZF_CD_OPTS="--tac --tiebreak=index --no-sort" \
+ zle fzf-cd-widget
+}
+zle -N cd-path-history _cd-path-history
+bindkey '^[k' cd-path-history
+
+_fzf-history-widget() {
+ zle vi-fetch-history -n "$(fc -rl 1 | fzf --height 40% -n2.. --tiebreak=index \
+ --preview 'echo {2..}' --preview-window up:50%:hidden:wrap \
+ --bind 'ctrl-y:execute-silent(echo -n {2..} | xsel --clipboard)' \
+ --query="$LBUFFER")"
+ zle reset-prompt
+}
+zle -N fzf-history-widget _fzf-history-widget
+bindkey '^R' fzf-history-widget
+
+
+get-help() {
+ [ "$1" != sudo ] && cmd="$1" || cmd="$2"
+ cmdinfo="$(command -v "$cmd")"
+ case "${$(whence -w "$cmd")##*: }" in
+ builtin) MANPAGER="less +/'^ $cmd'" man zshbuiltins && HELP_FOUND=1 ;;
+ reserved) MANPAGER="less +/'^reserved' +/'$cmd'" man zshall && HELP_FOUND=1 ;;
+ alias) echo "$cmdinfo"; cmd="$(alias "$cmd" | sed "s/$cmd='\(\S*\) .*'/\1/")" ;;
+ esac
+ [ -n "$cmdinfo" ] && help "$cmd" || help "$1"
+}
+alias run-help='get-help'
+alias which-command='where'
+
+_get-help() {
+ cmd=(${=BUFFER})
+ zle push-line
+ case "${cmd[1]}" in
+ gh|hugo|npm|git) BUFFER="help ${cmd[1]}-${cmd[2]}" ;;
+ *) BUFFER="get-help $cmd" ;;
+ esac
+ zle accept-line
+}
+zle -N get-help _get-help
+bindkey '^[H' get-help
+
+
+[ -f "$SDOTDIR/aliasrc" ] && source "$SDOTDIR/aliasrc"
+[ -f "$SDOTDIR/shortcutrc" ] && source "$SDOTDIR/shortcutrc"
+[ -f "$ZDOTDIR/zshnameddirrc" ] && source "$ZDOTDIR/zshnameddirrc"
+
+case "$TERM" in *256*)
+ if [ -x /bin/eza ] || [ -x /usr/bin/eza ]; then
+ alias l='exa -aF --group-directories-first --color=always --icons'
+ lt() { exa --group-directories-first --color=always \
+ --icons -FaT "$@" | less -rF; }
+ fi
+
+ command -V starship >/dev/null && {
+ eval "$(starship init zsh)"
+ function set_win_title(){
+ echo -ne "\033]0; $USER@$HOST:${PWD/$HOME/~} \007"
+ }
+ precmd_functions+=(set_win_title)
+ }
+ ;;
+esac
+
+alias p='pacman'
+alias sp='sudo pacman'
+alias sv='sudo sv'
+alias mmv='noglob zmv -W'
+alias s='sudo '
+alias mirror='sudo reflector -f 30 -l 30 --number 10 --verbose --save /etc/pacman.d/mirrorlist'
+alias mirrord='sudo reflector --latest 50 --number 20 --sort delay --save /etc/pacman.d/mirrorlist'
+alias cleanup='sudo pacman -Rns $(pacman -Qtdq)'
+alias fixpacman='sudo rm /var/lib/pacman/db.lck'
+alias gtypist="gtypist $GTYPIST_OPTS"
+alias typ='launch-gtypist -l "$(sed "/^gtypist lesson - \(.*\)$/!d; s//\1/" ~/Documents/Notes/QuickNote.md)"'
+alias typa='launch-gtypist -e 3 -l "$(sed "/^gtypist lesson - \(.*\)$/!d; s//\1/" ~/Documents/Notes/ak47.txt)"'
+
+f() {
+ ret=$?
+ [ -n "$1" ] && { pacman -F "$@"; return; }
+ [ "$ret" != 127 ] && echo "Return code of last command is not 127" >&2 && return 2
+ pacman -F "$(fc -s 2>&1 | tail -1 | cut -d\ -f5-)"
+}
+
+# Execute functions with sudo
+# sudofu() {
+# [[ "$(type -w $1)" == "$1: function" ]] &&
+# ARGS="$@" && sudo bash -c "$(declare -f $1); $ARGS"
+# }
+# alias ssudo='sudofu '
+
+# Load syntax highlighter; should be last.
+source "$ZDOTDIR/plugins/fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh"
+
diff --git a/.config/zsh/command-tools.zsh b/.config/zsh/command-tools.zsh
new file mode 100644
index 0000000..20126cb
--- /dev/null
+++ b/.config/zsh/command-tools.zsh
@@ -0,0 +1,61 @@
+whereis_alias() {
+ location="$(zsh -xic exit 2>&1 | sed -E "/alias[ '$]*$1=/!d" |
+ fzf --exit-0 --select-1 --ansi --header-first --header='Select alias location' |
+ sed -n "s|^\+\(/.*:[0-9]*\)>.*$|\1|p")"
+
+ if [ -z "$location" ]; then
+ echo "$0: '$1' not found in zsh debug log" >&2; return 1
+ elif [ "$location" != "${location#*shortcutrc}" ]; then
+ awk "/^$1/ {print FILENAME\":\"NR}" ~/.config/shell/bm-{files,dirs}
+ else
+ echo "$location"
+ fi
+}
+
+edit-command() {
+ [ -z "$1" ] && echo "USAGE: $0 <command>" >&2 && return 2
+ cmd="$1"
+ cmdtype=$(whence -w "$cmd" | cut -d: -f2 | tr -d ' ')
+
+ case "$cmdtype" in
+ alias)
+ query="alias ${cmd}="
+ location="$(whereis_alias "$cmd")" || return
+ file="${location%%:*}"
+ line="${location##*:}"
+ [ "$file" != "${file#*/bm-}" ] && query="^$cmd"
+ ;;
+ function)
+ query="^\s*${cmd}\s*()"
+ file=$(whence -v "$cmd" | awk '{print $NF}')
+ ;;
+ command)
+ file=$(whence -ps "$cmd" | awk -F' -> ' '{print $NF}')
+ case "$(file --mime-type --brief "$file")" in
+ text/*) $EDITOR "$file" ;;
+ *) echo "$0: not a text file: $file" >&2; return 2 ;;
+ esac
+ return
+ ;;
+ builtin) echo "$0: $cmd is a builtin command" >&2; return 2 ;;
+ reserved) echo "$0: $cmd is a reserved command" >&2; return 2 ;;
+ none) echo "$0: $cmd not found" >&2; return 2 ;;
+ *) echo "$0: unknown command type: $cmdtype" >&2; return 2 ;;
+ esac
+
+ if [ -n "$query" ]; then
+ $EDITOR +${line:-1} +/"$query" "$file"
+ else
+ $EDITOR "$file"
+ fi
+}
+
+_edit-command() {
+ [ -z "$BUFFER" ] && return 2
+ cmd=(${=BUFFER}); cmd="${cmd[1]}"
+ zle push-line
+ BUFFER="edit-command $cmd"
+ zle accept-line
+}
+zle -N edit-command _edit-command
+bindkey '^[e' edit-command
diff --git a/.config/zsh/plugins/fast-syntax-highlighting b/.config/zsh/plugins/fast-syntax-highlighting
new file mode 160000
+Subproject cf318e06a9b7c9f2219d78f41b46fa6e06011fd
diff --git a/.config/zsh/plugins/fzf-completion.zsh b/.config/zsh/plugins/fzf-completion.zsh
new file mode 100644
index 0000000..f12afca
--- /dev/null
+++ b/.config/zsh/plugins/fzf-completion.zsh
@@ -0,0 +1,329 @@
+# ____ ____
+# / __/___ / __/
+# / /_/_ / / /_
+# / __/ / /_/ __/
+# /_/ /___/_/ completion.zsh
+#
+# - $FZF_TMUX (default: 0)
+# - $FZF_TMUX_OPTS (default: '-d 40%')
+# - $FZF_COMPLETION_TRIGGER (default: '**')
+# - $FZF_COMPLETION_OPTS (default: empty)
+
+# Both branches of the following `if` do the same thing -- define
+# __fzf_completion_options such that `eval $__fzf_completion_options` sets
+# all options to the same values they currently have. We'll do just that at
+# the bottom of the file after changing options to what we prefer.
+#
+# IMPORTANT: Until we get to the `emulate` line, all words that *can* be quoted
+# *must* be quoted in order to prevent alias expansion. In addition, code must
+# be written in a way works with any set of zsh options. This is very tricky, so
+# careful when you change it.
+#
+# Start by loading the builtin zsh/parameter module. It provides `options`
+# associative array that stores current shell options.
+if 'zmodload' 'zsh/parameter' 2>'/dev/null' && (( ${+options} )); then
+ # This is the fast branch and it gets taken on virtually all Zsh installations.
+ #
+ # ${(kv)options[@]} expands to array of keys (option names) and values ("on"
+ # or "off"). The subsequent expansion# with (j: :) flag joins all elements
+ # together separated by spaces. __fzf_completion_options ends up with a value
+ # like this: "options=(shwordsplit off aliases on ...)".
+ __fzf_completion_options="options=(${(j: :)${(kv)options[@]}})"
+else
+ # This branch is much slower because it forks to get the names of all
+ # zsh options. It's possible to eliminate this fork but it's not worth the
+ # trouble because this branch gets taken only on very ancient or broken
+ # zsh installations.
+ () {
+ # That `()` above defines an anonymous function. This is essentially a scope
+ # for local parameters. We use it to avoid polluting global scope.
+ 'local' '__fzf_opt'
+ __fzf_completion_options="setopt"
+ # `set -o` prints one line for every zsh option. Each line contains option
+ # name, some spaces, and then either "on" or "off". We just want option names.
+ # Expansion with (@f) flag splits a string into lines. The outer expansion
+ # removes spaces and everything that follow them on every line. __fzf_opt
+ # ends up iterating over option names: shwordsplit, aliases, etc.
+ for __fzf_opt in "${(@)${(@f)$(set -o)}%% *}"; do
+ if [[ -o "$__fzf_opt" ]]; then
+ # Option $__fzf_opt is currently on, so remember to set it back on.
+ __fzf_completion_options+=" -o $__fzf_opt"
+ else
+ # Option $__fzf_opt is currently off, so remember to set it back off.
+ __fzf_completion_options+=" +o $__fzf_opt"
+ fi
+ done
+ # The value of __fzf_completion_options here looks like this:
+ # "setopt +o shwordsplit -o aliases ..."
+ }
+fi
+
+# Enable the default zsh options (those marked with <Z> in `man zshoptions`)
+# but without `aliases`. Aliases in functions are expanded when functions are
+# defined, so if we disable aliases here, we'll be sure to have no pesky
+# aliases in any of our functions. This way we won't need prefix every
+# command with `command` or to quote every word to defend against global
+# aliases. Note that `aliases` is not the only option that's important to
+# control. There are several others that could wreck havoc if they are set
+# to values we don't expect. With the following `emulate` command we
+# sidestep this issue entirely.
+'emulate' 'zsh' '-o' 'no_aliases'
+
+# This brace is the start of try-always block. The `always` part is like
+# `finally` in lesser languages. We use it to *always* restore user options.
+{
+
+# Bail out if not interactive shell.
+[[ -o interactive ]] || return 0
+
+# To use custom commands instead of find, override _fzf_compgen_{path,dir}
+if ! declare -f _fzf_compgen_path > /dev/null; then
+ _fzf_compgen_path() {
+ echo "$1"
+ command find -L "$1" \
+ -name .git -prune -o -name .hg -prune -o -name .svn -prune -o \( -type d -o -type f -o -type l \) \
+ -a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
+ }
+fi
+
+if ! declare -f _fzf_compgen_dir > /dev/null; then
+ _fzf_compgen_dir() {
+ command find -L "$1" \
+ -name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \
+ -a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
+ }
+fi
+
+###########################################################
+
+__fzf_comprun() {
+ if [[ "$(type _fzf_comprun 2>&1)" =~ function ]]; then
+ _fzf_comprun "$@"
+ elif [ -n "$TMUX_PANE" ] && { [ "${FZF_TMUX:-0}" != 0 ] || [ -n "$FZF_TMUX_OPTS" ]; }; then
+ shift
+ if [ -n "$FZF_TMUX_OPTS" ]; then
+ fzf-tmux ${(Q)${(Z+n+)FZF_TMUX_OPTS}} -- "$@"
+ else
+ fzf-tmux -d ${FZF_TMUX_HEIGHT:-40%} -- "$@"
+ fi
+ else
+ shift
+ fzf "$@"
+ fi
+}
+
+# Extract the name of the command. e.g. foo=1 bar baz**<tab>
+__fzf_extract_command() {
+ local token tokens
+ tokens=(${(z)1})
+ for token in $tokens; do
+ token=${(Q)token}
+ if [[ "$token" =~ [[:alnum:]] && ! "$token" =~ "=" ]]; then
+ echo "$token"
+ return
+ fi
+ done
+ echo "${tokens[1]}"
+}
+
+__fzf_generic_path_completion() {
+ local base lbuf cmd compgen fzf_opts suffix tail dir leftover matches
+ base=$1
+ lbuf=$2
+ cmd=$(__fzf_extract_command "$lbuf")
+ compgen=$3
+ fzf_opts=$4
+ suffix=$5
+ tail=$6
+
+ setopt localoptions nonomatch
+ eval "base=$base"
+ [[ $base = *"/"* ]] && dir="$base"
+ while [ 1 ]; do
+ if [[ -z "$dir" || -d ${dir} ]]; then
+ leftover=${base/#"$dir"}
+ leftover=${leftover/#\/}
+ [ -z "$dir" ] && dir='.'
+ [ "$dir" != "/" ] && dir="${dir/%\//}"
+ matches=$(eval "$compgen $(printf %q "$dir")" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_COMPLETION_OPTS" __fzf_comprun "$cmd" ${(Q)${(Z+n+)fzf_opts}} -q "$leftover" | while read item; do
+ echo -n "${(q)item}$suffix "
+ done)
+ matches=${matches% }
+ if [ -n "$matches" ]; then
+ LBUFFER="$lbuf$matches$tail"
+ fi
+ zle reset-prompt
+ break
+ fi
+ dir=$(dirname "$dir")
+ dir=${dir%/}/
+ done
+}
+
+_fzf_path_completion() {
+ __fzf_generic_path_completion "$1" "$2" _fzf_compgen_path \
+ "-m" "" " "
+}
+
+_fzf_dir_completion() {
+ __fzf_generic_path_completion "$1" "$2" _fzf_compgen_dir \
+ "" "/" ""
+}
+
+_fzf_feed_fifo() (
+ command rm -f "$1"
+ mkfifo "$1"
+ cat <&0 > "$1" &
+)
+
+_fzf_complete() {
+ setopt localoptions ksh_arrays
+ # Split arguments around --
+ local args rest str_arg i sep
+ args=("$@")
+ sep=
+ for i in {0..${#args[@]}}; do
+ if [[ "${args[$i]}" = -- ]]; then
+ sep=$i
+ break
+ fi
+ done
+ if [[ -n "$sep" ]]; then
+ str_arg=
+ rest=("${args[@]:$((sep + 1)):${#args[@]}}")
+ args=("${args[@]:0:$sep}")
+ else
+ str_arg=$1
+ args=()
+ shift
+ rest=("$@")
+ fi
+
+ local fifo lbuf cmd matches post
+ fifo="${TMPDIR:-/tmp}/fzf-complete-fifo-$$"
+ lbuf=${rest[0]}
+ cmd=$(__fzf_extract_command "$lbuf")
+ post="${funcstack[1]}_post"
+ type $post > /dev/null 2>&1 || post=cat
+
+ _fzf_feed_fifo "$fifo"
+ matches=$(FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_COMPLETION_OPTS $str_arg" __fzf_comprun "$cmd" "${args[@]}" -q "${(Q)prefix}" < "$fifo" | $post | tr '\n' ' ')
+ if [ -n "$matches" ]; then
+ LBUFFER="$lbuf$matches"
+ fi
+ command rm -f "$fifo"
+}
+
+_fzf_complete_telnet() {
+ _fzf_complete +m -- "$@" < <(
+ command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0' |
+ awk '{if (length($2) > 0) {print $2}}' | sort -u
+ )
+}
+
+_fzf_complete_ssh() {
+ _fzf_complete +m -- "$@" < <(
+ setopt localoptions nonomatch
+ command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2> /dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?]') \
+ <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
+ <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
+ awk '{if (length($2) > 0) {print $2}}' | sort -u
+ )
+}
+
+_fzf_complete_export() {
+ _fzf_complete -m -- "$@" < <(
+ declare -xp | sed 's/=.*//' | sed 's/.* //'
+ )
+}
+
+_fzf_complete_unset() {
+ _fzf_complete -m -- "$@" < <(
+ declare -xp | sed 's/=.*//' | sed 's/.* //'
+ )
+}
+
+_fzf_complete_unalias() {
+ _fzf_complete +m -- "$@" < <(
+ alias | sed 's/=.*//'
+ )
+}
+
+_fzf_complete_kill() {
+ _fzf_complete -m --preview 'echo {}' --preview-window down:3:wrap --min-height 15 -- "$@" < <(
+ command ps -ef | sed 1d
+ )
+}
+
+_fzf_complete_kill_post() {
+ awk '{print $2}'
+}
+
+fzf-completion() {
+ local tokens cmd prefix trigger tail matches lbuf d_cmds
+ setopt localoptions noshwordsplit noksh_arrays noposixbuiltins
+
+ # http://zsh.sourceforge.net/FAQ/zshfaq03.html
+ # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags
+ tokens=(${(z)LBUFFER})
+ if [ ${#tokens} -lt 1 ]; then
+ zle ${fzf_default_completion:-expand-or-complete}
+ return
+ fi
+
+ cmd=$(__fzf_extract_command "$LBUFFER")
+
+ # Explicitly allow for empty trigger.
+ trigger=${FZF_COMPLETION_TRIGGER-'**'}
+ [ -z "$trigger" -a ${LBUFFER[-1]} = ' ' ] && tokens+=("")
+
+ # When the trigger starts with ';', it becomes a separate token
+ if [[ ${LBUFFER} = *"${tokens[-2]}${tokens[-1]}" ]]; then
+ tokens[-2]="${tokens[-2]}${tokens[-1]}"
+ tokens=(${tokens[0,-2]})
+ fi
+
+ lbuf=$LBUFFER
+ tail=${LBUFFER:$(( ${#LBUFFER} - ${#trigger} ))}
+ # Kill completion (do not require trigger sequence)
+ if [ "$cmd" = kill -a ${LBUFFER[-1]} = ' ' ]; then
+ tail=$trigger
+ tokens+=$trigger
+ lbuf="$lbuf$trigger"
+ fi
+
+ # Trigger sequence given
+ if [ ${#tokens} -gt 1 -a "$tail" = "$trigger" ]; then
+ d_cmds=(${=FZF_COMPLETION_DIR_COMMANDS:-cd pushd rmdir})
+
+ [ -z "$trigger" ] && prefix=${tokens[-1]} || prefix=${tokens[-1]:0:-${#trigger}}
+ [ -n "${tokens[-1]}" ] && lbuf=${lbuf:0:-${#tokens[-1]}}
+
+ if eval "type _fzf_complete_${cmd} > /dev/null"; then
+ prefix="$prefix" eval _fzf_complete_${cmd} ${(q)lbuf}
+ zle reset-prompt
+ elif [ ${d_cmds[(i)$cmd]} -le ${#d_cmds} ]; then
+ _fzf_dir_completion "$prefix" "$lbuf"
+ else
+ _fzf_path_completion "$prefix" "$lbuf"
+ fi
+ # Fall back to default completion
+ else
+ zle ${fzf_default_completion:-expand-or-complete}
+ fi
+}
+
+[ -z "$fzf_default_completion" ] && {
+ binding=$(bindkey '^I')
+ [[ $binding =~ 'undefined-key' ]] || fzf_default_completion=$binding[(s: :w)2]
+ unset binding
+}
+
+zle -N fzf-completion
+bindkey '^I' fzf-completion
+
+} always {
+ # Restore the original options.
+ eval $__fzf_completion_options
+ 'unset' '__fzf_completion_options'
+}
diff --git a/.config/zsh/plugins/zsh-autosuggestions.zsh b/.config/zsh/plugins/zsh-autosuggestions.zsh
new file mode 100644
index 0000000..b19cac7
--- /dev/null
+++ b/.config/zsh/plugins/zsh-autosuggestions.zsh
@@ -0,0 +1,864 @@
+# Fish-like fast/unobtrusive autosuggestions for zsh.
+# https://github.com/zsh-users/zsh-autosuggestions
+# v0.7.0
+# Copyright (c) 2013 Thiago de Arruda
+# Copyright (c) 2016-2021 Eric Freese
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+#--------------------------------------------------------------------#
+# Global Configuration Variables #
+#--------------------------------------------------------------------#
+
+# Color to use when highlighting suggestion
+# Uses format of `region_highlight`
+# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
+(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
+typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
+
+# Prefix to use when saving original versions of bound widgets
+(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
+typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
+
+# Strategies to use to fetch a suggestion
+# Will try each strategy in order until a suggestion is returned
+(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && {
+ typeset -ga ZSH_AUTOSUGGEST_STRATEGY
+ ZSH_AUTOSUGGEST_STRATEGY=(history)
+}
+
+# Widgets that clear the suggestion
+(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
+ typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
+ ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
+ history-search-forward
+ history-search-backward
+ history-beginning-search-forward
+ history-beginning-search-backward
+ history-substring-search-up
+ history-substring-search-down
+ up-line-or-beginning-search
+ down-line-or-beginning-search
+ up-line-or-history
+ down-line-or-history
+ accept-line
+ copy-earlier-word
+ )
+}
+
+# Widgets that accept the entire suggestion
+(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
+ typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS
+ ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
+ forward-char
+ end-of-line
+ vi-forward-char
+ vi-end-of-line
+ vi-add-eol
+ )
+}
+
+# Widgets that accept the entire suggestion and execute it
+(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
+ typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS
+ ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
+ )
+}
+
+# Widgets that accept the suggestion as far as the cursor moves
+(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
+ typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
+ ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
+ forward-word
+ emacs-forward-word
+ vi-forward-word
+ vi-forward-word-end
+ vi-forward-blank-word
+ vi-forward-blank-word-end
+ vi-find-next-char
+ vi-find-next-char-skip
+ )
+}
+
+# Widgets that should be ignored (globbing supported but must be escaped)
+(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
+ typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS
+ ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
+ orig-\*
+ beep
+ run-help
+ set-local-history
+ which-command
+ yank
+ yank-pop
+ zle-\*
+ )
+}
+
+# Pty name for capturing completions for completion suggestion strategy
+(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
+typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty
+
+#--------------------------------------------------------------------#
+# Utility Functions #
+#--------------------------------------------------------------------#
+
+_zsh_autosuggest_escape_command() {
+ setopt localoptions EXTENDED_GLOB
+
+ # Escape special chars in the string (requires EXTENDED_GLOB)
+ echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
+}
+
+#--------------------------------------------------------------------#
+# Widget Helpers #
+#--------------------------------------------------------------------#
+
+_zsh_autosuggest_incr_bind_count() {
+ typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1))
+ _ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
+}
+
+# Bind a single widget to an autosuggest widget, saving a reference to the original widget
+_zsh_autosuggest_bind_widget() {
+ typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS
+
+ local widget=$1
+ local autosuggest_action=$2
+ local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
+
+ local -i bind_count
+
+ # Save a reference to the original widget
+ case $widgets[$widget] in
+ # Already bound
+ user:_zsh_autosuggest_(bound|orig)_*)
+ bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget]))
+ ;;
+
+ # User-defined widget
+ user:*)
+ _zsh_autosuggest_incr_bind_count $widget
+ zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
+ ;;
+
+ # Built-in widget
+ builtin)
+ _zsh_autosuggest_incr_bind_count $widget
+ eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
+ zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget
+ ;;
+
+ # Completion widget
+ completion:*)
+ _zsh_autosuggest_incr_bind_count $widget
+ eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
+ ;;
+ esac
+
+ # Pass the original widget's name explicitly into the autosuggest
+ # function. Use this passed in widget name to call the original
+ # widget instead of relying on the $WIDGET variable being set
+ # correctly. $WIDGET cannot be trusted because other plugins call
+ # zle without the `-w` flag (e.g. `zle self-insert` instead of
+ # `zle self-insert -w`).
+ eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() {
+ _zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
+ }"
+
+ # Create the bound widget
+ zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget
+}
+
+# Map all configured widgets to the right autosuggest widgets
+_zsh_autosuggest_bind_widgets() {
+ emulate -L zsh
+
+ local widget
+ local ignore_widgets
+
+ ignore_widgets=(
+ .\*
+ _\*
+ ${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
+ $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
+ $ZSH_AUTOSUGGEST_IGNORE_WIDGETS
+ )
+
+ # Find every widget we might want to bind and bind it appropriately
+ for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
+ if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
+ _zsh_autosuggest_bind_widget $widget clear
+ elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
+ _zsh_autosuggest_bind_widget $widget accept
+ elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
+ _zsh_autosuggest_bind_widget $widget execute
+ elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
+ _zsh_autosuggest_bind_widget $widget partial_accept
+ else
+ # Assume any unspecified widget might modify the buffer
+ _zsh_autosuggest_bind_widget $widget modify
+ fi
+ done
+}
+
+# Given the name of an original widget and args, invoke it, if it exists
+_zsh_autosuggest_invoke_original_widget() {
+ # Do nothing unless called with at least one arg
+ (( $# )) || return 0
+
+ local original_widget_name="$1"
+
+ shift
+
+ if (( ${+widgets[$original_widget_name]} )); then
+ zle $original_widget_name -- $@
+ fi
+}
+
+#--------------------------------------------------------------------#
+# Highlighting #
+#--------------------------------------------------------------------#
+
+# If there was a highlight, remove it
+_zsh_autosuggest_highlight_reset() {
+ typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+
+ if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
+ region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
+ unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+ fi
+}
+
+# If there's a suggestion, highlight it
+_zsh_autosuggest_highlight_apply() {
+ typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+
+ if (( $#POSTDISPLAY )); then
+ typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
+ region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
+ else
+ unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+ fi
+}
+
+#--------------------------------------------------------------------#
+# Autosuggest Widget Implementations #
+#--------------------------------------------------------------------#
+
+# Disable suggestions
+_zsh_autosuggest_disable() {
+ typeset -g _ZSH_AUTOSUGGEST_DISABLED
+ _zsh_autosuggest_clear
+}
+
+# Enable suggestions
+_zsh_autosuggest_enable() {
+ unset _ZSH_AUTOSUGGEST_DISABLED
+
+ if (( $#BUFFER )); then
+ _zsh_autosuggest_fetch
+ fi
+}
+
+# Toggle suggestions (enable/disable)
+_zsh_autosuggest_toggle() {
+ if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
+ _zsh_autosuggest_enable
+ else
+ _zsh_autosuggest_disable
+ fi
+}
+
+# Clear the suggestion
+_zsh_autosuggest_clear() {
+ # Remove the suggestion
+ unset POSTDISPLAY
+
+ _zsh_autosuggest_invoke_original_widget $@
+}
+
+# Modify the buffer and get a new suggestion
+_zsh_autosuggest_modify() {
+ local -i retval
+
+ # Only available in zsh >= 5.4
+ local -i KEYS_QUEUED_COUNT
+
+ # Save the contents of the buffer/postdisplay
+ local orig_buffer="$BUFFER"
+ local orig_postdisplay="$POSTDISPLAY"
+
+ # Clear suggestion while waiting for next one
+ unset POSTDISPLAY
+
+ # Original widget may modify the buffer
+ _zsh_autosuggest_invoke_original_widget $@
+ retval=$?
+
+ emulate -L zsh
+
+ # Don't fetch a new suggestion if there's more input to be read immediately
+ if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then
+ POSTDISPLAY="$orig_postdisplay"
+ return $retval
+ fi
+
+ # Optimize if manually typing in the suggestion or if buffer hasn't changed
+ if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
+ POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
+ return $retval
+ fi
+
+ # Bail out if suggestions are disabled
+ if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
+ return $?
+ fi
+
+ # Get a new suggestion if the buffer is not empty after modification
+ if (( $#BUFFER > 0 )); then
+ if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then
+ _zsh_autosuggest_fetch
+ fi
+ fi
+
+ return $retval
+}
+
+# Fetch a new suggestion based on what's currently in the buffer
+_zsh_autosuggest_fetch() {
+ if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then
+ _zsh_autosuggest_async_request "$BUFFER"
+ else
+ local suggestion
+ _zsh_autosuggest_fetch_suggestion "$BUFFER"
+ _zsh_autosuggest_suggest "$suggestion"
+ fi
+}
+
+# Offer a suggestion
+_zsh_autosuggest_suggest() {
+ emulate -L zsh
+
+ local suggestion="$1"
+
+ if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
+ POSTDISPLAY="${suggestion#$BUFFER}"
+ else
+ unset POSTDISPLAY
+ fi
+}
+
+# Accept the entire suggestion
+_zsh_autosuggest_accept() {
+ local -i retval max_cursor_pos=$#BUFFER
+
+ # When vicmd keymap is active, the cursor can't move all the way
+ # to the end of the buffer
+ if [[ "$KEYMAP" = "vicmd" ]]; then
+ max_cursor_pos=$((max_cursor_pos - 1))
+ fi
+
+ # If we're not in a valid state to accept a suggestion, just run the
+ # original widget and bail out
+ if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then
+ _zsh_autosuggest_invoke_original_widget $@
+ return
+ fi
+
+ # Only accept if the cursor is at the end of the buffer
+ # Add the suggestion to the buffer
+ BUFFER="$BUFFER$POSTDISPLAY"
+
+ # Remove the suggestion
+ unset POSTDISPLAY
+
+ # Run the original widget before manually moving the cursor so that the
+ # cursor movement doesn't make the widget do something unexpected
+ _zsh_autosuggest_invoke_original_widget $@
+ retval=$?
+
+ # Move the cursor to the end of the buffer
+ if [[ "$KEYMAP" = "vicmd" ]]; then
+ CURSOR=$(($#BUFFER - 1))
+ else
+ CURSOR=$#BUFFER
+ fi
+
+ return $retval
+}
+
+# Accept the entire suggestion and execute it
+_zsh_autosuggest_execute() {
+ # Add the suggestion to the buffer
+ BUFFER="$BUFFER$POSTDISPLAY"
+
+ # Remove the suggestion
+ unset POSTDISPLAY
+
+ # Call the original `accept-line` to handle syntax highlighting or
+ # other potential custom behavior
+ _zsh_autosuggest_invoke_original_widget "accept-line"
+}
+
+# Partially accept the suggestion
+_zsh_autosuggest_partial_accept() {
+ local -i retval cursor_loc
+
+ # Save the contents of the buffer so we can restore later if needed
+ local original_buffer="$BUFFER"
+
+ # Temporarily accept the suggestion.
+ BUFFER="$BUFFER$POSTDISPLAY"
+
+ # Original widget moves the cursor
+ _zsh_autosuggest_invoke_original_widget $@
+ retval=$?
+
+ # Normalize cursor location across vi/emacs modes
+ cursor_loc=$CURSOR
+ if [[ "$KEYMAP" = "vicmd" ]]; then
+ cursor_loc=$((cursor_loc + 1))
+ fi
+
+ # If we've moved past the end of the original buffer
+ if (( $cursor_loc > $#original_buffer )); then
+ # Set POSTDISPLAY to text right of the cursor
+ POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
+
+ # Clip the buffer at the cursor
+ BUFFER="${BUFFER[1,$cursor_loc]}"
+ else
+ # Restore the original buffer
+ BUFFER="$original_buffer"
+ fi
+
+ return $retval
+}
+
+() {
+ typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
+
+ _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
+ clear
+ fetch
+ suggest
+ accept
+ execute
+ enable
+ disable
+ toggle
+ )
+
+ local action
+ for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
+ eval "_zsh_autosuggest_widget_$action() {
+ local -i retval
+
+ _zsh_autosuggest_highlight_reset
+
+ _zsh_autosuggest_$action \$@
+ retval=\$?
+
+ _zsh_autosuggest_highlight_apply
+
+ zle -R
+
+ return \$retval
+ }"
+ done
+
+ for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
+ zle -N autosuggest-$action _zsh_autosuggest_widget_$action
+ done
+}
+
+#--------------------------------------------------------------------#
+# Completion Suggestion Strategy #
+#--------------------------------------------------------------------#
+# Fetches a suggestion from the completion engine
+#
+
+_zsh_autosuggest_capture_postcompletion() {
+ # Always insert the first completion into the buffer
+ compstate[insert]=1
+
+ # Don't list completions
+ unset 'compstate[list]'
+}
+
+_zsh_autosuggest_capture_completion_widget() {
+ # Add a post-completion hook to be called after all completions have been
+ # gathered. The hook can modify compstate to affect what is done with the
+ # gathered completions.
+ local -a +h comppostfuncs
+ comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
+
+ # Only capture completions at the end of the buffer
+ CURSOR=$#BUFFER
+
+ # Run the original widget wrapping `.complete-word` so we don't
+ # recursively try to fetch suggestions, since our pty is forked
+ # after autosuggestions is initialized.
+ zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
+
+ if is-at-least 5.0.3; then
+ # Don't do any cr/lf transformations. We need to do this immediately before
+ # output because if we do it in setup, onlcr will be re-enabled when we enter
+ # vared in the async code path. There is a bug in zpty module in older versions
+ # where the tty is not properly attached to the pty slave, resulting in stty
+ # getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream
+ # commit f75904a38
+ stty -onlcr -ocrnl -F /dev/tty
+ fi
+
+ # The completion has been added, print the buffer as the suggestion
+ echo -nE - $'\0'$BUFFER$'\0'
+}
+
+zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
+
+_zsh_autosuggest_capture_setup() {
+ # There is a bug in zpty module in older zsh versions by which a
+ # zpty that exits will kill all zpty processes that were forked
+ # before it. Here we set up a zsh exit hook to SIGKILL the zpty
+ # process immediately, before it has a chance to kill any other
+ # zpty processes.
+ if ! is-at-least 5.4; then
+ zshexit() {
+ # The zsh builtin `kill` fails sometimes in older versions
+ # https://unix.stackexchange.com/a/477647/156673
+ kill -KILL $$ 2>&- || command kill -KILL $$
+
+ # Block for long enough for the signal to come through
+ sleep 1
+ }
+ fi
+
+ # Try to avoid any suggestions that wouldn't match the prefix
+ zstyle ':completion:*' matcher-list ''
+ zstyle ':completion:*' path-completion false
+ zstyle ':completion:*' max-errors 0 not-numeric
+
+ bindkey '^I' autosuggest-capture-completion
+}
+
+_zsh_autosuggest_capture_completion_sync() {
+ _zsh_autosuggest_capture_setup
+
+ zle autosuggest-capture-completion
+}
+
+_zsh_autosuggest_capture_completion_async() {
+ _zsh_autosuggest_capture_setup
+
+ zmodload zsh/parameter 2>/dev/null || return # For `$functions`
+
+ # Make vared completion work as if for a normal command line
+ # https://stackoverflow.com/a/7057118/154703
+ autoload +X _complete
+ functions[_original_complete]=$functions[_complete]
+ function _complete() {
+ unset 'compstate[vared]'
+ _original_complete "$@"
+ }
+
+ # Open zle with buffer set so we can capture completions for it
+ vared 1
+}
+
+_zsh_autosuggest_strategy_completion() {
+ # Reset options to defaults and enable LOCAL_OPTIONS
+ emulate -L zsh
+
+ # Enable extended glob for completion ignore pattern
+ setopt EXTENDED_GLOB
+
+ typeset -g suggestion
+ local line REPLY
+
+ # Exit if we don't have completions
+ whence compdef >/dev/null || return
+
+ # Exit if we don't have zpty
+ zmodload zsh/zpty 2>/dev/null || return
+
+ # Exit if our search string matches the ignore pattern
+ [[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return
+
+ # Zle will be inactive if we are in async mode
+ if zle; then
+ zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
+ else
+ zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
+ zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
+ fi
+
+ {
+ # The completion result is surrounded by null bytes, so read the
+ # content between the first two null bytes.
+ zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
+
+ # Extract the suggestion from between the null bytes. On older
+ # versions of zsh (older than 5.3), we sometimes get extra bytes after
+ # the second null byte, so trim those off the end.
+ # See http://www.zsh.org/mla/workers/2015/msg03290.html
+ suggestion="${${(@0)line}[2]}"
+ } always {
+ # Destroy the pty
+ zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
+ }
+}
+
+#--------------------------------------------------------------------#
+# History Suggestion Strategy #
+#--------------------------------------------------------------------#
+# Suggests the most recent history item that matches the given
+# prefix.
+#
+
+_zsh_autosuggest_strategy_history() {
+ # Reset options to defaults and enable LOCAL_OPTIONS
+ emulate -L zsh
+
+ # Enable globbing flags so that we can use (#m) and (x~y) glob operator
+ setopt EXTENDED_GLOB
+
+ # Escape backslashes and all of the glob operators so we can use
+ # this string as a pattern to search the $history associative array.
+ # - (#m) globbing flag enables setting references for match data
+ # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
+ local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
+
+ # Get the history items that match the prefix, excluding those that match
+ # the ignore pattern
+ local pattern="$prefix*"
+ if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
+ pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
+ fi
+
+ # Give the first history item matching the pattern as the suggestion
+ # - (r) subscript flag makes the pattern match on values
+ typeset -g suggestion="${history[(r)$pattern]}"
+}
+
+#--------------------------------------------------------------------#
+# Match Previous Command Suggestion Strategy #
+#--------------------------------------------------------------------#
+# Suggests the most recent history item that matches the given
+# prefix and whose preceding history item also matches the most
+# recently executed command.
+#
+# For example, suppose your history has the following entries:
+# - pwd
+# - ls foo
+# - ls bar
+# - pwd
+#
+# Given the history list above, when you type 'ls', the suggestion
+# will be 'ls foo' rather than 'ls bar' because your most recently
+# executed command (pwd) was previously followed by 'ls foo'.
+#
+# Note that this strategy won't work as expected with ZSH options that don't
+# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
+# `HIST_EXPIRE_DUPS_FIRST`.
+
+_zsh_autosuggest_strategy_match_prev_cmd() {
+ # Reset options to defaults and enable LOCAL_OPTIONS
+ emulate -L zsh
+
+ # Enable globbing flags so that we can use (#m) and (x~y) glob operator
+ setopt EXTENDED_GLOB
+
+ # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
+ local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
+
+ # Get the history items that match the prefix, excluding those that match
+ # the ignore pattern
+ local pattern="$prefix*"
+ if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
+ pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
+ fi
+
+ # Get all history event numbers that correspond to history
+ # entries that match the pattern
+ local history_match_keys
+ history_match_keys=(${(k)history[(R)$~pattern]})
+
+ # By default we use the first history number (most recent history entry)
+ local histkey="${history_match_keys[1]}"
+
+ # Get the previously executed command
+ local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
+
+ # Iterate up to the first 200 history event numbers that match $prefix
+ for key in "${(@)history_match_keys[1,200]}"; do
+ # Stop if we ran out of history
+ [[ $key -gt 1 ]] || break
+
+ # See if the history entry preceding the suggestion matches the
+ # previous command, and use it if it does
+ if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
+ histkey="$key"
+ break
+ fi
+ done
+
+ # Give back the matched history entry
+ typeset -g suggestion="$history[$histkey]"
+}
+
+#--------------------------------------------------------------------#
+# Fetch Suggestion #
+#--------------------------------------------------------------------#
+# Loops through all specified strategies and returns a suggestion
+# from the first strategy to provide one.
+#
+
+_zsh_autosuggest_fetch_suggestion() {
+ typeset -g suggestion
+ local -a strategies
+ local strategy
+
+ # Ensure we are working with an array
+ strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
+
+ for strategy in $strategies; do
+ # Try to get a suggestion from this strategy
+ _zsh_autosuggest_strategy_$strategy "$1"
+
+ # Ensure the suggestion matches the prefix
+ [[ "$suggestion" != "$1"* ]] && unset suggestion
+
+ # Break once we've found a valid suggestion
+ [[ -n "$suggestion" ]] && break
+ done
+}
+
+#--------------------------------------------------------------------#
+# Async #
+#--------------------------------------------------------------------#
+
+_zsh_autosuggest_async_request() {
+ zmodload zsh/system 2>/dev/null # For `$sysparams`
+
+ typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
+
+ # If we've got a pending request, cancel it
+ if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
+ # Close the file descriptor and remove the handler
+ exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
+ zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
+
+ # We won't know the pid unless the user has zsh/system module installed
+ if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then
+ # Zsh will make a new process group for the child process only if job
+ # control is enabled (MONITOR option)
+ if [[ -o MONITOR ]]; then
+ # Send the signal to the process group to kill any processes that may
+ # have been forked by the suggestion strategy
+ kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
+ else
+ # Kill just the child process since it wasn't placed in a new process
+ # group. If the suggestion strategy forked any child processes they may
+ # be orphaned and left behind.
+ kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
+ fi
+ fi
+ fi
+
+ # Fork a process to fetch a suggestion and open a pipe to read from it
+ exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
+ # Tell parent process our pid
+ echo $sysparams[pid]
+
+ # Fetch and print the suggestion
+ local suggestion
+ _zsh_autosuggest_fetch_suggestion "$1"
+ echo -nE "$suggestion"
+ )
+
+ # There's a weird bug here where ^C stops working unless we force a fork
+ # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
+ autoload -Uz is-at-least
+ is-at-least 5.8 || command true
+
+ # Read the pid from the child process
+ read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
+
+ # When the fd is readable, call the response handler
+ zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
+}
+
+# Called when new data is ready to be read from the pipe
+# First arg will be fd ready for reading
+# Second arg will be passed in case of error
+_zsh_autosuggest_async_response() {
+ emulate -L zsh
+
+ local suggestion
+
+ if [[ -z "$2" || "$2" == "hup" ]]; then
+ # Read everything from the fd and give it as a suggestion
+ IFS='' read -rd '' -u $1 suggestion
+ zle autosuggest-suggest -- "$suggestion"
+
+ # Close the fd
+ exec {1}<&-
+ fi
+
+ # Always remove the handler
+ zle -F "$1"
+}
+
+#--------------------------------------------------------------------#
+# Start #
+#--------------------------------------------------------------------#
+
+# Start the autosuggestion widgets
+_zsh_autosuggest_start() {
+ # By default we re-bind widgets on every precmd to ensure we wrap other
+ # wrappers. Specifically, highlighting breaks if our widgets are wrapped by
+ # zsh-syntax-highlighting widgets. This also allows modifications to the
+ # widget list variables to take effect on the next precmd. However this has
+ # a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND
+ # to disable the automatic re-binding.
+ if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then
+ add-zsh-hook -d precmd _zsh_autosuggest_start
+ fi
+
+ _zsh_autosuggest_bind_widgets
+}
+
+# Mark for auto-loading the functions that we use
+autoload -Uz add-zsh-hook is-at-least
+
+# Automatically enable asynchronous mode in newer versions of zsh. Disable for
+# older versions because there is a bug when using async mode where ^C does not
+# work immediately after fetching a suggestion.
+# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
+if is-at-least 5.0.8; then
+ typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
+fi
+
+# Start the autosuggestion widgets on the next precmd
+add-zsh-hook precmd _zsh_autosuggest_start
diff --git a/.config/zsh/plugins/zsh-history-substring-search.zsh b/.config/zsh/plugins/zsh-history-substring-search.zsh
new file mode 100644
index 0000000..a791cc4
--- /dev/null
+++ b/.config/zsh/plugins/zsh-history-substring-search.zsh
@@ -0,0 +1,759 @@
+#!/usr/bin/env zsh
+##############################################################################
+#
+# Copyright (c) 2009 Peter Stephenson
+# Copyright (c) 2011 Guido van Steen
+# Copyright (c) 2011 Suraj N. Kurapati
+# Copyright (c) 2011 Sorin Ionescu
+# Copyright (c) 2011 Vincent Guerci
+# Copyright (c) 2016 Geza Lore
+# Copyright (c) 2017 Bengt Brodersen
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+#
+# * Neither the name of the FIZSH nor the names of its contributors
+# may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+##############################################################################
+
+#-----------------------------------------------------------------------------
+# declare global configuration variables
+#-----------------------------------------------------------------------------
+
+typeset -g HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND='bg=magenta,fg=white,bold'
+typeset -g HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold'
+typeset -g HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i'
+typeset -g HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE=''
+typeset -g HISTORY_SUBSTRING_SEARCH_FUZZY=''
+
+#-----------------------------------------------------------------------------
+# declare internal global variables
+#-----------------------------------------------------------------------------
+
+typeset -g BUFFER MATCH MBEGIN MEND CURSOR
+typeset -g _history_substring_search_refresh_display
+typeset -g _history_substring_search_query_highlight
+typeset -g _history_substring_search_result
+typeset -g _history_substring_search_query
+typeset -g -a _history_substring_search_query_parts
+typeset -g -a _history_substring_search_raw_matches
+typeset -g -i _history_substring_search_raw_match_index
+typeset -g -a _history_substring_search_matches
+typeset -g -i _history_substring_search_match_index
+typeset -g -A _history_substring_search_unique_filter
+
+#-----------------------------------------------------------------------------
+# the main ZLE widgets
+#-----------------------------------------------------------------------------
+
+history-substring-search-up() {
+ _history-substring-search-begin
+
+ _history-substring-search-up-history ||
+ _history-substring-search-up-buffer ||
+ _history-substring-search-up-search
+
+ _history-substring-search-end
+}
+
+history-substring-search-down() {
+ _history-substring-search-begin
+
+ _history-substring-search-down-history ||
+ _history-substring-search-down-buffer ||
+ _history-substring-search-down-search
+
+ _history-substring-search-end
+}
+
+zle -N history-substring-search-up
+zle -N history-substring-search-down
+
+#-----------------------------------------------------------------------------
+# implementation details
+#-----------------------------------------------------------------------------
+
+zmodload -F zsh/parameter
+
+#
+# We have to "override" some keys and widgets if the
+# zsh-syntax-highlighting plugin has not been loaded:
+#
+# https://github.com/nicoulaj/zsh-syntax-highlighting
+#
+if [[ $+functions[_zsh_highlight] -eq 0 ]]; then
+ #
+ # Dummy implementation of _zsh_highlight() that
+ # simply removes any existing highlights when the
+ # user inserts printable characters into $BUFFER.
+ #
+ _zsh_highlight() {
+ if [[ $KEYS == [[:print:]] ]]; then
+ region_highlight=()
+ fi
+ }
+
+ #
+ # The following snippet was taken from the zsh-syntax-highlighting project:
+ #
+ # https://github.com/zsh-users/zsh-syntax-highlighting/blob/56b134f5d62ae3d4e66c7f52bd0cc2595f9b305b/zsh-syntax-highlighting.zsh#L126-161
+ #
+ # Copyright (c) 2010-2011 zsh-syntax-highlighting contributors
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions are
+ # met:
+ #
+ # * Redistributions of source code must retain the above copyright
+ # notice, this list of conditions and the following disclaimer.
+ #
+ # * Redistributions in binary form must reproduce the above copyright
+ # notice, this list of conditions and the following disclaimer in the
+ # documentation and/or other materials provided with the distribution.
+ #
+ # * Neither the name of the zsh-syntax-highlighting contributors nor the
+ # names of its contributors may be used to endorse or promote products
+ # derived from this software without specific prior written permission.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+ #--------------8<-------------------8<-------------------8<-----------------
+ # Rebind all ZLE widgets to make them invoke _zsh_highlights.
+ _zsh_highlight_bind_widgets()
+ {
+ # Load ZSH module zsh/zleparameter, needed to override user defined widgets.
+ zmodload zsh/zleparameter 2>/dev/null || {
+ echo 'zsh-syntax-highlighting: failed loading zsh/zleparameter.' >&2
+ return 1
+ }
+
+ # Override ZLE widgets to make them invoke _zsh_highlight.
+ local cur_widget
+ for cur_widget in ${${(f)"$(builtin zle -la)"}:#(.*|_*|orig-*|run-help|which-command|beep|yank*)}; do
+ case $widgets[$cur_widget] in
+
+ # Already rebound event: do nothing.
+ user:$cur_widget|user:_zsh_highlight_widget_*);;
+
+ # User defined widget: override and rebind old one with prefix "orig-".
+ user:*) eval "zle -N orig-$cur_widget ${widgets[$cur_widget]#*:}; \
+ _zsh_highlight_widget_$cur_widget() { builtin zle orig-$cur_widget -- \"\$@\" && _zsh_highlight }; \
+ zle -N $cur_widget _zsh_highlight_widget_$cur_widget";;
+
+ # Completion widget: override and rebind old one with prefix "orig-".
+ completion:*) eval "zle -C orig-$cur_widget ${${widgets[$cur_widget]#*:}/:/ }; \
+ _zsh_highlight_widget_$cur_widget() { builtin zle orig-$cur_widget -- \"\$@\" && _zsh_highlight }; \
+ zle -N $cur_widget _zsh_highlight_widget_$cur_widget";;
+
+ # Builtin widget: override and make it call the builtin ".widget".
+ builtin) eval "_zsh_highlight_widget_$cur_widget() { builtin zle .$cur_widget -- \"\$@\" && _zsh_highlight }; \
+ zle -N $cur_widget _zsh_highlight_widget_$cur_widget";;
+
+ # Default: unhandled case.
+ *) echo "zsh-syntax-highlighting: unhandled ZLE widget '$cur_widget'" >&2 ;;
+ esac
+ done
+ }
+ #-------------->8------------------->8------------------->8-----------------
+
+ _zsh_highlight_bind_widgets
+fi
+
+_history-substring-search-begin() {
+ setopt localoptions extendedglob
+
+ _history_substring_search_refresh_display=
+ _history_substring_search_query_highlight=
+
+ #
+ # If the buffer is the same as the previously displayed history substring
+ # search result, then just keep stepping through the match list. Otherwise
+ # start a new search.
+ #
+ if [[ -n $BUFFER && $BUFFER == ${_history_substring_search_result:-} ]]; then
+ return;
+ fi
+
+ #
+ # Clear the previous result.
+ #
+ _history_substring_search_result=''
+
+ if [[ -z $BUFFER ]]; then
+ #
+ # If the buffer is empty, we will just act like up-history/down-history
+ # in ZSH, so we do not need to actually search the history. This should
+ # speed things up a little.
+ #
+ _history_substring_search_query=
+ _history_substring_search_query_parts=()
+ _history_substring_search_raw_matches=()
+
+ else
+ #
+ # For the purpose of highlighting we keep a copy of the original
+ # query string.
+ #
+ _history_substring_search_query=$BUFFER
+
+ #
+ # compose search pattern
+ #
+ if [[ -n $HISTORY_SUBSTRING_SEARCH_FUZZY ]]; then
+ #
+ # `=` split string in arguments
+ #
+ _history_substring_search_query_parts=(${=_history_substring_search_query})
+ else
+ _history_substring_search_query_parts=(${==_history_substring_search_query})
+ fi
+
+ #
+ # Escape and join query parts with wildcard character '*' as seperator
+ # `(j:CHAR:)` join array to string with CHAR as seperator
+ #
+ local search_pattern="*${(j:*:)_history_substring_search_query_parts[@]//(#m)[\][()|\\*?#<>~^]/\\$MATCH}*"
+
+ #
+ # Find all occurrences of the search pattern in the history file.
+ #
+ # (k) returns the "keys" (history index numbers) instead of the values
+ # (R) returns values in reverse older, so the index of the youngest
+ # matching history entry is at the head of the list.
+ #
+ _history_substring_search_raw_matches=(${(k)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)${search_pattern}]})
+ fi
+
+ #
+ # In order to stay as responsive as possible, we will process the raw
+ # matches lazily (when the user requests the next match) to choose items
+ # that need to be displayed to the user.
+ # _history_substring_search_raw_match_index holds the index of the last
+ # unprocessed entry in _history_substring_search_raw_matches. Any items
+ # that need to be displayed will be added to
+ # _history_substring_search_matches.
+ #
+ # We use an associative array (_history_substring_search_unique_filter) as
+ # a 'set' data structure to ensure uniqueness of the results if desired.
+ # If an entry (key) is in the set (non-empty value), then we have already
+ # added that entry to _history_substring_search_matches.
+ #
+ _history_substring_search_raw_match_index=0
+ _history_substring_search_matches=()
+ _history_substring_search_unique_filter=()
+
+ #
+ # If $_history_substring_search_match_index is equal to
+ # $#_history_substring_search_matches + 1, this indicates that we
+ # are beyond the end of $_history_substring_search_matches and that we
+ # have also processed all entries in
+ # _history_substring_search_raw_matches.
+ #
+ # If $#_history_substring_search_match_index is equal to 0, this indicates
+ # that we are beyond the beginning of $_history_substring_search_matches.
+ #
+ # If we have initially pressed "up" we have to initialize
+ # $_history_substring_search_match_index to 0 so that it will be
+ # incremented to 1.
+ #
+ # If we have initially pressed "down" we have to initialize
+ # $_history_substring_search_match_index to 1 so that it will be
+ # decremented to 0.
+ #
+ if [[ $WIDGET == history-substring-search-down ]]; then
+ _history_substring_search_match_index=1
+ else
+ _history_substring_search_match_index=0
+ fi
+}
+
+_history-substring-search-end() {
+ setopt localoptions extendedglob
+
+ _history_substring_search_result=$BUFFER
+
+ # the search was successful so display the result properly by clearing away
+ # existing highlights and moving the cursor to the end of the result buffer
+ if [[ $_history_substring_search_refresh_display -eq 1 ]]; then
+ region_highlight=()
+ CURSOR=${#BUFFER}
+ fi
+
+ # highlight command line using zsh-syntax-highlighting
+ _zsh_highlight
+
+ # highlight the search query inside the command line
+ if [[ -n $_history_substring_search_query_highlight ]]; then
+ # highlight first matching query parts
+ local highlight_start_index=0
+ local highlight_end_index=0
+ local query_part
+ for query_part in $_history_substring_search_query_parts; do
+ local escaped_query_part=${query_part//(#m)[\][()|\\*?#<>~^]/\\$MATCH}
+ # (i) get index of pattern
+ local query_part_match_index="${${BUFFER:$highlight_start_index}[(i)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)${escaped_query_part}]}"
+ if [[ $query_part_match_index -le ${#BUFFER:$highlight_start_index} ]]; then
+ highlight_start_index=$(( $highlight_start_index + $query_part_match_index ))
+ highlight_end_index=$(( $highlight_start_index + ${#query_part} ))
+ region_highlight+=("$(($highlight_start_index - 1)) $(($highlight_end_index - 1)) $_history_substring_search_query_highlight")
+ fi
+ done
+ fi
+
+ # For debugging purposes:
+ # zle -R "mn: "$_history_substring_search_match_index" m#: "${#_history_substring_search_matches}
+ # read -k -t 200 && zle -U $REPLY
+
+ # Exit successfully from the history-substring-search-* widgets.
+ return 0
+}
+
+_history-substring-search-up-buffer() {
+ #
+ # Check if the UP arrow was pressed to move the cursor within a multi-line
+ # buffer. This amounts to three tests:
+ #
+ # 1. $#buflines -gt 1.
+ #
+ # 2. $CURSOR -ne $#BUFFER.
+ #
+ # 3. Check if we are on the first line of the current multi-line buffer.
+ # If so, pressing UP would amount to leaving the multi-line buffer.
+ #
+ # We check this by adding an extra "x" to $LBUFFER, which makes
+ # sure that xlbuflines is always equal to the number of lines
+ # until $CURSOR (including the line with the cursor on it).
+ #
+ local buflines XLBUFFER xlbuflines
+ buflines=(${(f)BUFFER})
+ XLBUFFER=$LBUFFER"x"
+ xlbuflines=(${(f)XLBUFFER})
+
+ if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xlbuflines -ne 1 ]]; then
+ zle up-line-or-history
+ return 0
+ fi
+
+ return 1
+}
+
+_history-substring-search-down-buffer() {
+ #
+ # Check if the DOWN arrow was pressed to move the cursor within a multi-line
+ # buffer. This amounts to three tests:
+ #
+ # 1. $#buflines -gt 1.
+ #
+ # 2. $CURSOR -ne $#BUFFER.
+ #
+ # 3. Check if we are on the last line of the current multi-line buffer.
+ # If so, pressing DOWN would amount to leaving the multi-line buffer.
+ #
+ # We check this by adding an extra "x" to $RBUFFER, which makes
+ # sure that xrbuflines is always equal to the number of lines
+ # from $CURSOR (including the line with the cursor on it).
+ #
+ local buflines XRBUFFER xrbuflines
+ buflines=(${(f)BUFFER})
+ XRBUFFER="x"$RBUFFER
+ xrbuflines=(${(f)XRBUFFER})
+
+ if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xrbuflines -ne 1 ]]; then
+ zle down-line-or-history
+ return 0
+ fi
+
+ return 1
+}
+
+_history-substring-search-up-history() {
+ #
+ # Behave like up in ZSH, except clear the $BUFFER
+ # when beginning of history is reached like in Fish.
+ #
+ if [[ -z $_history_substring_search_query ]]; then
+
+ # we have reached the absolute top of history
+ if [[ $HISTNO -eq 1 ]]; then
+ BUFFER=
+
+ # going up from somewhere below the top of history
+ else
+ zle up-line-or-history
+ fi
+
+ return 0
+ fi
+
+ return 1
+}
+
+_history-substring-search-down-history() {
+ #
+ # Behave like down-history in ZSH, except clear the
+ # $BUFFER when end of history is reached like in Fish.
+ #
+ if [[ -z $_history_substring_search_query ]]; then
+
+ # going down from the absolute top of history
+ if [[ $HISTNO -eq 1 && -z $BUFFER ]]; then
+ BUFFER=${history[1]}
+ _history_substring_search_refresh_display=1
+
+ # going down from somewhere above the bottom of history
+ else
+ zle down-line-or-history
+ fi
+
+ return 0
+ fi
+
+ return 1
+}
+
+_history_substring_search_process_raw_matches() {
+ #
+ # Process more outstanding raw matches and append any matches that need to
+ # be displayed to the user to _history_substring_search_matches.
+ # Return whether there were any more results appended.
+ #
+
+ #
+ # While we have more raw matches. Process them to see if there are any more
+ # matches that need to be displayed to the user.
+ #
+ while [[ $_history_substring_search_raw_match_index -lt $#_history_substring_search_raw_matches ]]; do
+ #
+ # Move on to the next raw entry and get its history index.
+ #
+ _history_substring_search_raw_match_index+=1
+ local index=${_history_substring_search_raw_matches[$_history_substring_search_raw_match_index]}
+
+ #
+ # If HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE is set to a non-empty value,
+ # then ensure that only unique matches are presented to the user.
+ # When HIST_IGNORE_ALL_DUPS is set, ZSH already ensures a unique history,
+ # so in this case we do not need to do anything.
+ #
+ if [[ ! -o HIST_IGNORE_ALL_DUPS && -n $HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE ]]; then
+ #
+ # Get the actual history entry at the new index, and check if we have
+ # already added it to _history_substring_search_matches.
+ #
+ local entry=${history[$index]}
+
+ if [[ -z ${_history_substring_search_unique_filter[$entry]} ]]; then
+ #
+ # This is a new unique entry. Add it to the filter and append the
+ # index to _history_substring_search_matches.
+ #
+ _history_substring_search_unique_filter[$entry]=1
+ _history_substring_search_matches+=($index)
+
+ #
+ # Indicate that we did find a match.
+ #
+ return 0
+ fi
+
+ else
+ #
+ # Just append the new history index to the processed matches.
+ #
+ _history_substring_search_matches+=($index)
+
+ #
+ # Indicate that we did find a match.
+ #
+ return 0
+ fi
+
+ done
+
+ #
+ # We are beyond the end of the list of raw matches. Indicate that no
+ # more matches are available.
+ #
+ return 1
+}
+
+_history-substring-search-has-next() {
+ #
+ # Predicate function that returns whether any more older matches are
+ # available.
+ #
+
+ if [[ $_history_substring_search_match_index -lt $#_history_substring_search_matches ]]; then
+ #
+ # We did not reach the end of the processed list, so we do have further
+ # matches.
+ #
+ return 0
+
+ else
+ #
+ # We are at the end of the processed list. Try to process further
+ # unprocessed matches. _history_substring_search_process_raw_matches
+ # returns whether any more matches were available, so just return
+ # that result.
+ #
+ _history_substring_search_process_raw_matches
+ return $?
+ fi
+}
+
+_history-substring-search-has-prev() {
+ #
+ # Predicate function that returns whether any more younger matches are
+ # available.
+ #
+
+ if [[ $_history_substring_search_match_index -gt 1 ]]; then
+ #
+ # We did not reach the beginning of the processed list, so we do have
+ # further matches.
+ #
+ return 0
+
+ else
+ #
+ # We are at the beginning of the processed list. We do not have any more
+ # matches.
+ #
+ return 1
+ fi
+}
+
+_history-substring-search-found() {
+ #
+ # A match is available. The index of the match is held in
+ # $_history_substring_search_match_index
+ #
+ # 1. Make $BUFFER equal to the matching history entry.
+ #
+ # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
+ # to highlight the current buffer.
+ #
+ BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]]
+ _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
+}
+
+_history-substring-search-not-found() {
+ #
+ # No more matches are available.
+ #
+ # 1. Make $BUFFER equal to $_history_substring_search_query so the user can
+ # revise it and search again.
+ #
+ # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
+ # to highlight the current buffer.
+ #
+ BUFFER=$_history_substring_search_query
+ _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
+}
+
+_history-substring-search-up-search() {
+ _history_substring_search_refresh_display=1
+
+ #
+ # Select history entry during history-substring-down-search:
+ #
+ # The following variables have been initialized in
+ # _history-substring-search-up/down-search():
+ #
+ # $_history_substring_search_matches is the current list of matches that
+ # need to be displayed to the user.
+ # $_history_substring_search_match_index is the index of the current match
+ # that is being displayed to the user.
+ #
+ # The range of values that $_history_substring_search_match_index can take
+ # is: [0, $#_history_substring_search_matches + 1]. A value of 0
+ # indicates that we are beyond the beginning of
+ # $_history_substring_search_matches. A value of
+ # $#_history_substring_search_matches + 1 indicates that we are beyond
+ # the end of $_history_substring_search_matches and that we have also
+ # processed all entries in _history_substring_search_raw_matches.
+ #
+ # If $_history_substring_search_match_index equals
+ # $#_history_substring_search_matches and
+ # $_history_substring_search_raw_match_index is not greater than
+ # $#_history_substring_search_raw_matches, then we need to further process
+ # $_history_substring_search_raw_matches to see if there are any more
+ # entries that need to be displayed to the user.
+ #
+ # In _history-substring-search-up-search() the initial value of
+ # $_history_substring_search_match_index is 0. This value is set in
+ # _history-substring-search-begin(). _history-substring-search-up-search()
+ # will initially increment it to 1.
+ #
+
+ if [[ $_history_substring_search_match_index -gt $#_history_substring_search_matches ]]; then
+ #
+ # We are beyond the end of $_history_substring_search_matches. This
+ # can only happen if we have also exhausted the unprocessed matches in
+ # _history_substring_search_raw_matches.
+ #
+ # 1. Update display to indicate search not found.
+ #
+ _history-substring-search-not-found
+ return
+ fi
+
+ if _history-substring-search-has-next; then
+ #
+ # We do have older matches.
+ #
+ # 1. Move index to point to the next match.
+ # 2. Update display to indicate search found.
+ #
+ _history_substring_search_match_index+=1
+ _history-substring-search-found
+
+ else
+ #
+ # We do not have older matches.
+ #
+ # 1. Move the index beyond the end of
+ # _history_substring_search_matches.
+ # 2. Update display to indicate search not found.
+ #
+ _history_substring_search_match_index+=1
+ _history-substring-search-not-found
+ fi
+
+ #
+ # When HIST_FIND_NO_DUPS is set, meaning that only unique command lines from
+ # history should be matched, make sure the new and old results are different.
+ #
+ # However, if the HIST_IGNORE_ALL_DUPS shell option, or
+ # HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE is set, then we already have a
+ # unique history, so in this case we do not need to do anything.
+ #
+ if [[ -o HIST_IGNORE_ALL_DUPS || -n $HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE ]]; then
+ return
+ fi
+
+ if [[ -o HIST_FIND_NO_DUPS && $BUFFER == $_history_substring_search_result ]]; then
+ #
+ # Repeat the current search so that a different (unique) match is found.
+ #
+ _history-substring-search-up-search
+ fi
+}
+
+_history-substring-search-down-search() {
+ _history_substring_search_refresh_display=1
+
+ #
+ # Select history entry during history-substring-down-search:
+ #
+ # The following variables have been initialized in
+ # _history-substring-search-up/down-search():
+ #
+ # $_history_substring_search_matches is the current list of matches that
+ # need to be displayed to the user.
+ # $_history_substring_search_match_index is the index of the current match
+ # that is being displayed to the user.
+ #
+ # The range of values that $_history_substring_search_match_index can take
+ # is: [0, $#_history_substring_search_matches + 1]. A value of 0
+ # indicates that we are beyond the beginning of
+ # $_history_substring_search_matches. A value of
+ # $#_history_substring_search_matches + 1 indicates that we are beyond
+ # the end of $_history_substring_search_matches and that we have also
+ # processed all entries in _history_substring_search_raw_matches.
+ #
+ # In _history-substring-search-down-search() the initial value of
+ # $_history_substring_search_match_index is 1. This value is set in
+ # _history-substring-search-begin(). _history-substring-search-down-search()
+ # will initially decrement it to 0.
+ #
+
+ if [[ $_history_substring_search_match_index -lt 1 ]]; then
+ #
+ # We are beyond the beginning of $_history_substring_search_matches.
+ #
+ # 1. Update display to indicate search not found.
+ #
+ _history-substring-search-not-found
+ return
+ fi
+
+ if _history-substring-search-has-prev; then
+ #
+ # We do have younger matches.
+ #
+ # 1. Move index to point to the previous match.
+ # 2. Update display to indicate search found.
+ #
+ _history_substring_search_match_index+=-1
+ _history-substring-search-found
+
+ else
+ #
+ # We do not have younger matches.
+ #
+ # 1. Move the index beyond the beginning of
+ # _history_substring_search_matches.
+ # 2. Update display to indicate search not found.
+ #
+ _history_substring_search_match_index+=-1
+ _history-substring-search-not-found
+ fi
+
+ #
+ # When HIST_FIND_NO_DUPS is set, meaning that only unique command lines from
+ # history should be matched, make sure the new and old results are different.
+ #
+ # However, if the HIST_IGNORE_ALL_DUPS shell option, or
+ # HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE is set, then we already have a
+ # unique history, so in this case we do not need to do anything.
+ #
+ if [[ -o HIST_IGNORE_ALL_DUPS || -n $HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE ]]; then
+ return
+ fi
+
+ if [[ -o HIST_FIND_NO_DUPS && $BUFFER == $_history_substring_search_result ]]; then
+ #
+ # Repeat the current search so that a different (unique) match is found.
+ #
+ _history-substring-search-down-search
+ fi
+}
+
+# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=zsh sw=2 ts=2 et
diff --git a/.config/zsh/plugins/zsh-syntax-highlighting b/.config/zsh/plugins/zsh-syntax-highlighting
new file mode 160000
+Subproject e0165eaa730dd0fa321a6a6de74f092fe87630b
diff --git a/.config/zsh/zprofile b/.config/zsh/zprofile
new file mode 100644
index 0000000..46c5217
--- /dev/null
+++ b/.config/zsh/zprofile
@@ -0,0 +1,21 @@
+#!/bin/zsh
+. ~/.profile
+
+[ -n "$TMUX" ] || [ -n "$TERMUX_VERSION" ] || [ "$SSH_CONNECTION" ] &&
+ return
+
+on_ac_power="$(cat /sys/class/power_supply/ACAD/online)"
+[ "$on_ac_power" = 0 ] && brightnessctl set 5% || brightnessctl set 20%
+
+case "$TTY" in
+ /dev/tty1)
+ [ "$on_ac_power" = 1 ] && {
+ echo "Waiting for nvidia card to load up..."
+ until [ -e /dev/dri/card0 ]; do; sleep 0.1; done
+ }
+ command -V startx >/dev/null && { pgrep startx || startx }
+ ;;
+ /dev/tty3) tmux new -s master ;;
+ /dev/tty[2-5]) tmux new -s "${TTY#/dev/}" ;;
+ # /dev/pts/*) exec tmux new -s "${TTY#/dev/}" ;;
+esac
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..1d21d73
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,69 @@
+/*
+
+!/.gitignore
+!/.gitmodules
+!/.profile
+!/.xprofile
+!/.zprofile
+!/gtkrc-2.0
+
+!/.config
+/.config/*
+!/.config/gh/config.yml
+
+shortcutrc
+shortcuts.*
+
+!/.config/shell
+/.config/shell/*
+!/.config/shell/aliasrc
+!/.config/shell/bm-files
+!/.config/shell/bm-dirs
+!/.config/shell/inputrc
+!/.config/shell/profile
+
+!/.config/zsh
+/.config/zsh/*
+!/.config/zsh/plugins
+!/.config/zsh/command-tools.zsh
+!/.config/zsh/zprofile
+!/.config/zsh/.zshrc
+
+!/.config/terminal-colors.d
+!/.config/wget
+!/.config/htop
+!/.config/gotop
+!/.config/tmux
+!/.config/nvim
+!/.config/lf
+!/.config/sc-im
+!/.config/yt-dlp
+!/.config/python
+!/.config/ipython
+!/.config/git
+
+!/.config/gtk-2.0
+!/.config/gtk-3.0
+!/.config/gtk-4.0
+!/.config/lxsession
+!/.config/X11
+
+!/.config/i3
+!/.config/i3blocks
+!/.config/jgmenu
+!/.config/keepassxc
+!/.config/Thunar
+!/.config/zathura
+!/.config/Zeal
+
+!/.local
+/.local/*
+!/.local/bin
+/.local/bin/.st*
+
+!/.local/share
+/.local/share/*
+!/.local/share/fzf
+/.local/share/fzf/*
+!/.local/share/applications
+!/.local/share/chars
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..5ec3787
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule ".config/zsh/plugins/fast-syntax-highlighting"]
+ path = .config/zsh/plugins/fast-syntax-highlighting
+ url = https://github.com/zdharma-continuum/fast-syntax-highlighting
+[submodule ".config/zsh/plugins/zsh-syntax-highlighting"]
+ path = .config/zsh/plugins/zsh-syntax-highlighting
+ url = https://github.com/zsh-users/zsh-syntax-highlighting
diff --git a/.local/bin/automountd b/.local/bin/automountd
new file mode 100755
index 0000000..f09871f
--- /dev/null
+++ b/.local/bin/automountd
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+pathtoname() {
+ udevadm info -p /sys/"$1" | awk -v FS== '/DEVNAME/ {print $2}'
+}
+
+stdbuf -oL -- udevadm monitor --udev -s block | while read -r -- _ _ event devpath _; do
+ if [ "$event" = add ]; then
+ devname=$(pathtoname "$devpath")
+ udisksctl mount --block-device "$devname" --no-user-interaction
+ fi
+done
diff --git a/.local/bin/backup b/.local/bin/backup
new file mode 100755
index 0000000..8f6e00d
--- /dev/null
+++ b/.local/bin/backup
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+sudo cryptsetup open /dev/sdb1 backup
+sudo mount --mkdir /dev/mapper/backup /mnt/backup
+backup="/mnt/backup/$(hostname)"
+[ -d "$backup" ] ||
+ { echo "$0: directory doesn't exist: $backup" >&2; exit 1; }
+
+cd ~ || exit
+rsync -Plru --delete \
+ .config \
+ .git \
+ .gnupg \
+ .local \
+ .librewolf \
+ .ssh \
+ bin \
+ DCIM \
+ Dev \
+ Documents \
+ Downloads \
+ GDrive \
+ Music \
+ Phone \
+ Pictures \
+ repos \
+ Videos \
+ "$backup/home/$USER/"
+
+find . -maxdepth 1 \( -type f -o -type l \) -exec rsync -Plu {} "$backup/home/$USER" \;
+
+echo "Backing up /etc directory..."
+sudo rsync -Plruq --delete /etc "$backup"
diff --git a/.local/bin/clearx b/.local/bin/clearx
new file mode 100755
index 0000000..225c208
--- /dev/null
+++ b/.local/bin/clearx
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+help() { echo "clearx - execute command in clear screen
+
+USAGE:
+ clearx [OPTION]... <command>
+
+OPTIONS:
+ -n no prompt when exiting
+ -h show this help message"; }
+
+err() { printf 'clearx: %s\n' "$@" >&2; exit 1; }
+while getopts 'nh' o; do case "$o" in
+ n) nflag=0 ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+cmds="$*"
+[ "$nflag" = 0 ] ||
+ cmds="$cmds; printf '\n%s' 'Press <Enter> to continue: '; read -r arg"
+
+tmuxcmds="tmux set status off; $cmds; tmux set status on;"
+set_screen() {
+ [ -z "$TMUX" ] &&
+ err '$TMUX not set, only tmux is supported for screen program'
+ tmux new-window -n clearx "$tmuxcmds"
+}
+new_screen() { tmux new-session -s clearx "$tmuxcmds"; }
+
+terminal_emulator() {
+ [ -z "$DISPLAY" ] && return 1
+ #err 'clearx: terminal_emulator: $DISPLAY not set'
+ case "$TERMINAL" in
+ '') echo 'clearx: $TERMINAL not set' && exit 1 ;;
+ alacritty) export TERMINAL="alacritty" ;;
+ esac
+ wmctrl -r :ACTIVE: -b remove,fullscreen
+ $TERMINAL -e sh -c "sleep 0.2; $cmds" &
+ sleep 0.2 && wmctrl -r :ACTIVE: -b add,fullscreen
+}
+
+case "$TERM" in
+ '') err '$TERM not set' ;;
+ *screen*) set_screen ;;
+ *linux*) setfont ter-132n && new_screen ;;
+ *256*) terminal_emulator || new_screen ;;
+ *) err "no action for \$TERM: $TERM"
+esac
diff --git a/.local/bin/desktop/beautify b/.local/bin/desktop/beautify
new file mode 100755
index 0000000..e535129
--- /dev/null
+++ b/.local/bin/desktop/beautify
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+## properties of script
+
+## set home screen and lock screen wallpaper
+HOMEWALL="${XDG_DATA_HOME:-$HOME/.local/share}/wallpapers/artix-wampire.png"
+LOCKWALL="${XDG_DATA_HOME:-$HOME/.local/share}/wallpapers/artix-wampire.png"
+
+## choose random wallpaper from a directory
+# WALLPAPERS="$HOME/.local/share/wallpapers"
+## requires 'setbg' script found in lukesmithxyz github repo
+setbg_link="https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/setbg"
+## path to download script files like setbg
+BIN="$HOME/.local/bin"
+
+# Location to put lock screen wallpaper for lock program
+LOCKWALL_LOC="/tmp/lockWall"
+
+## list of programs to be installed/uninstalled
+PROGRAMS="eza dust conky picom xwallpaper cxxmatrix"
+## some additional programs that I think are essential are installed below
+## these will be not removed during uninstall
+
+
+help() { echo "beautify - beautify you desktop environment
+
+USAGE:
+ beautify [OPTION]...
+
+OPTIONS:
+ -h show this help message
+
+ -i install programs for beautification
+ -u uninstall beautification programs
+ -x clear beautifications
+
+ The above group of options are conflicting.
+ Passing any one of them will disable the others.
+
+This is very much a personal script and is meant to be configured directly.
+I have only made it work with arch linux and the pacman package manager."; }
+
+err() { printf 'beautify: %s\n' "$@" >&2; exit 1; }
+while getopts 'iuxh' o; do case "$o" in
+ i) opflag=0 ;;
+ u) opflag=1 ;;
+ x) opflag=2 ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+case "$opflag" in
+ 0)
+ PROGRAMS="$PROGRAMS neovim tmux dunst highlight starship"
+ sudo pacman -Syu --noconfirm
+ for pkg in $PROGRAMS; do
+ if ! pacman -Q "$pkg" >/dev/null; then
+ yay -S --noconfirm "$pkg"
+ fi
+ done
+
+ mkdir -pv ~/.local/bin
+ wget -c "$setbg_link" -o "${BIN}/setbg" && chmod +x "${BIN}/setbg"
+ ;;
+
+ 1)
+ for pkg in $PROGRAMS; do
+ if pacman -Q "$pkgs" >/dev/null; then
+ sudo pacman -Rns --noconfirm "$pkg"
+ fi
+ done
+ rm -f "$setbg"
+ ;;
+
+ 2)
+ i3-msg 'gaps inner all set 0'
+ xwallpaper --clear
+ rm -f "$LOCKWALL_LOC"
+ killall -q -o 1s conky picom beautify
+ ;;
+esac
+
+[ -n "$opflag" ] && exit
+
+if [ "${LOCKWALL%.png}" = "$LOCKWALL" ]; then
+ temp="/tmp/$(basename "${LOCKWALL%.*}.png")"
+ convert "$LOCKWALL" "$temp"
+ cp -f "$temp" "$LOCKWALL_LOC"
+ rm -f "$temp"
+else
+ cp -f "$LOCKWALL" "$LOCKWALL_LOC"
+fi
+
+i3-msg 'gaps inner all set 10'
+xwallpaper --zoom "$HOMEWALL"
+pidof -q conky || conky
+pidof -q picom || picom -b
+
+if [ -e "$WALLPAPERS" ]; then
+ while sleep 1m; do setbg "$WALLPAPERS"; done
+fi
diff --git a/.local/bin/desktop/brightness b/.local/bin/desktop/brightness
new file mode 100755
index 0000000..11733f4
--- /dev/null
+++ b/.local/bin/desktop/brightness
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+help() { echo "brightness - change screen brightness
+USAGE: brightness <up|down>"; }
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+
+brightness="$(brightnessctl --machine-readable | cut -d, -f4 | tr -d %)"
+step="$(( brightness / 10 + 1))"
+
+case "$1" in
+ up) brightnessctl --quiet set +${step}% ;;
+ down) brightnessctl --quiet set ${step}%- ;;
+ *) help >&2; exit 1 ;;
+esac
+
+brightness="$(brightnessctl --machine-readable | cut -d, -f4)"
+
+if [ -n "$TMUX" ]; then
+ tmux display "Brightness: $brightness"
+ exit
+fi
+
+notify() { [ -n "$DISPLAY" ] && notify-send -r 45234 "$1" "$2"; }
+case "${brightness%\%}" in
+ [0-9]) notify "💡 Brightness: $brightness" ;;
+ [1-7][0-9]) notify "🔅 Brightness: $brightness" ;;
+ [89][0-9]) notify "🔆 Brightness: $brightness" ;;
+ 100) notify "🔆 MAX Brightness: $brightness" ;;
+ *) notify "brightness" "can't determine brightness"
+esac
+exit 0
diff --git a/.local/bin/desktop/detect-keys b/.local/bin/desktop/detect-keys
new file mode 100755
index 0000000..da00dad
--- /dev/null
+++ b/.local/bin/desktop/detect-keys
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+xev | awk -F'[ )]+' '/^KeyPress/ { a[NR+2] } NR in a { printf "%-3s %s\n", $5, $8 }'
diff --git a/.local/bin/desktop/dmenu-syncthing-devices b/.local/bin/desktop/dmenu-syncthing-devices
new file mode 100755
index 0000000..bb93f6d
--- /dev/null
+++ b/.local/bin/desktop/dmenu-syncthing-devices
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+pidof -q syncthing || {
+ echo "ERROR: Syncthing is not running" >&2
+ exit 2
+}
+
+get_devices() {
+ for device_id in $(syncthing cli config devices list); do
+ printf '%-10s %s\n' \
+ "$(syncthing cli config devices "$device_id" name get)" \
+ "$device_id"
+ done | nl -w1 -s'. '
+}
+
+device="$(get_devices | dmenu -l 10 -p "Syncthing devices")"
+device_id="${device##* }"
+[ -z "$device_id" ] && exit 1
+
+if [ -n "$1" ]; then
+ xdotool type "$device_id"
+else
+ printf '%s\n' "$device_id" | xclip -selection clipboard
+ notify-send "📋 Copied to clipboard" "$device_id"
+fi
diff --git a/.local/bin/desktop/dmenu-unicode b/.local/bin/desktop/dmenu-unicode
new file mode 100755
index 0000000..16e1cfc
--- /dev/null
+++ b/.local/bin/desktop/dmenu-unicode
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+chosen=$(cat ~/.local/share/chars/* | dmenu -i -l 25 -fn :size=20)
+
+[ -z "$chosen" ] && exit
+
+if [ -n "$1" ]; then
+ printf "%s" "${chosen#* }" | cut -d\; -f1 | tr -d '\n' | xclip -selection clipboard
+else
+ printf "%s" "${chosen%% *}" | xclip -selection clipboard
+fi
diff --git a/.local/bin/desktop/dmenu-zeal b/.local/bin/desktop/dmenu-zeal
new file mode 100755
index 0000000..608be89
--- /dev/null
+++ b/.local/bin/desktop/dmenu-zeal
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+cd ~/.local/share/Zeal/Zeal || exit
+
+selection="$(echo "Shell
+C/C++
+Java
+Python
+$(find . -maxdepth 1 -type d ! -name 'docsets' |
+ tail +2 | cut -c3- | sed 's/^/ds:/')
+" | dmenu -i -p "Select docset group")"
+
+case "$selection" in
+ Shell) key="bash,zsh,linux" ;;
+ C/C++) key="c,cpp,linux" ;;
+ Java) key="java,javaspec" ;;
+ Python) key="python,numpy,matplotlib" ;;
+ ds:*)
+ ln -sfT "${selection#ds:}" docsets
+ killall -q zeal; zeal
+ exit
+ ;;
+ *) exit 2 ;;
+esac
+
+query="$(dmenu -p "Enter query")"
+zeal "$key:$query"
diff --git a/.local/bin/desktop/edit-graphical-buffer b/.local/bin/desktop/edit-graphical-buffer
new file mode 100755
index 0000000..10eac8f
--- /dev/null
+++ b/.local/bin/desktop/edit-graphical-buffer
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+sleep 0.5
+xdotool key --clearmodifiers ctrl+a ctrl+c
+content="$(xclip -o -sel clipboard)"
+
+tempfile=/tmp/scratch-buffer/$$.txt
+mkdir -pv /tmp/scratch-buffer
+echo "$content" | tee "$tempfile" > "$tempfile.bak"
+${TERMINAL:-xdg-terminal-exec} -c dropdown_buffer -e nvim "$tempfile"
+
+diff "$tempfile" "$tempfile.bak" >/dev/null || {
+ xclip -sel clipboard < "$tempfile"
+ xdotool key --clearmodifiers ctrl+a ctrl+v
+}
+
+rm -f "$tempfile" "$tempfile.bak"
diff --git a/.local/bin/desktop/i3exit b/.local/bin/desktop/i3exit
new file mode 100755
index 0000000..0be387c
--- /dev/null
+++ b/.local/bin/desktop/i3exit
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# with openrc use loginctl
+[ "$(cat /proc/1/comm)" = "systemd" ] && logind=systemctl || logind=loginctl
+
+command="$1"
+system_control() {
+ if [ "$(loginctl show-session --property=NCurrentSessions --value)" -gt 2 ]; then
+ notify-send --replace-id=4252 \
+ "i3exit" "Multiple users are logged in\nCant't $command"
+ exit
+ fi
+ eval "$@"
+}
+
+lockWall="$HOME/.local/share/lockWall"
+lock_desktop() {
+ [ -f "$lockWall" ] &&
+ i3lock --tiling --image="$lockWall" ||
+ i3lock --color=001177
+ pkill ssh-agent
+}
+
+case "$command" in
+ lock)
+ lock_desktop
+ xset dpms force off
+ ;;
+ logout)
+ switch-session
+ i3-msg exit
+ ;;
+ switch_user)
+ dm-tool switch-to-greeter
+ ;;
+ suspend)
+ lock_desktop; $logind suspend
+ ;;
+ hibernate)
+ system_control lock_desktop && $logind hibernate
+ ;;
+ reboot)
+ system_control $logind reboot
+ ;;
+ shutdown)
+ system_control $logind poweroff
+ ;;
+ *)
+ echo "== ! i3exit: missing or invalid argument ! =="
+ echo "Try again with: lock | logout | switch_user | suspend | hibernate | reboot | shutdown"
+ exit 2
+esac
+
+exit 0
diff --git a/.local/bin/desktop/i3exit-script b/.local/bin/desktop/i3exit-script
new file mode 100755
index 0000000..b27f0f5
--- /dev/null
+++ b/.local/bin/desktop/i3exit-script
@@ -0,0 +1,18 @@
+#!/bin/bash
+# TODO: copy and configure the i3 script to take parametres
+# possibly make it as syst-power
+
+# snippet for blur effect on lock screen
+
+
+# DEPEDNDENCIES: i3lock imagemagic scrot
+
+PICTURE=/tmp/i3lock.png
+SCREENSHOT="scrot $PICTURE"
+
+BLUR="5x4"
+
+$SCREENSHOT
+convert $PICTURE -blur $BLUR $PICTURE
+i3lock -i $PICTURE
+rm $PICTURE
diff --git a/.local/bin/desktop/librewolf-open b/.local/bin/desktop/librewolf-open
new file mode 100755
index 0000000..4bb2d70
--- /dev/null
+++ b/.local/bin/desktop/librewolf-open
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+window="LibreWolf"
+running() { windows=$(wmctrl -l)
+ test "${windows#*"$window"}" != "$windows"; }
+press() { sleep 0.1; xdotool keyup Super
+ xdotool key --clearmodifiers "$@"; }
+
+if ! running; then
+ notify-send "Starting $window..."
+ start="$(date +%s.%3N)"
+ setsid -f librewolf -P "${FFPROFILE:-default-release}"
+ for _ in $(seq 1000); do sleep 0.1; running && break; done
+ end="$(date +%s.%3N)"
+ time="$(echo "$end - $start" | bc)"
+ notify-send "$window" "Started in ${time}s"
+ started=1
+fi
+
+wmctrl -a "$window" ||
+ { notify-send "ffbrowser" "ERROR: librewolf window not found"; exit 1; }
+[ "$started" = 1 ] || press ctrl+t
+
+query="$*"
+if [ "$query" != "${query#http*://}" ]; then
+ press ctrl+l
+elif [ -e "$query" ]; then
+ query="$(readlink -f "$query")"; press ctrl+l
+else
+ # workaround for ctrl+k not working at initial startup
+ [ "$started" = 1 ] && sleep 0.5
+ press ctrl+k
+fi
+
+if [ -n "$query" ]; then
+ xdotool type "$query"
+ press Return
+fi
+
diff --git a/.local/bin/desktop/mlock b/.local/bin/desktop/mlock
new file mode 100755
index 0000000..67da8a3
--- /dev/null
+++ b/.local/bin/desktop/mlock
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+command -v xtrlock || exit
+
+[ "$(xrandr --current | grep -c "\S* connected \S\+.* (")" -gt 1 ] && {
+ xtrlock -b -f
+ xset dpms force off
+ exit
+}
+
+TERMINAL="alacritty -t matrixlock"
+if command -v cxxmatrix; then
+ $TERMINAL -e cxxmatrix &
+elif command -v cmatrix; then
+ $TERMINAL -e sh -c 'sleep 0.5 && cmatrix' &
+else
+ xtrlock -b -f; exit
+fi
+
+xtrlock -f
+sleep 0.2
+wmctrl -r matrixlock -b add,fullscreen
diff --git a/.local/bin/desktop/remap b/.local/bin/desktop/remap
new file mode 100755
index 0000000..3635464
--- /dev/null
+++ b/.local/bin/desktop/remap
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+# This script cannot run without the X server (GUI)
+# So exit if DISPLAY is not set
+[ -z "$DISPLAY" ] && {
+ notify-send remap "ERROR: DISPLAY not set"
+ exit
+}
+
+timeout="${KEY_RELEASE_TIMEOUT:-500}"
+
+help() { echo "remap - remap modifier keys for easy access
+
+USAGE:
+ remap [OPTION]...
+
+OPTIONS:
+ -x reset keys
+ -t toggle (remap/reset)
+ -s show remap status
+ -i show info of all key remaps
+ -h show this help message"; }
+
+key_info() { echo "
+ +-----------------+-----------------------------------+
+ | Before | After |
+ +-----------------+-----------------+-----------------+
+ | Key | On Hold | On Tap |
+ +-----------------+-----------------+-----------------+
+ | Tab | Super | Tab |
+ | Caps Lock | Ctrl | Esc |
+ | Space | Shift | Space |
+ | Left Ctrl | Ctrl | Caps Lock |
+ | Escape | Tab | Tab |
+ +-----------------+-----------------+-----------------+
+
+Note:
+ By default, 'On Tap' will timeout at 500 miliseconds. In other words,
+ if you release a key after timeout, the key will not be generated.
+ You can increase it's value by setting the \$KEY_RELEASE_TIMEOUT environment
+ variable. This is useful in case you don't have a fast typing speed.
+
+If you want to change more keys or want a different configuration, you
+can edit the remap_keys() function inside this script.
+ "; }
+
+while getopts 'rxtsih' o; do case "$o" in
+ x) action=x ;;
+ t) action=t ;;
+ s) action=s ;;
+ i) key_info >&2; exit ;;
+ h) help >&2; exit ;;
+ *) printf "remap: invalid argument -- '%s'\n" "$OPTARG" ;;
+esac; done
+
+status_file="/tmp/.remap.lock"
+keymap_file="/tmp/.xmodmap.defaults"
+[ -f "$keymap_file" ] || xmodmap -pke > "$keymap_file"
+
+msg() {
+ [ "$VERBOSE_REMAP" != 1 ] && return
+ printf "remap: %s\n" "$@"
+ # notify-send "remap" "$*"
+}
+
+remap_keys() {
+ msg "remapping keys..."
+ # Fast key repeats
+ xset r rate 300 50
+
+ # New key behaviour on Hold
+ # lines after ! are comments
+ xmodmap - <<-EOF
+ ! Hold Caps_Lock -> Control_R
+ remove lock = Caps_Lock
+ remove Control = Control_R
+ ! keysym Control_R = Caps_Lock
+ keysym Caps_Lock = Control_R
+ ! add lock = Caps_Lock
+ add Control = Control_R
+ keycode any = Caps_Lock
+
+ ! Hold space -> Shift_R
+ remove shift = Shift_R
+ keycode 65 = Shift_R
+ add shift = Shift_R
+ keycode any = space
+
+ ! Hold Tab -> Super_L
+ ! ! Escape -> Tab
+ remove mod4 = Super_L
+ keycode 23 = Super_L
+ keycode any = Tab ISO_Left_Tab Tab ISO_Left_Tab
+ ! keycode 133 = Tab ISO_Left_Tab Tab ISO_Left_Tab
+ add mod4 = Super_L
+ ! keycode 230 = Escape
+ ! keycode 9 = Tab ISO_Left_Tab Tab ISO_Left_Tab
+ EOF
+
+ # New key behaviour on Tap
+ killall xcape 2>/dev/null
+ xcape -t "$timeout" -e "Super_L=Tab"
+ xcape -t "$timeout" -e "Control_R=Escape"
+ xcape -t "$timeout" -e "Shift_L=Caps_Lock"
+ xcape -t "$timeout" -e "Shift_R=space"
+ date > "$status_file"
+ xset led 3
+ msg "keys remapped"
+}
+
+
+reset_keys() {
+ msg "resetting keys..."
+ xset r rate
+ killall xcape 2>/dev/null
+ setxkbmap -layout us
+ xmodmap "$keymap_file"
+
+ [ -f "$status_file" ] && rm "$status_file"
+ xset -led 3
+ msg "keys reset"
+}
+
+toggle_remap() {
+ if [ -f "$status_file" ]; then
+ reset_keys
+ else
+ remap_keys
+ fi
+}
+
+remap_status() {
+ if [ -f "$status_file" ]; then
+ printf "Keys are remapped since "
+ cat "$status_file"
+ else
+ echo "Keys are NOT remapped"
+ fi
+}
+
+case "$action" in
+ s) remap_status ;;
+ x) reset_keys ;;
+ t) toggle_remap ;;
+ *) remap_keys ;;
+esac
diff --git a/.local/bin/desktop/remapd b/.local/bin/desktop/remapd
new file mode 100755
index 0000000..851d7d2
--- /dev/null
+++ b/.local/bin/desktop/remapd
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+while :; do
+ remap
+ grep -qP -m1 '[^un]bind.+\/[^:]+\(usb\)' <(udevadm monitor -u -t seat -s input -s usb)
+done
diff --git a/.local/bin/desktop/setdp b/.local/bin/desktop/setdp
new file mode 100755
index 0000000..48c6a7a
--- /dev/null
+++ b/.local/bin/desktop/setdp
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+displays="$(xrandr | grep "^\S* connected" | cut -d\ -f1)"
+display_count="$(echo "$displays" | wc -l)"
+
+[ "$display_count" -gt 2 ] &&
+ { echo "Too many displays to configure" >&2; exit 1; }
+
+set --
+
+
+if [ "$display_count" = 2 ]; then
+
+ for display in $displays; do
+ case "$display" in
+ eDP*) export PRIMARY="$display"; set -- "$@" --output "$display" --mode 1920x1080 --primary --pos 0x270 ;;
+ HDMI*) set -- "$@" --output "$display" --mode 1920x1080 --pos 1920x0 --scale "1.25x1.25" ;;
+ esac
+ done
+
+else
+
+ for display in $displays; do
+ case "$display" in
+ eDP*) set -- "$@" --output "$display" --primary --mode 1920x1080 --scale "1.1x1.1" ;;
+ HDMI*) set -- "$@" --output "$display" --mode 1366x768 --scale "1.25x1.25" ;;
+ LVDS*) set -- "$@" --output "$display" --primary ;;
+ DP*) set -- "$@" --output "$display" --primary --scale "1.1x1.1" ;;
+ esac
+ done
+
+fi
+
+
+eval "xrandr --auto $*"
+
diff --git a/.local/bin/desktop/show-i3-keybindings b/.local/bin/desktop/show-i3-keybindings
new file mode 100755
index 0000000..45d0626
--- /dev/null
+++ b/.local/bin/desktop/show-i3-keybindings
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ -n "$TERM" ]; then
+ grep '^bindsym' ~/.config/i3/config | sort |
+ sed 's/^bindsym \(\S*\)\s\+\(.*\)$/\1|\2/; s/\$super+/  /; s/Shift+/וּ /; s/$alt+/Alt /; s/Ctrl+/Ctrl /' |
+ column --table --separator='|' | less -r
+else
+ grep '^bindsym' ~/.config/i3/config | sort |
+ sed 's/^bindsym \(\S*\)\s\+\(.*\)$/\1|\2/; s/\$super+/  /; s/Shift+/Shift /; s/$alt+/Alt /; s/Ctrl+/Ctrl /' |
+ column --table --separator='|' | yad --text-info
+fi
diff --git a/.local/bin/desktop/toggle-xeyes b/.local/bin/desktop/toggle-xeyes
new file mode 100755
index 0000000..af5c590
--- /dev/null
+++ b/.local/bin/desktop/toggle-xeyes
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if pidof -q xeyes; then
+ killall xeyes
+else
+ setsid -f xeyes
+fi
diff --git a/.local/bin/desktop/torbrowser b/.local/bin/desktop/torbrowser
new file mode 100755
index 0000000..27e365b
--- /dev/null
+++ b/.local/bin/desktop/torbrowser
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+help() { echo "torbrowser - open or search in tor browser
+USAGE: torbrowser <open|search> [query]"; }
+
+cmd="$1"
+case "$cmd" in
+ open) extra_cmds='' ;;
+ search) extra_cmds='press ctrl+k' ;;
+ *) help >&2; exit 1 ;;
+esac
+
+query="$2"
+window="Tor Browser"
+windows=$(wmctrl -l)
+if [ "${windows##*"$window"}" = "$windows" ]; then
+ # query="$(dmenu -p "search in tor browser")" || exit
+ torbrowser-launcher && sleep 3
+fi
+
+press() {
+ xdotool keyup ctrl shift alt super meta BackSpace Tab Escape Return
+ xdotool key "$1"
+}
+
+wmctrl -a "$window"
+press ctrl+t
+$extra_cmds
+xdotool type "$query"
+press Return
diff --git a/.local/bin/desktop/volctl b/.local/bin/desktop/volctl
new file mode 100755
index 0000000..7d0edb9
--- /dev/null
+++ b/.local/bin/desktop/volctl
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+help() { echo "volctl - change system volume
+USAGE: volctl <toggle|up|down>"; }
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+
+case "$1" in
+ toggle) wpctl set-mute @DEFAULT_SINK@ toggle ;;
+ up) wpctl set-volume @DEFAULT_SINK@ 5%+ ;;
+ down) wpctl set-volume @DEFAULT_SINK@ 5%- ;;
+ *) help >&2; exit 1 ;;
+esac
+
+vol="$(wpctl get-volume @DEFAULT_SINK@ | tr -d .)"
+vol="${vol#Volume: }"
+
+notify() {
+ if [ -n "$DISPLAY" ]; then
+ notify-send -t 3000 -r 93475 "$1"
+ else
+ printf 'volume : '
+ wpctl get-volume @DEFAULT_SINK@
+ fi
+}
+
+if [ "$vol" != "${vol% \[MUTED\]}" ]; then
+ vol="${vol% \[MUTED\]}"
+ muted=1
+else
+ muted=0
+fi
+
+vol="$(printf '%.0f' "$vol")"
+
+msg=""
+if [ "$vol" -gt "100" ]; then icon="📢"; msg=" Boosted"
+elif [ "$vol" = "100" ]; then icon="🔊"; msg=" Maxed"
+elif [ "$vol" -gt "70" ]; then icon="🔊"
+elif [ "$vol" -gt "30" ]; then icon="🔉"
+elif [ "$vol" -gt "0" ]; then icon="🔈"
+else icon="🔇"
+fi
+
+if [ "$muted" -eq 1 ]; then
+ notify "🔇 Volume Muted ($vol%)"
+else
+ notify "$icon Volume$msg: $vol%"
+fi
+
diff --git a/.local/bin/development/dev b/.local/bin/development/dev
new file mode 100755
index 0000000..76f1772
--- /dev/null
+++ b/.local/bin/development/dev
@@ -0,0 +1,179 @@
+#!/bin/sh
+
+err() { [ "$DEV_SUPRESS_ERRORS" = 1 ] ||
+ printf "dev: %s\n" "$@" >&2; exit 5; }
+
+[ "$#" -lt 2 ] && { err "dev - execute action based on file
+USAGE: dev <ACTION> <FILE> [ARGS...]"; }
+
+action="$1"
+file="$2"
+basename="${file##*/}"
+shift 2
+
+[ -e "$file" ] || err "$file: No such file or directory"
+
+# auxilary functions
+findweb() { find "$@" -or -name '*.html'; }
+
+
+
+### #################################################################
+### BEGIN TASKS
+### #################################################################
+
+sh_lint() { shellcheck -x "$file"; }
+sh_run() { $(sed -n '1s|^#!/.*/\(.*\)|\1|p' "$file") "$file" "$@"; }
+zsh_run() { zsh "$file" "$@"; }
+awk_run() { awk -f "$file" "$@"; }
+pl_run() { perl "$file" "$@"; }
+
+md_run() { glow --pager --style dark "$file"; }
+md_test() { pandoc -t pdf "$file" | zathura -; }
+tex_compile() { pdflatex -output-directory="$(dirname "$file")" "$file"; }
+tex_clean() { find "$(dirname "${1}")" -regex \
+ '.*\(_minted.*\|.*\.\(4tc\|xref\|tmp\|pyc\|pyg\|pyo\|fls\|vrb\|fdb_latexmk\|bak\|swp\|aux\|log\|synctex\(busy\)\|lof\|lot\|maf\|idx\|mtc\|mtc0\|nav\|out\|snm\|toc\|bcf\|run\.xml\|synctex\.gz\|blg\|bbl\)\)' -delete; }
+html_format() { tidy -q "$file" 2>/dev/null; }
+html_lint() { tidy -q "$file" >/dev/null; }
+html_run() { w3m "$file"; }
+js_test() { node "$file"; }
+json_format() { jq . "$file"; }
+php_run() { php "$file" "$@"; }
+
+c_compile() { make "${file%.c}"; }
+c_run() { "$(realpath "${file%.c}")" "$@"; }
+c_clean() { rm -v "${file%.c}"; }
+
+go_format() { gofmt "$file"; }
+go_lint() { gofmt -d "$file"; }
+go_compile() { go build "$file"; }
+go_run() { "$(realpath "${file%.go}")" "$@"; }
+go_test() { go run "$file" "$@"; }
+go_serve() { findweb . -name '*.go' | entr -r sh -c "printf '\n\n$ go run *.go\n'; go run *.go"; }
+
+c_test() {
+ out="${file%.c}"
+ # ARGS="$(sed -nE -e 's|.*#include\s*<(.*)>|-l\1|gp' "$file" |
+ # paste -d' ' -s)"
+ # echo "$ clang -o $out $file $ARGS"
+ # clang -o "$out" "$file" $ARGS && "$out" "$@"
+ make "$out" && echo && "$(realpath "$out")" "$@"
+}
+
+cpp_test() {
+ out="$(realpath "${file%.cpp}")"
+ if [ -f GNUmakefile ] || [ -f makefile ] || [ -f Makefile ]; then
+ make && "${out%/*}/main" "$@"
+ else
+ g++ -o "$out" "$file" && "$out" "$@"
+ fi
+}
+
+ino_test() {
+ [ -t 1 ] || set -- --no-color
+ if [ -c /dev/ttyACM0 ]; then
+ arduino-cli compile --fqbn arduino:avr:uno "$file" "$@"
+ arduino-cli upload --fqbn arduino:avr:uno --port /dev/ttyACM0 "$file" "$@"
+ if [ -t 1 ]; then
+ picocom /dev/ttyACM0
+ else
+ stty -F /dev/ttyACM0 raw 9600
+ cat /dev/ttyACM0
+ fi
+ else
+ arduino-cli compile --fqbn arduino:avr:uno --output-dir . "$file" "$@"
+ rm -- *.eep *.elf *.bin *.with_bootloader.hex
+ fi
+}
+
+java_test() {
+ if [ -f build.xml ]; then
+ ant
+ build="$(find . -name 'classes' -or -name 'build' | tail -1)"
+ class="$({ cd "$build" &&
+ find . -name "$(basename "$file" .java).class"; } |
+ tail -1 | cut -c 3- | sed 's|.class||g' | tr '/' '.')"
+ else
+ mkdir -pv build
+ build="$(dirname "$file")/build"
+ class="$(basename "$file" .java)"
+ javac -d "$build" "$file"
+ fi
+ java -cp "$build:lib/*" "$class"
+}
+
+kt_test() {
+ out="${file%.*}.jar"
+ bash /opt/android-studio/plugins/Kotlin/kotlinc/bin/kotlinc "$file" -include-runtime -d "$out"
+ java -jar "$out"
+ rm "$out"
+}
+
+py_serve() { findweb . -name '*.py' | entr -r python "$file"; }
+# py_lint() {
+# [ -t 1 ] && printf '\033[33m'
+# pycodestyle "$file" >&2
+# [ -t 1 ] && printf '\033[0;39m'
+# }
+
+py_run() {
+ python "$file" "$@"
+ # if [ -x "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" ]; then
+ # "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" "$file" "$@"
+ # else
+ # python "$file" "$@"
+ # fi
+}
+
+### #################################################################
+### END TASKS
+### #################################################################
+
+
+
+filetype=$(file --brief --mime-type "$file")
+case $filetype in
+ text/x-c) filetype_ext="c" ;;
+ text/x-script.python) filetype_ext="py" ;;
+ text/x-shellscript) filetype_ext="sh" ;;
+ text/html) filetype_ext="html" ;;
+ application/javascript) filetype_ext="js" ;;
+ text/x-php) filetype_ext="php" ;;
+ text/x-awk) filetype_ext="awk" ;;
+esac
+
+if [ "${basename#*.}" != "${basename}" ]; then
+ file_ext="${basename##*.}"
+else
+ [ -z "$filetype_ext" ] && err "no file type association for $filetype"
+ NO_BASENAME=1
+fi
+
+execute_task() {
+ [ "$NO_BASENAME" != 1 ] && {
+ file_task="${file_ext}_${action}"
+ [ "${tasks#*"[$file_task]"}" != "$tasks" ] &&
+ { $file_task; local ret=$?; local tasked=1; }
+ }
+ [ "$tasked" != 1 ] && {
+ filetype_task="${filetype_ext}_${action}"
+ [ "${tasks#*"[$filetype_task]"}" != "$tasks" ] &&
+ { $filetype_task; local ret=$?; local tasked=1; }
+ }
+ [ "$tasked" != 1 ] && return 1
+ [ "$ret" != 0 ] && printf "\nshell returned %s\n" "$ret" >&2
+ return 0
+}
+
+tasks="$(sed -n "/^### BEGIN TASKS$/,/^### END TASKS$/ s/\(^[a-zA-Z0-9_]\+\)().*/[\1]/p" "$0")"
+
+if [ "$action" = test ]; then
+ execute_task && exit
+ for action in lint compile run; do
+ execute_task && tested=1
+ done
+ [ "$tested" != 1 ] && err "no tests for .${file_ext:-$filetype_ext} file"
+ exit 0
+fi
+
+execute_task || err "no $action action for .${file_ext:-$filetype_ext} file"
diff --git a/.local/bin/development/getcomproot b/.local/bin/development/getcomproot
new file mode 100755
index 0000000..16e946a
--- /dev/null
+++ b/.local/bin/development/getcomproot
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# author: Luke Smith
+#
+# A helper script for LaTeX/groff files used by `compiler` and `opout`.
+# The user can add the root file of a larger project as a comment as below:
+# % root = mainfile.tex
+# And the compiler script will run on that instead of the opened file.
+
+texroot="$(grep -i "^.\+\s*root\s*=\s*\S\+" "$1")"
+texroot="${texroot##*=}"
+texroot="${texroot//[\"\' ]}"
+
+[ -f "$texroot" ] && readlink -f "$texroot" || exit 1
diff --git a/.local/bin/development/gitpush b/.local/bin/development/gitpush
new file mode 100755
index 0000000..97aa43b
--- /dev/null
+++ b/.local/bin/development/gitpush
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+case "$(git config --get remote.origin.url)" in
+ *csstudent41*) sshadd ~/.ssh/github.com_id_ed25519 ;;
+ *labstudent41*) sshadd ~/.ssh/labstudent41_id_ed25519 ;;
+esac
+
+git add --all
+git commit # --allow-empty-message
+git push -u origin
diff --git a/.local/bin/development/gitw b/.local/bin/development/gitw
new file mode 100755
index 0000000..881c81c
--- /dev/null
+++ b/.local/bin/development/gitw
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# git-web: open the url of current git repositary in a web browser.
+# USAGE: gitw [remote]
+# 'remote' is set to origin if not provided.
+
+err() { printf "gitw: %s\n" "$@" >&2; exit 1; }
+
+git rev-parse --is-inside-work-tree >/dev/null || exit
+
+remote="${1:-origin}"
+url="$(git remote get-url "$remote" |
+ sed "s|^git@\(\S\+\):|https://\1/|")" || exit
+
+[ -z "$url" ] || [ "$remote" = "$url" ] &&
+ err "remote has no url: $remote"
+
+xdg-open "$url"
diff --git a/.local/bin/development/ipy b/.local/bin/development/ipy
new file mode 100755
index 0000000..1f39550
--- /dev/null
+++ b/.local/bin/development/ipy
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+unset PYTHONSTARTUP
+"${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/ipython" "$@"
diff --git a/.local/bin/development/ipytest b/.local/bin/development/ipytest
new file mode 100755
index 0000000..17a5a55
--- /dev/null
+++ b/.local/bin/development/ipytest
@@ -0,0 +1,23 @@
+#!/bin/sh
+# create a 'dev' firefox profile and use it in selenium
+
+[ -z "$FF_DEV_PROFILE" ] && [ -d ~/.librewolf ] &&
+ FF_DEV_PROFILE="$(find ~/.librewolf/ -maxdepth 1 -type d -name '????????.dev')"
+
+[ -z "$FF_DEV_PROFILE" ] && [ -d ~/.librewolf ] &&
+ FF_DEV_PROFILE="$(find ~/.mozilla/ -maxdepth 1 -type d -name '????????.dev')"
+
+ipy -i -c "
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+
+options = webdriver.FirefoxOptions()
+options.binary_location = '/usr/bin/librewolf'
+options.profile = webdriver.FirefoxProfile(\"$FF_DEV_PROFILE\")
+
+d = webdriver.Firefox(options=options)
+d.get(\"${1:-http://127.0.0.1}\")
+
+import atexit
+atexit.register(d.quit)
+"
diff --git a/.local/bin/development/nx b/.local/bin/development/nx
new file mode 100755
index 0000000..862be99
--- /dev/null
+++ b/.local/bin/development/nx
@@ -0,0 +1,148 @@
+#!/bin/sh
+
+help() {
+ echo "nx - create new script"
+ echo "USAGE: nx <script_name>"
+}
+
+err() { printf '%s: %s\n' "$0" "$@" >&2; exit 1; }
+warn() {
+ printf '%s: %s [Y/n] ' "$0" "$@" >&2; read -r arg
+ case "$arg" in ''|y|Y) ;; *) exit ;; esac
+}
+
+while getopts 'h' o; do case "$o" in
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help && exit 1
+[ "$#" -gt 1 ] && err "too many arguments. Only one expected"
+
+
+new_script() {
+ cat << EOF > "$1"
+#!/bin/sh
+
+help() { echo "$1 -
+
+USAGE:
+ $1 [OPTION]...
+
+OPTIONS:
+ -h show this help message"; }
+
+err() { printf '$1: %s\n' "\$@" >&2; exit 1; }
+while getopts 'h' o; do case "\$o" in
+ h) help; exit ;;
+ *) err "invalid option -- '\$OPTARG'" ;;
+esac done
+shift \$((OPTIND - 1))
+
+[ "\$#" -lt 1 ] && help >&2 && exit 1
+
+EOF
+
+ chmod u+x -- "$1" || exit
+}
+
+
+new_c_file() {
+ cat << EOF > "$1"
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello\n");
+
+ return 0;
+}
+EOF
+}
+
+
+new_cpp_file() {
+ cat << EOF > "$1"
+#include <iostream>
+
+using namespace std;
+
+int main()
+{
+ cout << "Hello" << endl;
+
+ cin.get();
+ return 0;
+}
+EOF
+}
+
+
+new_py_file() {
+ cat << EOF > "$1"
+import timeit
+
+print("Finished in %fs" % timeit.timeit())
+EOF
+}
+
+
+new_java_file() {
+ PATTERN="Scanner"
+ VIMCMDS="normal!2n\n noh"
+ cat << EOF > "$1"
+import java.util.Scanner;
+
+class ${1%.java} {
+ public static void main(String args[]) {
+ Scanner sc = new Scanner(System.in);
+
+ System.out.println("Finished!");
+ sc.close
+ }
+}
+EOF
+}
+
+
+file="$1"
+
+new_file() {
+ case "$file" in
+ *.c) new_c_file "$file" ;;
+ *.cpp) new_cpp_file "$file" ;;
+ *.py) new_py_file "$file" ;;
+ *.java) new_java_file "$file" ;;
+ *) new_script "$file" ;;
+ esac
+}
+
+if [ -f "$file" ]; then
+ [ ! -w "$file" ] && chmod u+rw "$file"
+ if [ -s "$file" ]; then
+ warn "'$file' already exists, edit existing file?" || exit
+ else
+ warn "an empty file '$file' already exists, fill and edit?" &&
+ new_file "$file"
+ fi
+elif [ -e "$file" ]; then
+ err "'$file' already exists and is a non-regular file"
+else
+ new_file "$file"
+fi
+
+ls -lF --color -- "$file"
+
+case "$EDITOR" in
+ '') echo "$0: \$EDITOR variable not set" >&2 && exit 1 ;;
+ vi|*vim*)
+ VIMCONF="$(mktemp)"; export VIMCONF
+ [ -n "$VIOPTS" ] && echo "set $VIOPTS" >> "$VIMCONF"
+ [ -n "$PATTERN" ] && echo "/$PATTERN" >> "$VIMCONF"
+ [ -n "$VIMCMDS" ] && echo "$VIMCMDS" >> "$VIMCONF"
+ $EDITOR -S "$VIMCONF" "$file"
+ rm -f "$VIMCONF"
+ ;;
+ *) $EDITOR "$file" ;;
+esac; exit
diff --git a/.local/bin/development/opout b/.local/bin/development/opout
new file mode 100755
index 0000000..3adc8fd
--- /dev/null
+++ b/.local/bin/development/opout
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+basename="${1%.*}"
+err() { printf "opout: %s\n" "$@" >&2; exit 1; }
+
+case "${*}" in
+ '') err "filename required" ;;
+ *.tex|*.sil|*.m[dse]|*.[rR]md|*.mom|*.[0-9]) target="$(getcomproot "$1" || echo "$1")" ; setsid -f "${OPENER:-xdg-open}" "${target%.*}".pdf >/dev/null 2>&1 ;;
+ *.html) setsid -f xdg-open "$basename".html >/dev/null 2>&1 ;;
+ *.sent) setsid -f sent "$1" >/dev/null 2>&1 ;;
+ *) err "file extension unmatched"
+esac
diff --git a/.local/bin/development/pipsearch b/.local/bin/development/pipsearch
new file mode 100755
index 0000000..0d1d495
--- /dev/null
+++ b/.local/bin/development/pipsearch
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+{ sleep 1 && tmux send-keys /search\ results Enter; } &
+tmux new w3m "http://pypi.org/search?q=$*"
diff --git a/.local/bin/development/py b/.local/bin/development/py
new file mode 100755
index 0000000..af32c95
--- /dev/null
+++ b/.local/bin/development/py
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+"${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" "$@"
+
diff --git a/.local/bin/development/pyh b/.local/bin/development/pyh
new file mode 100755
index 0000000..fdd524a
--- /dev/null
+++ b/.local/bin/development/pyh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# python-help: get help for keywords in python
+
+[ -x "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" ] &&
+ alias python="${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python"
+
+if [ "$#" -gt 0 ]; then
+ python -c "help('$*')"
+else
+ python -c "help()"
+fi
diff --git a/.local/bin/development/texclear b/.local/bin/development/texclear
new file mode 100755
index 0000000..6ad3c12
--- /dev/null
+++ b/.local/bin/development/texclear
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Clears the build files of a LaTeX/XeLaTeX build.
+# I have vim run this file whenever I exit a .tex file.
+
+[ "${1##*.}" = "tex" ] && {
+ find "$(dirname "${1}")" -regex '.*\(_minted.*\|.*\.\(4tc\|xref\|tmp\|pyc\|pyg\|pyo\|fls\|vrb\|fdb_latexmk\|bak\|swp\|aux\|log\|synctex\(busy\)\|lof\|lot\|maf\|idx\|mtc\|mtc0\|nav\|out\|snm\|toc\|bcf\|run\.xml\|synctex\.gz\|blg\|bbl\)\)' -delete
+} || printf "Provide a .tex file.\n"
+
diff --git a/.local/bin/fcode b/.local/bin/fcode
new file mode 100755
index 0000000..8da7a17
--- /dev/null
+++ b/.local/bin/fcode
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# fzf-unicode: get a list of emojis or unicode charecters using fzf
+# place your charecter files in plain text in ~/.local/share/chars/*
+
+FZF_HIST="$HOME/.local/share/fzf/unicode_history"
+mkdir -pv ~/.local/share/fzf
+
+if [ "$OPENFLAG" = 0 ]; then
+ notify-send fzf-unicode "$*"
+ chosen="$(printf '%s\n' "$@" | cut -d\ -f1 | tr -d '\n')"
+ echo "$chosen" | xclip -selection clipboard
+ notify-send "'$chosen' copied to clipboard."
+ exit
+fi
+
+cut -d ';' -f1 ~/.local/share/chars/* |
+ fzf -m --history="$FZF_HIST" \
+ --header="Copy Emojis to Clipboard" --header-first \
+ --preview 'printf "%s\n" {+} | cut -d\ -f1 | tr -d "\n"' \
+ --preview-window=nohidden,up,1 \
+ --bind 'ctrl-/:change-preview-window(down|up)' \
+ --bind 'enter:execute(echo {q} >> $FZF_HIST; OPENFLAG=0 fzf-unicode {+})'
diff --git a/.local/bin/fdict b/.local/bin/fdict
new file mode 100755
index 0000000..8a4ed61
--- /dev/null
+++ b/.local/bin/fdict
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# fzf-dict: get word definitions using sdcv
+
+mkdir -pv ~/.local/share/fzf
+export SDCV_PAGER="less -R"
+
+if [ "$OPENFLAG" = 0 ]; then
+ sdcv --color \
+ -u 'WordNet® 3.0 (En-En)' \
+ -u 'American Heritage Dictionary 4th Ed. (En-En)' \
+ -u 'Urban Dictionary P1 (En-En)' \
+ -u 'Urban Dictionary P2 (En-En)' \
+ "$@"
+ sdcv -u 'Wikipedia English - Free Encyclopedia' "$@" | w3m -T text/html
+ exit
+fi
+
+grep -v \' "${PREFIX:-/usr}/share/dict/words" | fzf \
+ --history "$HOME/.local/share/fzf/word_history" \
+ --header "Startdict Dictionary" --header-first \
+ --preview='OPENFLAG=0 fzf-words {} | fold -sw "$FZF_PREVIEW_COLUMNS"' \
+ --preview-window='nohidden,75%' --tiebreak=begin --print-query \
+ --bind 'alt-enter:execute(OPENFLAG=0 fzf-words {q})' \
+ --bind 'enter:execute(OPENFLAG=0 fzf-words {})'
diff --git a/.local/bin/fgrp b/.local/bin/fgrp
new file mode 100755
index 0000000..ddf3448
--- /dev/null
+++ b/.local/bin/fgrp
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# fzf-grep: browse through grepped lines using fzf
+
+if [ "$OPENFLAG" = 0 ]; then
+ location="$(echo "$*" | sed 's/^\(.*\):\([0-9]\+\):.*$/\1|\2/')"
+ file="${location%|*}"; line="${location##*|}"
+ case "${OPENWITH:=$EDITOR}" in
+ ''|vi|*vim*) $OPENWITH +"$line" "$file" ;;
+ *) $OPENWITH "$file" ;;
+ esac; exit
+fi
+
+mkdir -pv "${XDG_DATA_HOME:=$HOME/.local/share}/fzf"
+export FZF_HIST="$XDG_DATA_HOME/fzf/grep_history"
+grep -Rnsi --exclude-dir=.git --exclude-dir=node_modules --color=always "$@" |
+ fzf --ansi \
+ --history="$FZF_HIST" \
+ --prompt="grep > " \
+ --preview='preview "$(echo {1} | cut -d: -f1)"' \
+ --preview-window="hidden" \
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview' \
+ --bind "ctrl-r:reload(grep -Rns --color=always $*)" \
+ --bind 'enter:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 fgrp {})' \
+ --bind 'alt-e:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 OPENWITH=${EDITOR:-vi} fgrp {})' \
+ --bind 'alt-o:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 OPENWITH=${OPENER:-xdg-open} fgrp {})' \
+ --bind 'alt-O:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 OPENWITH=${FILES:-lf} fgrp {})'
diff --git a/.local/bin/filter b/.local/bin/filter
new file mode 100755
index 0000000..9d3e5e3
--- /dev/null
+++ b/.local/bin/filter
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+help() { echo "filter - filter input based on given expression to evaluate
+
+USAGE:
+ filter [OPTION]... <FILTER_EXPRESSION> [FILES]...
+
+OPTIONS:
+ -i update files with filtered content
+ -h show this help message
+
+FILTER_EXPRESSION is a contains the command string that will be executed to test
+the input line. {} should be used as a placeholder that will be replaced to the
+double-quoted string of the input line. If the command evaluates to true, the
+line is printed to stdout.
+"; }
+
+err() { printf 'filter: %s\n' "$@" >&2; exit 1; }
+while getopts 'ih' o; do case "$o" in
+ i) iflag=1 ;;
+ h) help; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+filter="$1"; shift
+
+evaluate() {
+ while IFS= read -r line; do
+ escaped_line="$(printf "%s\n" "$line" | sed "s|\"|\\\\\\\\\"|")"
+ cmd="$(printf "%s\n" "$filter" | sed "s|{}|\"$escaped_line\"|")"
+ eval "$cmd" && printf "%s\n" "$line"
+ done
+}
+
+if [ "$iflag" = 1 ]; then
+ for file in "$@"; do
+ [ -z "$1" ] && err "option -i requires file argument and none were passed"
+ tmp="$(mktemp "/tmp/$file.tmp-filter.XXXXXX")"
+ evaluate < "$file" > "$tmp"
+ mv "$tmp" "$file"
+ done
+ exit
+fi
+
+if [ -n "$1" ]; then
+ evaluate < "$@"
+else
+ evaluate
+fi
+
diff --git a/.local/bin/fm b/.local/bin/fm
new file mode 100755
index 0000000..2f4fbb8
--- /dev/null
+++ b/.local/bin/fm
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# fzf-man: fuzzy search manual pages
+
+if [ "$OPENFLAG" = 0 ]; then
+ input="$*"; page="${input%%)*}";
+ name="${page%%[ (]*}"; section="${page#*(}"
+ if [ "$name" = "$section" ]; then
+ man "$name"
+ else
+ man "$section" "$name"
+ fi; exit
+fi
+
+mkdir -pv "${XDG_DATA_HOME:=$HOME/.local/share}/fzf"
+export FZF_HIST="${XDG_DATA_HOME:=$HOME/.local/share}/fzf/manual_history"
+
+apropos -l "${@:-.}" | fzf --history="$FZF_HIST" --prompt="man: " \
+ --preview='MANWIDTH=$FZF_PREVIEW_COLUMNS OPENFLAG=0 fm {}' \
+ --preview-window="hidden" --tiebreak="begin" \
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview' \
+ --bind 'enter:execute(echo {1} >> "$FZF_HIST"; OPENFLAG=0 fm {})'
diff --git a/.local/bin/fmd b/.local/bin/fmd
new file mode 100755
index 0000000..0139d77
--- /dev/null
+++ b/.local/bin/fmd
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# fzf-media: fuzzy search media files
+# Useful when you want to look through a list of video without having to
+# bother with their individual supplementary files like subtitles.
+
+export PREVIEW="${PREVIEW:-"cat \"\$(dirname {})/.description/\${\$(basename {})%.*}.txt\" 2>/dev/null || preview {}"}"
+
+find "$@" -type f \
+ ! -path '*/.*' \
+ ! -name '*.srt' \
+ ! -name '*.vtt' \
+ ! -name '*.description' \
+ ! -wholename '.description/*' \
+ ! -name '*.info.json' \
+ ! -name '*.live_chat.json' \
+ ! -name '*.yt*' |
+ sort |
+ fzf --multi --reverse \
+ --history="${FZF_HIST:=$HOME/.local/share/fzf/media_history}" \
+ --header="${FZF_HEADER:-Browse Media Files}" --header-first \
+ --preview="$PREVIEW" --preview-window=hidden \
+ --bind 'alt-C:execute( ffbrowser "$(mediainfo --inform="General;%Comment%" {})" )' \
+ --bind 'ctrl-o:execute(append-to-history {q} "$FZF_HIST"; ${OPENER:-xdg-open} {})' \
+ --bind "alt-3:change-preview($PREVIEW)" \
+ --bind 'alt-#:execute($PREVIEW | less)'
diff --git a/.local/bin/fpm b/.local/bin/fpm
new file mode 100755
index 0000000..8da3d35
--- /dev/null
+++ b/.local/bin/fpm
@@ -0,0 +1,148 @@
+#!/bin/sh
+
+help() { echo "fzf-pm - fzf package manager
+
+USAGE:
+ fzf-pkgs [OPTION]... [QUERY]
+
+OPTIONS:
+ -g list global [all] packages
+ -l list local [instllaed] packages (default)
+ -i select and install packages (implies -g)
+ -u select and uninstall packages (implies -l)
+ -v show verbose output
+ -h show this help message
+
+ (for Arch linux only)
+ -a AUR_HELPER specify command for AUR helper
+
+ (special options)
+ -s PACKAGE print package info
+ -p print package manager
+
+ Note: passing global (-g) or local (-l) pkg list will cancel
+ any install (-i) or uninstall (-u) operations started previously.
+
+ENVIRONMENT VARIABLES:
+ AUR_HELPER set an AUR helper command for Arch linux
+
+Following package managers are supported:
+ apt, pkg, pacman and any pacman compatible AUR helper
+
+QUERY is mandatory when using an AUR Helper" ;}
+
+while getopts 's:gliuha:p' o; do case "$o" in
+ s) sflag=0; pkg="$OPTARG" ;;
+ g) operation=""; opmsg=""; list_all=0 ;;
+ l) operation=""; opmsg=""; list_all=1 ;;
+ i) operation="install_pkgs"; opmsg="to Install"; list_all=0 ;;
+ u) operation="uninstall_pkgs"; opmsg="to Uninstall"; list_all=1 ;;
+ h) help; exit ;;
+ a) export AUR_HELPER="$OPTARG" ;;
+ p) pflag=0 ;;
+ *) printf "fzf-pkgs: invalid option -- '%s'" "$OPTARG"; exit 1 ;;
+esac done
+shift $((OPTIND - 1))
+
+if command -v apt-get >> /dev/null; then
+ alias pkg_sort='sed -e "s/ - / => /"'
+
+ if [ "$list_all" = 0 ]; then
+ export pkg_info='apt-cache show'
+ alias list_pkgs='apt-cache search .'
+ alias search_pkg='apt-cache search'
+ else
+ export DPKG_COLOR='always'
+ export pkg_info='dpkg-query --status'
+ format='${Package} - ${Description}\n'
+ alias list_pkgs='dpkg-query --show --showformat "$format"'
+ alias search_pkg='dpkg-query --show --showformat "$format" | grep'
+ fi
+
+ if command -v pkg >> /dev/null; then
+ export PKGMAN="pkg"
+ alias install_pkgs='pkg install'
+ alias uninstall_pkgs='pkg uninstall'
+ else
+ export PKGMAN="apt"
+ alias install_pkgs='sudo apt-get install'
+ alias uninstall_pkgs='sudo apt-get remove'
+ fi
+
+elif command -v pacman >> /dev/null; then
+ alias pkg_sort='sed -e "N;s/\n\s*/ => /"'
+
+ if [ -n "$AUR_HELPER" ]; then
+ export PKGMAN="$AUR_HELPER"
+ if command -v "$PKGMAN" >/dev/null; then
+ alias install_pkgs='$PKGMAN -S'
+ alias uninstall_pkgs='$PKGMAN -Rns'
+ else
+ echo "fzf-pkgs: AUR Helper '$PKGMAN' command not found" >&2 &&
+ exit 1
+ fi
+ else
+ export PKGMAN='pacman'
+ alias install_pkgs='sudo $PKGMAN -S'
+ alias uninstall_pkgs='sudo $PKGMAN -Rns'
+ fi
+
+ if [ "$list_all" = 0 ]; then
+ export pkg_info="$PKGMAN --color=always -Si"
+ alias list_pkgs='$PKGMAN --color=always -Ss'
+ alias search_pkg='$PKGMAN --color=always -Ss'
+ else
+ export pkg_info="$PKGMAN --color=always -Qi"
+ alias list_pkgs='$PKGMAN --color=always -Qs'
+ alias search_pkg='$PKGMAN --color=always -Qs'
+ fi
+
+else
+ echo "fzf-pkgs: package manager not found" >&2
+ exit 1
+fi
+
+if [ "$pflag" = 0 ]; then
+ printf "%s\n" "$PKGMAN"
+ exit
+elif [ "$sflag" = 0 ]; then
+ printf "$ %s '%s'\n" "$pkg_info" "$pkg"
+ $pkg_info $pkg
+ exit
+fi
+
+query="$1"
+if [ -n "$AUR_HELPER" ] && [ -z "$query" ] && [ "$list_all" = 0 ]; then
+ echo "fzf-pkgs: providing QUERY is mandatory when using an AUR Helper"
+ exit 1
+ # printf "query: "; read -r query
+ # [ -z "$query" ] && exit 1
+fi
+
+if [ -n "$query" ]; then
+ prompt="searching '$query' "
+ get_pkgs() { search_pkg "$query"; }
+else
+ get_pkgs() { list_pkgs; }
+fi
+
+[ -z "$FZF_HIST_DIR" ] && export FZF_HIST_DIR="$HOME/.local/share/fzf"
+fzff() {
+ preview='
+ echo "selected packages:";
+ printf "\t%s\n" {+1} | tr " " "\n"
+ echo
+ eval "$pkg_info 2>/dev/null" {1}
+ '
+ fzf --ansi --multi \
+ --history="${FZF_HIST_DIR:-$HOME/.local/share}/package_history" \
+ --header="Select packages $opmsg" --header-first --prompt="$prompt> " \
+ --preview="$preview" --preview-window="hidden" --tiebreak='begin' \
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview'
+}
+
+pkgs="$(get_pkgs | pkg_sort | fzff | cut -d' ' -f1 | tr '\n' ' ')"
+[ -n "$pkgs" ] || exit 2
+echo "$pkgs"
+[ -n "$operation" ] && eval $operation $pkgs
+
diff --git a/.local/bin/fsend b/.local/bin/fsend
new file mode 100755
index 0000000..f75739d
--- /dev/null
+++ b/.local/bin/fsend
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+content="${1:-$(xprint | fzf -m --header "Select clipboard lines to send")}" || exit
+host="${2:-$(sed '/^Host \(.*\)/!d; s//\1/' ~/.ssh/config | fzf --header "Send to?")}" || exit
+sshadd "$(find ~/.ssh -name "${host}_id_*" | head -1)"
+[ -z "$NOTIFY" ] && command -V notify-send >/dev/null && NOTIFY=1
+
+notify() {
+ [ "$NOTIFY" = 1 ] && notify-send -r 8529 "$@"
+ printf "%s\n" "$@"
+}
+
+transferto() {
+ notify "Transfering files to $host:$1/" "$content"
+ rsync -PLru --progress "$content" "$host:$1/"
+}
+
+if [ -e "$content" ]; then
+ case "$content" in
+ *.txt|*.pdf) transferto "Documents" ;;
+ *)
+ case "$(file --brief --mime-type "$content")" in
+ text/*) transferto "Documents" ;;
+ image/*) transferto "Pictures" ;;
+ audio/*) transferto "Music" ;;
+ video/*) transferto "Videos" ;;
+ *) transferto "Downloads" ;;
+ esac
+ ;;
+ esac
+
+else
+ case "$content" in
+ http*) notify "Opening link in $host" "$content"
+ ssh "$host" "xdg-open \"$content\"" ;;
+ *) notify "Copying in $host's clipboard" "$content"
+ ssh "$host" "termux-clipboard-set \"$content\"" ;;
+ esac
+fi
+
+if [ $? = 0 ]; then
+ notify "  Done (fzf-send)"
+else
+ notify " ❌ Errors Occured (fzf-send)"
+ printf "\n%s" "Press Enter to continue..."
+ read -r
+fi
diff --git a/.local/bin/fw b/.local/bin/fw
new file mode 100755
index 0000000..ada20e8
--- /dev/null
+++ b/.local/bin/fw
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+export FZF_HIST="$HOME/.local/share/fzf/wiki_history"
+export FZF_HEADER="Search local wiki files"
+export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --delimiter='/' --with-nth=-1"
+fmd \
+ /mnt/storage/Media/Tech/ \
+ /mnt/storage/Library \
+ /usr/share/doc/arch-wiki/html/en \
+ "$@" ! -name '*.css'
diff --git a/.local/bin/help b/.local/bin/help
new file mode 100755
index 0000000..046b1cc
--- /dev/null
+++ b/.local/bin/help
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+help() { echo "help - get help for shell commands or programs
+
+USAGE:
+ help [OPTION...] <QUERY>
+
+OPTIONS:
+ -a show all available help
+ -h show this help message
+ "; }
+
+while getopts 'avh' o; do case "$o" in
+ a) aflag=0;;
+ h) help; exit ;;
+ *) printf "help: invalid option -- '%s'" "$OPTARG" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help >&2 && exit 2
+
+
+##############################################################
+### H E L P F U N C T I O N S I N O R D E R ###
+##############################################################
+
+man_query() {
+ man -w "$query" >/dev/null 2>&1 || return 2
+ man -a "$query"
+}
+
+info_query() {
+ # if command -v info
+ [ -n "$(info --where "$query")" ] || return 2
+ info --vi-keys --all "$query"
+}
+
+show_script() {
+ file="$(which "$query" 2>/dev/null)" || return 2
+ "${PAGER:-less}" "$file"
+}
+
+cmd_help() {
+ if content="$($query -h 2>/dev/null)"; then
+ printf "$ %s -h" "$query"
+ elif content="$($query --help 2>/dev/null)"; then
+ printf "$ %s --help" "$query"
+ else
+ return 2
+ fi
+ printf '\n%s\n' "$content" | "${PAGER:-less}" -X
+ echo
+}
+
+tldr_query() {
+ content="$(tldr --color=always "$query" 2>/dev/null)" || return 2
+ printf "\n$ tldr '%s'\n%s\n\n" "$query" "$content" | "${PAGER:-less}" -X
+}
+
+pkg_info() {
+ if command -v pacman >/dev/null; then
+ cmd="$ pacman -Si $query"
+ info="$(pacman -Si "$query" 2>/dev/null)" || return 2
+ elif command -v apt >/dev/null; then
+ cmd="$ apt show $query"
+ info="$(apt show "$query" 2>/dev/null)" || return 2
+ elif command -v pkg >/dev/null; then
+ cmd="$ pkg info $query"
+ info="$(pkg info "$query" 2>/dev/null)" || return 2
+ else
+ return
+ fi
+ [ -z "$info" ] && return 2
+ printf "\n%s\n%s\n\n" "$cmd" "$info" | "${PAGER:-less}" -X
+}
+
+##########################################################
+### E N D O F H E L P F U N C T I O N S ###
+##########################################################
+
+
+help_funcs="$(sed -ne "/^### H E L P/,/^### E N D/ s/^\([a-zA-Z0-9_]\+\)\(\).*/\1/p" "$0")"
+main() {
+ if [ "$aflag" = 0 ]; then
+ eval "$help_funcs"
+ else
+ eval "$(echo "$help_funcs" | sed -z 's/\n/||/g' | sed 's/||$//')"
+ fi
+}
+
+query="$*"
+[ -f "$query" ] && { "${PAGER:-less}" "$query"; exit 0; }
+[ -d "$query" ] &&
+ { ls -AlFh --color --group-directories-first -- "$query"; exit 0; }
+
+command -V "$query" 2>/dev/null && { echo; export HELP_FOUND=1; }
+
+main || [ "$HELP_FOUND" = 1 ] ||
+ { echo "No help found for '$query'" >&2; exit 2; }
diff --git a/.local/bin/launch-gtypist b/.local/bin/launch-gtypist
new file mode 100755
index 0000000..c5f452f
--- /dev/null
+++ b/.local/bin/launch-gtypist
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+
+help() {
+ echo "launch-gtypist - launch gtypist in fullscreen
+
+USAGE:
+ launch-gtypist [OPTION]...
+
+OPTIONS:
+ -l LESSON start gtypist lesson
+ -f FILE load lesson from a file
+ -e % max error percentage
+ -v verbose output
+ -h show this help message
+
+LESSON can optionally be followed by the exercise number seprated by a colon.
+Example - Q2:3, which means 3rd execercise of lesson Q2.
+If LESSON is provided through the command line along with a file with -f
+option then the file will ignored"
+}
+
+
+while getopts 'l:f:e:vh' o; do case "$o" in
+ l) use_file=1; current="$OPTARG" ;;
+ f) use_file=0; file="$OPTARG" ;;
+ e) export GTYPIST_OPTS="$GTYPIST_OPTS --max-error=$OPTARG" ;;
+ v) vflag=0 ;;
+ h) help; exit ;;
+ *) echo "launch-gtypist: invalid option -- '${OPTARG}'"
+ echo 'Try `launch-gtypist -h` for more information.' >&2; exit 1 ;;
+esac done
+shift $((OPTIND - 1))
+
+msg() { [ "$vflag" = 0 ] && printf ':: %s\n' "$@" >&2; true; }
+notify() {
+ [ -n "$DISPLAY" ] && notify-send 'launch-gtypist' "$@"
+ printf '%s\n' "$@"
+}
+
+if [ "$use_file" = 0 ]; then
+ msg "Getting lesson from file: $file"
+ current="$(sed -En 's/^gtypist lesson\s*-\s*(.*)$/\1/p' "$file")" ||
+ exit 1
+ [ -z "$current" ] &&
+ printf 'launch-gtypist: current gtypist lesson not found in:\n\t%s\n' \
+ "$file" && exit 1
+fi
+
+[ -n "$1" ] && current="$1" && shift
+[ "${current#*:}" != "$current" ] && lesson="${current%:*}" &&
+ exercise="${current##*:}" || lesson="$current"
+[ -n "$lesson" ] && {
+ msg "Gtypist lesson name: $lesson"
+ export GTYPIST_OPTS="$GTYPIST_OPTS --start-label=$lesson"
+}
+
+tmuxx() { [ -z "$TMUX" ] && return 1; tmux "$@"; }
+
+
+shift_exercise() {
+ msg "Shifting to exercise $exercise"
+ sleep 1
+
+ keys() {
+ if [ -n "$TMUX" ]; then
+ for key in "$@"; do
+ tmux send-keys -t gtypist "$key";
+ done
+ else
+ xdotool key --clearmodifiers --delay 100 "$@"
+ fi
+ }
+
+ for i in $(seq "$((exercise-1))"); do
+ if [ "$i" -gt 1 ]; then
+ keys Escape n
+ else
+ keys space space space space space Escape Escape n
+ fi
+ done
+}
+
+
+msg "Switcing to default keymap"
+# kmonad-manage stop
+remap -x
+
+msg "Waiting for terminal columns to get more than 100..."
+while [ "$(tput cols)" -lt 100 ]; do sleep 0.5; done
+tmuxx rename-window gtypist
+[ -n "$exercise" ] && shift_exercise &
+msg " >>> Gtypist started."
+msg " gtypist $GTYPIST_OPTS $*"
+gtypist $GTYPIST_OPTS $@
+msg " <<< Gtypist exited."
+tmuxx set-window-option automatic-rename on
+
+msg "Switcing to user keymap"
+# kmonad-manage start
+remap
diff --git a/.local/bin/lessopen.sh b/.local/bin/lessopen.sh
new file mode 100755
index 0000000..df4a58e
--- /dev/null
+++ b/.local/bin/lessopen.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+[ -d "$1" ] && { tree -CL 3 "$1"; exit; }
+
+if command -V highlight >/dev/null; then
+ highlight --force --out-format=ansi -- "$1"
+else
+ cat "$1"
+fi
diff --git a/.local/bin/loop b/.local/bin/loop
new file mode 100755
index 0000000..d3dccc7
--- /dev/null
+++ b/.local/bin/loop
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+help() {
+ echo "loop - execute command in loop
+
+USAGE:
+ loop [OPTION]... <COMMAND>
+
+OPTIONS:
+ -n INTERVAL sleep for given INTERVAL time between loops
+ all arguments of \`sleep\` command are valid
+ -c COUNT maximum count of loops (default: 1000)
+ -s clear screen for every execution
+ -q quiet, redirect output to /dev/null
+ -h show this help message
+
+ENVIRONMENT VARIABLES:
+ LOOP_INTERVAL set INTERVAL time
+ MAX_LOOP_COUNT set loop COUNT"
+}
+
+err() { printf 'loop: %s\n' "$@" >&2; exit 1; }
+
+while getopts 'sc:n:qh' o; do case "$o" in
+ s) cflag=1 ;;
+ n) export LOOP_INTERVAL="$OPTARG" ;;
+ c) export MAX_LOOP_COUNT="$OPTARG" ;;
+ q) qflag=1 ;;
+ h) help; exit ;;
+ *) err "invalid option -- $OPTARG" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && err "no COMMAND given"
+cmds="$*"
+max_count="${MAX_LOOP_COUNT:-1000}"
+[ -n "$LOOP_INTERVAL" ] && cmds="$cmds; sleep '$LOOP_INTERVAL'"
+[ "$cflag" = 1 ] && cmds="clear; $cmds"
+[ "$qflag" = 1 ] && cmds="$cmds >/dev/null"
+
+for count in $(seq "$max_count"); do
+ eval "$cmds" || break
+done
+
+[ "$count" -ge "$max_count" ] && err "reached max loop COUNT: $max_count"
diff --git a/.local/bin/lsinputs b/.local/bin/lsinputs
new file mode 100755
index 0000000..8bb091f
--- /dev/null
+++ b/.local/bin/lsinputs
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do
+ (
+ syspath="${sysdevpath%/dev}"
+ devname="$(udevadm info -q name -p $syspath)"
+ [[ "$devname" == "bus/"* ]] && exit
+ eval "$(udevadm info -q property --export -p $syspath)"
+ [[ -z "$ID_SERIAL" ]] && exit
+ echo "/dev/$devname - $ID_SERIAL"
+ )
+done
diff --git a/.local/bin/mnt b/.local/bin/mnt
new file mode 100755
index 0000000..8470667
--- /dev/null
+++ b/.local/bin/mnt
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+sudo mkdir -p "${MOUNTPATH:=/run/media/$USER}"
+sudo chown "$USER:$USER" "$MOUNTPATH"
+
+makepath() {
+ [ -d "$path" ] && { rmdir "$path" || exit; }
+ mkdir -p "$path"
+}
+
+case "$1" in
+
+ mtp:*)
+ path="$MOUNTPATH/${1#mtp:}"
+ makepath
+ simple-mtpfs "$path"
+ ;;
+
+ *:|*:/*)
+ path="$MOUNTPATH/${1%%:*}"
+ makepath
+ if grep -q "^\[${1%:}\]$" "${XDG_CONFIG_HOME:-$HOME/.config}/rclone/rclone.conf"; then
+ rclone mount --daemon "$1" "$path"
+ else
+ sshfs "$1" "$path"
+ fi
+ ;;
+
+ *)
+ if sudo cryptsetup isLuks "$1"; then
+ uuid=$(sudo cryptsetup luksUUID "$1" | tr -d -)
+ test -b /dev/disk/by-id/dm-uuid-*$uuid* && exit
+ sudo cryptsetup open "$1" "crypt-$uuid"
+ udisksctl mount -b "/dev/mapper/crypt-$uuid"
+ exit
+ fi
+ udisksctl mount -b "$1"
+ ;;
+esac
diff --git a/.local/bin/open b/.local/bin/open
new file mode 100755
index 0000000..a996105
--- /dev/null
+++ b/.local/bin/open
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+[ -z "$1" ] && echo "USAGE: open <FILE>" >&2 && exit 1
+
+for file in "$@"; do
+ case "$file" in
+
+ *.pdf|*.djvu|*.epub) setsid -f zathura "$file" ;;
+ *.png|*.jpg|*.jpeg|*.webp) setsid -f nsxiv "$file" ;;
+ *.gif|*.mkv|*.mp3|*.mp4|*.webm|*.ogg) ${PLAYER:-mpv --sub-auto=fuzzy} "$file" ;;
+ *.html) ${BROWSER:-w3m} "$file" ;;
+ *.pl.txt) fpl "$file" ;;
+ *.txt|*.description) ${PAGER:-less} "$file" ;;
+ *.md) glow --pager "$file" ;;
+ *.css|*.json|*.ipynb|*.vim|*.lua|*.iso|*.zip) LESSOPEN="|preview %s" less -r "$file" ;;
+ *.srt) fzf-subtitles -o "$file" ;;
+ *.dig) setsid -f digital "$file" ;;
+ *.doc|*.docx|*.ppt|*.pptx) setsid -f libreoffice "$file" ;;
+ *.sc|*.xls|*.xlsx) sc-im "$file" ;;
+ *.sim1) simulide "$file" ;;
+ *.xz) ${EDITOR:-nvim} "$file" ;;
+
+ *)
+ filetype="$(file --dereference --brief --mime-type "$file")"
+ case "$filetype" in
+ inode/directory) ${FILES:-lf} "$file" ; exit ;;
+ text/html*) ${BROWSER:-w3m} "$file" ;;
+ *pdf|*djvu|*epub+zip|*oxps|*fictionbook) setsid -f zathura "$file" ;;
+ text/*|*json|*zip|*zstd) "${EDITOR:-nvim}" "$file" ;;
+ application/vnd.openxmlformats-officedocument.*) setsid -f libreoffice "$file" ;;
+ application/sc) sc-im "$file" ;;
+ application/x-executable) "$file" ;;
+ image/*) setsid -f nsxiv "$file" ;;
+ video/*|audio/*) ${PLAYER:- mpv --sub-auto=fuzzy} "$file" ;;
+ *)
+ xdg-open "$file" || exit
+ [ -n "$DISPLAY" ] && notify-send "⚠️ open: unknown filetype" "$filetype"
+ echo "open: unknown filetype: $filetype" >&2
+ ;;
+ esac
+ ;;
+
+ esac
+
+ file="$(realpath "$file")"
+ sed -i "\|^$file$|d" "${XDG_DATA_HOME:-$HOME/.local/share}/openhist"
+ echo "$file" >> "${XDG_DATA_HOME:-$HOME/.local/share}/openhist"
+done
diff --git a/.local/bin/preview b/.local/bin/preview
new file mode 100755
index 0000000..f0cedb0
--- /dev/null
+++ b/.local/bin/preview
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+if [ -d "$1" ]; then
+ if [ -x /bin/eza ] || [ -x /usr/bin/eza ]; then
+ eza -alhF --group-directories-first --color=always --icons -- "$1"
+ else
+ ls -lhAF --group-directories-first --color -- "$1"
+ fi
+ readme="$(find "$1" -maxdepth 1 -name "README.*" | head -1)"
+ [ -n "$readme" ] && preview "$readme"
+ exit
+fi
+
+alias highlight='highlight --out-format=ansi'
+
+case "$1" in
+ '') echo "preview: file name required" >&2; exit 1 ;;
+ *.html) w3m -dump "$1" ;;
+ *.md) glow -s dark --width="${FZF_PREVIEW_COLUMNS:-"$(tput cols)"}" "$1" ;;
+ # *.vim) highlight --syntax=vim --replace-tabs=2 -- "$1" ;;
+ *.js|*.vim|*.lua) highlight -- "$1" ;;
+ *.txt|*.description|*.srt) cat -- "$1" ;;
+ *.png|*.jpg|*.jpeg|*.webp|*.mp3|*.ogg|*.mp4|*.mkv|*.webm) mediainfo -- "$1" ;;
+ *.info.json) jq -C . "$1" ;;
+ *.json|*.ipynb) highlight --syntax=json -- "$1" ;;
+ *.tgz|*.tar.gz) tar tzf "$1" ;;
+ *.tar.bz2|*.tbz2) tar tjf "$1" ;;
+ *.tar.txz|*.txz) xz --list "$1" ;;
+ *.tar) tar tf "$1" ;;
+ *.zip|*.jar|*.war|*.ear|*.oxt) unzip -l "$1" ;;
+ *.rar) unrar l "$1" ;;
+ *.7z) 7z l "$1" ;;
+ *.zst) zstdcat "$1" ;;
+ *.[1-8]) man "$1" | col -b ;;
+ *.o) nm "$1" ;;
+ *.torrent) transmission-show "$1" ;;
+ *.iso) iso-info --no-header -l "$1" ;;
+ *odt|*.ods|*.odp|*.sxw) odt2txt "$1" ;;
+ *.doc) catdoc "$1" ;;
+ *.docx) docx2txt "$1" - ;;
+ # *.csv) sed s/,/\\n/g "$1" ;;
+
+ *)
+ filetype=$(file --dereference --brief --mime-type "$1")
+ case $filetype in
+ *html) w3m -dump "$1" ;;
+ text/markdown) glow -s dark -w "$(tput cols)" "$1" ;;
+ application/json) highlight --syntax=json --replace-tabs=2 -- "$1" ;;
+ text/*) highlight --force -- "$1" ;;
+ audio/*|video/*|image/*) mediainfo -- "$1" ;;
+ *xz) xz --list "$1" ;;
+ *zip|*tar*|*7z*|*bzip2) atool --list -- "$1" ;;
+ *opendocument*) odt2txt "$1" ;;
+ application/pgp-encrypted) gpg -d -- "$1" ;;
+ *) file -b "$1" ;;
+ esac
+ ;;
+
+esac
diff --git a/.local/bin/search b/.local/bin/search
new file mode 100755
index 0000000..d9c1a3d
--- /dev/null
+++ b/.local/bin/search
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+help() { echo "search - search tool for unix users
+
+USAGE:
+ search [OPTION]... <QUERY>
+
+OPTIONS:
+ -h show this help message"; }
+
+err() { printf 'search: %s\n' "$@" >&2; exit 1; }
+while getopts 'h' o; do case "$o" in
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+if [ "$PREVIEWFLAG" = 0 ]; then
+ [ -z "$INDEX" ] && export INDEX="$(echo "$*" | cut -d: -f1)"
+ [ -z "$LINE" ] && export LINE="$(echo "$*" | cut -d: -f2-)"
+
+ case "$INDEX" in
+ wiki) "${FILE_HANDLER:-preview}" "/usr/share/doc/$LINE" ;;
+ docs) "${FILE_HANDLER:-preview}" "$HOME/.local/share/Zeal/Zeal/docsets/$LINE" ;;
+ media) "${FILE_HANDLER:-preview}" "/run/media/$USER/Storage/Media/$LINE" ;;
+ library) "${FILE_HANDLER:-preview}" "/run/media/$USER/Storage/Library/$LINE" ;;
+ tldr) tldr --color=always "$LINE" ;;
+ word) sdcv-dict "$LINE" ;;
+ man)
+ page="${LINE%%)*}"; name="${page%%[ (]*}"; section="${page#*(}"
+ if [ "$name" != "$section" ]; then
+ man "$section" "$name"
+ else
+ man "$name"
+ fi
+ ;;
+ pacman) pacman --color=always -Si "${LINE%% *}" ;;
+ esac
+ exit
+fi
+
+if [ "$OPENFLAG" = 0 ]; then
+ export INDEX="$(echo "$*" | cut -d: -f1)"
+ export LINE="$(echo "$*" | cut -d: -f2-)"
+ export FILE_HANDLER="open"
+
+ case "$INDEX" in
+ wiki|docs|web-docs|media|library|man) PREVIEWFLAG=0 search ;;
+ *) PREVIEWFLAG=0 search | less -r ;;
+ esac
+ exit
+fi
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+FZF_HIST="$HOME/.local/share/fzf/search_history"
+
+cd "${SEARCHDB:-$HOME/.cache/search}" || exit
+mkdir -pv ~/.local/share/fzf
+grep -Rsi --color=always "$@" | fzf --ansi \
+ --history="$FZF_HIST" \
+ --preview="PREVIEWFLAG=0 search {}" \
+ --bind 'enter:execute(echo {} >> $FZF_HIST; OPENFLAG=0 search {})'
diff --git a/.local/bin/searchdb b/.local/bin/searchdb
new file mode 100755
index 0000000..57e3fa8
--- /dev/null
+++ b/.local/bin/searchdb
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+help() {
+ echo "searchdb - update local search database
+
+USAGE:
+ searchdb [OPTION]...
+
+OPTIONS:
+ -x clear all databases
+ -h show this help message"
+}
+
+err() { printf 'searchdb: %s\n' "$@" >&2; exit 1; }
+while getopts 'xh' o; do case "$o" in
+ x) rm -rf ~/.cache/search; exit ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+rm -rf ~/.cache/search
+export SEARCHDB="$HOME/.cache/search"
+mkdir -p "$SEARCHDB" || exit
+ln -sf /usr/share/dict/words "$SEARCHDB/word"
+
+tldr --list > "$SEARCHDB/tldr"
+apropos . > "$SEARCHDB/man"
+pacman -Ss | sed -e "N;s/\n\s*/ => /" > "$SEARCHDB/pacman"
+
+list() { find -L "$@" ! -wholename '*/.git*' -printf "%P\n"; }
+list /usr/share/doc > "$SEARCHDB/wiki"
+list ~/.local/share/Zeal/Zeal/docsets > "$SEARCHDB/docs"
+list -L "/run/media/$USER/Storage/Media" > "$SEARCHDB/media"
+list "/run/media/$USER/Storage/Library" > "$SEARCHDB/library"
diff --git a/.local/bin/setbg b/.local/bin/setbg
new file mode 100755
index 0000000..b636a37
--- /dev/null
+++ b/.local/bin/setbg
@@ -0,0 +1,18 @@
+--2024-10-23 16:26:25-- https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/setbg
+Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
+Resolving github.com (github.com)... 20.207.73.82
+Connecting to github.com (github.com)|20.207.73.82|:443... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: unspecified [text/html]
+Saving to: ‘setbg’
+
+ 0K .......... .......... .......... .......... .......... 3.47M
+ 50K .......... .......... .......... .......... .......... 9.00M
+ 100K .......... .......... .......... .......... .......... 10.7M
+ 150K .......... .......... .......... .......... .......... 10.7M
+ 200K .......... .......... .......... .......... .......... 10.9M
+ 250K .......... .......... .......... .......... .......... 11.2M
+ 300K .......... .......... .......... ....... 10.8M=0.04s
+
+2024-10-23 16:26:25 (8.07 MB/s) - ‘setbg’ saved [345695]
+
diff --git a/.local/bin/shortcuts b/.local/bin/shortcuts
new file mode 100755
index 0000000..545799f
--- /dev/null
+++ b/.local/bin/shortcuts
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+config="${XDG_CONFIG_HOME:-$HOME/.config}"
+bmdirs="$config/shell/bm-dirs"
+bmfiles="$config/shell/bm-files"
+
+shell_shortcuts="$config/shell/shortcutrc"
+zsh_named_dirs="$config/zsh/zshnameddirrc"
+lf_shortcuts="$config/lf/shortcutrc"
+vim_shortcuts="$config/nvim/shortcuts.vim"
+
+rm -f "$zsh_named_dirs" "$lf_shortcuts" "$vim_shortcuts"
+printf "# vim: filetype=sh\n" > "$shell_shortcuts"
+
+eval "echo \"$(cat "$bmdirs")\"" |
+awk -F'\t' "
+ !/^\s*#/ && !/^\s*$/ {
+ gsub(\"\\\s*#.*$\", \"\");
+ printf(\"alias %s='cd %s && ls -A'\n\", \$1, \$2) >> \"$shell_shortcuts\"
+ printf(\"hash -d %s=%s\n\", \$1, \$2) >> \"$zsh_named_dirs\"
+ printf(\"map c%s :cd %s\n\", \$1, \$2) >> \"$lf_shortcuts\"
+ printf(\"cmap ;%s %s\n\", \$1, \$2) >> \"$vim_shortcuts\"
+ }
+ "
+
+eval "echo \"$(cat "$bmfiles")\"" |
+awk -F'\t' "
+ !/^\s*#/ && !/^\s*$/ {
+ gsub(\"\\\s*#.*$\", \"\");
+ printf(\"alias %s='\$EDITOR %s'\n\", \$1, \$2) >> \"$shell_shortcuts\"
+ printf(\"hash -d %s=%s\n\", \$1, \$2) >> \"$zsh_named_dirs\"
+ printf(\"map E%s $\$EDITOR %s\n\", \$1, \$2) >> \"$lf_shortcuts\"
+ printf(\"cmap ;%s %s\n\", \$1, \$2) >> \"$vim_shortcuts\"
+ }
+ "
diff --git a/.local/bin/shorts/adbs b/.local/bin/shorts/adbs
new file mode 100755
index 0000000..bca7733
--- /dev/null
+++ b/.local/bin/shorts/adbs
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+adb -s "${ADB_DEVICE}" shell "$@"
diff --git a/.local/bin/shorts/append-to-history b/.local/bin/shorts/append-to-history
new file mode 100755
index 0000000..7d23dc8
--- /dev/null
+++ b/.local/bin/shorts/append-to-history
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+[ -n "$1" ] || exit
+sed -i "\|^${1}$|d" "${2}"
+echo "$1" >> "$2"
diff --git a/.local/bin/shorts/bs b/.local/bin/shorts/bs
new file mode 100755
index 0000000..7e7ec0a
--- /dev/null
+++ b/.local/bin/shorts/bs
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# build site
+
+cd "${SITE_BASE_DIR:-$HOME/Dev/sites/vikas.rocks}" || exit
+rm -rf public/*
+hugo
diff --git a/.local/bin/shorts/conv b/.local/bin/shorts/conv
new file mode 100755
index 0000000..92379e8
--- /dev/null
+++ b/.local/bin/shorts/conv
@@ -0,0 +1,10 @@
+#!/bin/sed -nf
+
+p
+s/\([0-9]\+\)[0-9]\{3\}\([^A-Za-z0-9]\|$\)/\1K\2/gp
+s/\([0-9]\+\)[0-9]\{3\}K\([^A-Za-z0-9]\|$\)/\1M\2/gp
+s/\([0-9]\+\)[0-9]\{3\}M\([^A-Za-z0-9]\|$\)/\1G\2/gp
+s/\([0-9]\+\)[0-9]\{3\}G\([^A-Za-z0-9]\|$\)/\1T\2/gp
+s/\([0-9]\+\)[0-9]\{3\}T\([^A-Za-z0-9]\|$\)/\1P\2/gp
+s/\([0-9]\+\)[0-9]\{3\}P\([^A-Za-z0-9]\|$\)/\1Z\2/gp
+s/\([0-9]\+\)[0-9]\{3\}Z\([^A-Za-z0-9]\|$\)/\1Y\2/gp
diff --git a/.local/bin/shorts/diffdirs b/.local/bin/shorts/diffdirs
new file mode 100755
index 0000000..9585f9f
--- /dev/null
+++ b/.local/bin/shorts/diffdirs
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+tree --dirsfirst -aL 3 "$1" > "$PREFIX/tmp/dir1.tree.txt"
+tree --dirsfirst -aL 3 "$2" > "$PREFIX/tmp/dir2.tree.txt"
+nvim -d "$PREFIX/tmp/dir1.tree.txt" "$PREFIX/tmp/dir2.tree.txt"
+
diff --git a/.local/bin/shorts/font2svg b/.local/bin/shorts/font2svg
new file mode 100755
index 0000000..539972d
--- /dev/null
+++ b/.local/bin/shorts/font2svg
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+fontforge -c "import fontforge; fontforge.open('$1').generate('${1%.*}.svg')"
diff --git a/.local/bin/shorts/preview-bat b/.local/bin/shorts/preview-bat
new file mode 100755
index 0000000..43d1532
--- /dev/null
+++ b/.local/bin/shorts/preview-bat
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+bat --tabs=2 --style=plain --color=always "$@"
diff --git a/.local/bin/shorts/preview-highlight b/.local/bin/shorts/preview-highlight
new file mode 100755
index 0000000..0972538
--- /dev/null
+++ b/.local/bin/shorts/preview-highlight
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+highlight --force --stdout --replace-tabs=2 --out-format=ansi "$@"
diff --git a/.local/bin/shorts/refcitx b/.local/bin/shorts/refcitx
new file mode 100755
index 0000000..e99fcd3
--- /dev/null
+++ b/.local/bin/shorts/refcitx
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+fcitx
+sleep 0.1
+remap
+
diff --git a/.local/bin/shorts/sc b/.local/bin/shorts/sc
new file mode 100755
index 0000000..8760379
--- /dev/null
+++ b/.local/bin/shorts/sc
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+sc-im "$@"
diff --git a/.local/bin/shorts/scrcpy-k b/.local/bin/shorts/scrcpy-k
new file mode 100755
index 0000000..139732b
--- /dev/null
+++ b/.local/bin/shorts/scrcpy-k
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+remap -x
+adb connect blue:43896
+notify-send scrcpy-k "Starting scrcpy..."
+scrcpy -K --no-playback
+notify-send scrcpy-k "Connection closed..."
+remap
diff --git a/.local/bin/shorts/ssha b/.local/bin/shorts/ssha
new file mode 100755
index 0000000..3cbf87c
--- /dev/null
+++ b/.local/bin/shorts/ssha
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+[ "$TERM" != "${TERM#st-256color}" ] && export TERM=xterm-256color
+sshadd "$(find ~/.ssh -name "${1}_id_*" | head -1)"
+ssh "$@" -t "tmux attach -t $USER || tmux new -s $USER"
diff --git a/.local/bin/shorts/sync-server b/.local/bin/shorts/sync-server
new file mode 100755
index 0000000..641db9c
--- /dev/null
+++ b/.local/bin/shorts/sync-server
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+sshadd "$HOME/.ssh/${1}_id_ed25519"
+sync() { rsync -PRru --delete --exclude "*.git" "$@"; }
+
+sync \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./vim/vimrc" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./tmux/tmux.conf" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./shell/aliasrc" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./shell/inputrc" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./shell/server.profile" \
+ "${1}:.config"
diff --git a/.local/bin/shorts/syncdrive b/.local/bin/shorts/syncdrive
new file mode 100755
index 0000000..3d010cc
--- /dev/null
+++ b/.local/bin/shorts/syncdrive
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+rclone -v sync --delete-excluded --exclude=".git/**" ~/GDrive gdrive:
diff --git a/.local/bin/shorts/synchs b/.local/bin/shorts/synchs
new file mode 100755
index 0000000..244dd48
--- /dev/null
+++ b/.local/bin/shorts/synchs
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+sync-server rpi
+
+# rsync -u ~/.config/lf/lfrc /tmp/lfrc
+# sed -i '/set icons/d' /tmp/lfrc
+# rsync -Pu /tmp/lfrc rpi:.config/lf/
diff --git a/.local/bin/shorts/synctab b/.local/bin/shorts/synctab
new file mode 100755
index 0000000..1e44419
--- /dev/null
+++ b/.local/bin/shorts/synctab
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+sshadd ~/.ssh/tab_id_ed25519
+sync() { rsync -Pru --delete --exclude "*.git" "$@"; }
+
+sync ~/GDrive/ tab:GDrive/
+sync "${XDG_VIDEOS_DIR:-$HOME/Videos}" tab:Videos/
+
+sync -R \
+ "${XDG_DOCUMENTS_DIR:-$HOME/Documents}/./allreader" \
+ "${XDG_DOCUMENTS_DIR:-$HOME/Documents}/./latex" \
+ "${XDG_DOCUMENTS_DIR:-$HOME/Documents}/./Notes/bookmarks.txt" \
+ tab:Documents/
+
+sync \
+ "${XDG_MUSIC_DIR:-$HOME/Music}/Piano" \
+ "${XDG_MUSIC_DIR:-$HOME/Music}/Devotional" \
+ tab:Music/
+
diff --git a/.local/bin/shorts/xdg-terminal-exec b/.local/bin/shorts/xdg-terminal-exec
new file mode 100755
index 0000000..43ed65d
--- /dev/null
+++ b/.local/bin/shorts/xdg-terminal-exec
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+st -e "$@"
diff --git a/.local/bin/shorts/xprint b/.local/bin/shorts/xprint
new file mode 100755
index 0000000..12156f2
--- /dev/null
+++ b/.local/bin/shorts/xprint
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+[ -n "$TERMUX_VERSION" ] && { termux-clipboard-get; exit; }
+
+xclip -out -selection clipboard 2>/dev/null ||
+xclip -out -selection secondry 2>/dev/null ||
+xclip -out -selection primary 2>/dev/null ||
+notify-send "Selection and clipboard is empty"
diff --git a/.local/bin/sshadd b/.local/bin/sshadd
new file mode 100755
index 0000000..6fb3b18
--- /dev/null
+++ b/.local/bin/sshadd
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+[ -z "$SSH_AUTH_SOCK" ] && export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
+msg=$(ssh-add -L 2>&1)
+if [ "$msg" = 'Could not open a connection to authentication agent.' ] ||
+ [ "$msg" = 'Error connecting to agent: No such file or directory' ] ||
+ [ "$msg" = 'Error connecting to agent: Connection refused' ]; then
+ rm -f "${SSH_AUTH_SOCK}"
+ ssh-agent -a "${SSH_AUTH_SOCK}" > /dev/null
+fi
+
+private_key="$1"
+content="$(cat "$1.pub")"
+if [ "$msg" = "The agent has no identities." ] ||
+ [ "${msg#*$content}" = "$msg" ]; then
+ ssh-add "$private_key"
+fi
diff --git a/.local/bin/statusbar/cpu_usage b/.local/bin/statusbar/cpu_usage
new file mode 100755
index 0000000..be729e2
--- /dev/null
+++ b/.local/bin/statusbar/cpu_usage
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+#
+# Copyright 2014 Pierre Mavro <deimos@deimos.fr>
+# Copyright 2014 Vivien Didelot <vivien@didelot.org>
+# Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com>
+#
+# Licensed under the terms of the GNU GPL v3, or any later version.
+
+use strict;
+use warnings;
+use utf8;
+use Getopt::Long;
+
+# default values
+my $t_warn = 50;
+my $t_crit = 80;
+my $cpu_usage = -1;
+
+sub help {
+ print "Usage: cpu_usage [-w <warning>] [-c <critical>]\n";
+ print "-w <percent>: warning threshold to become yellow\n";
+ print "-c <percent>: critical threshold to become red\n";
+ exit 0;
+}
+
+GetOptions("help|h" => \&help,
+ "w=i" => \$t_warn,
+ "c=i" => \$t_crit);
+
+# Get CPU usage
+$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it is
+open (MPSTAT, 'mpstat 1 1 |') or die;
+while (<MPSTAT>) {
+ if (/^.*\s+(\d+\.\d+)\s+$/) {
+ $cpu_usage = 100 - $1; # 100% - %idle
+ last;
+ }
+}
+close(MPSTAT);
+
+$cpu_usage eq -1 and die 'Can\'t find CPU information';
+
+# Print short_text, full_text
+printf "%.1f%%\n", $cpu_usage;
+# printf "%.2f%%\n", $cpu_usage;
+
+# # Print color, if needed
+# if ($cpu_usage >= $t_crit) {
+# print "#FF0000\n";
+# exit 33;
+# } elsif ($cpu_usage >= $t_warn) {
+# print "#FFFC00\n";
+# }
+
+exit 0;
diff --git a/.local/bin/statusbar/i3bandwidth b/.local/bin/statusbar/i3bandwidth
new file mode 100755
index 0000000..8877d28
--- /dev/null
+++ b/.local/bin/statusbar/i3bandwidth
@@ -0,0 +1,105 @@
+#!/usr/bin/bash
+# Copyright (C) 2012 Stefan Breunig <stefan+measure-net-speed@mathphys.fsk.uni-heidelberg.de>
+# Copyright (C) 2014 kaueraal
+# Copyright (C) 2015 Thiago Perrotta <perrotta dot thiago at poli dot ufrj dot br>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+case "$BLOCK_BUTTON" in
+ 2) $TERMINAL -e nvim "$0" ;;
+esac
+
+# Use the provided interface, otherwise the device used for the default route.
+if [[ -n $BLOCK_INSTANCE ]]; then
+ INTERFACE=$BLOCK_INSTANCE
+else
+ INTERFACE=$(ip route | awk '/^default/ { print $5 ; exit }')
+fi
+
+[ -z "$INTERFACE" ] && echo && exit
+
+# Issue #36 compliant.
+if ! [ -e "/sys/class/net/${INTERFACE}/operstate" ] || ! [ "$(cat "/sys/class/net/${INTERFACE}/operstate")" = "up" ]
+then
+ # echo "$INTERFACE down"
+ # echo "$INTERFACE down"
+ # echo "#FF0000"
+ echo " "
+ exit 0
+fi
+
+# path to store the old results in
+path="/dev/shm/$(basename "$0")-${INTERFACE}"
+
+# grabbing data for each adapter.
+read -r rx < "/sys/class/net/${INTERFACE}/statistics/rx_bytes"
+read -r tx < "/sys/class/net/${INTERFACE}/statistics/tx_bytes"
+
+# get time
+time=$(date +%s)
+
+# write current data if file does not exist. Do not exit, this will cause
+# problems if this file is sourced instead of executed as another process.
+if ! [[ -f "${path}" ]]; then
+ echo "${time} ${rx} ${tx}" > "${path}"
+ chmod 0666 "${path}"
+fi
+
+# read previous state and update data storage
+read -r old < "${path}"
+echo "${time} ${rx} ${tx}" > "${path}"
+
+# parse old data and calc time passed
+old=(${old//;/ })
+time_diff=$(( time - old[0] ))
+
+# sanity check: has a positive amount of time passed
+[[ "${time_diff}" -gt 0 ]] || { echo " "; exit; }
+
+# calc bytes transferred, and their rate in byte/s
+rx_diff=$(( rx - old[1] ))
+tx_diff=$(( tx - old[2] ))
+rx_rate=$(( rx_diff / time_diff ))
+tx_rate=$(( tx_diff / time_diff ))
+
+# shift by 10 bytes to get KiB/s. If the value is larger than
+# 1024^2 = 1048576, then display MiB/s instead
+
+# incoming
+rx_kib=$(( rx_rate >> 10 ))
+if [ "$rx_kib" -gt 1 ]; then
+ # echo -n "📥 "
+ echo -n "↓ "
+ if [[ "$rx_rate" -gt 1048576 ]]; then
+ printf '%sM' "$(echo "scale=1; $rx_kib / 1024" | bc)"
+ else
+ echo -n "${rx_kib}K"
+ fi
+fi
+
+# outgoing
+tx_kib=$(( tx_rate >> 10 ))
+if [ "$tx_kib" -gt 1 ]; then
+ # echo -n "📤 "
+ echo -n " ↑ "
+ if [[ "$tx_rate" -gt 1048576 ]]; then
+ printf '%sM' "$(echo "scale=1; $tx_kib / 1024" | bc)"
+ else
+ echo -n "${tx_kib}K"
+ fi
+fi
+
+# echo
+# echo
+# echo "$BLOCK_COLOR_LEVEL1"
diff --git a/.local/bin/statusbar/i3battery b/.local/bin/statusbar/i3battery
new file mode 100755
index 0000000..5b2fb15
--- /dev/null
+++ b/.local/bin/statusbar/i3battery
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+case "$BLOCK_BUTTON" in
+ 1) notify-send Temprature "$(sensors --no-adapter coretemp-isa-0000 |
+ tail +2 | sed "s|(.*)||")" ;;
+ 2) $TERMINAL -e "$EDITOR" "$0" ;;
+ 3) $TERMINAL -e battop ;;
+ 4) brightness up ;;
+ 5) brightness down ;;
+esac;
+
+# Loop through all attached batteries and format the info
+for battery in /sys/class/power_supply/BAT?*; do
+ capacity="$(cat "$battery/capacity" 2>&1)"
+ # If non-first battery, print a space separator.
+ # [ -n "${capacity+x}" ] && printf " "
+ # Sets up the status and capacity
+ status="$(cat "$battery/status" 2>&1)"
+ case "$status" in
+ "Full") icon="󰂄" ;;
+ "Discharging") case "$capacity" in
+ 9[0-9]) icon="󰂂" ;;
+ 8[0-9]) icon="󰂁" ;;
+ 7[0-9]) icon="󰂀" ;;
+ 6[0-9]) icon="󰁿" ;;
+ 5[0-9]) icon="󰁾" ;;
+ 4[0-9]) icon="󰁽" ;;
+ 3[0-9]) icon="󰁼" ;;
+ 2[0-9]) icon="󰁻" ;;
+ 1[0-9]|[0-9]) icon="󰁺" ;;
+ 100) icon="󰁹" ;;
+ esac ;;
+ "Charging") case "$capacity" in
+ 9[0-9]) icon="󰂋" ;;
+ 8[0-9]) icon="󰢞" ;;
+ 7[0-9]) icon="󰢞" ;;
+ 6[0-9]) icon="󰂉" ;;
+ 5[0-9]) icon="󰢝" ;;
+ 4[0-9]) icon="󰂈" ;;
+ 3[0-9]) icon="󰂇" ;;
+ 2[0-9]) icon="󰂆" ;;
+ 1[0-9]|[0-9]) icon="󰢜" ;;
+ 100) icon="󰂅" ;;
+ esac ;;
+ "Not charging") icon="󱉝" ;;
+ "Unknown") icon="󰂑" ;;
+ *) exit 1 ;;
+ esac
+ # Will make a warn variable if discharging and low
+ [ "$status" = "Discharging" ] && [ "$capacity" -le 25 ] && warn="❗"
+ # Prints the info
+ printf "%s%s %d%%" "$warn" "$icon" "$capacity"; unset warn
+done && printf "\\n"
+
+echo
+if [ $capacity -ge 80 ]; then
+ echo "$BLOCK_COLOR_LEVEL1"
+elif [ $capacity -ge 40 ]; then
+ echo "$BLOCK_COLOR_LEVEL2"
+elif [ $capacity -ge 20 ]; then
+ echo "$BLOCK_COLOR_LEVEL3"
+elif [ $capacity -ge 10 ]; then
+ echo "$BLOCK_COLOR_LEVEL4"
+else
+ echo "$BLOCK_COLOR_LEVEL5"
+fi
diff --git a/.local/bin/statusbar/i3cpu b/.local/bin/statusbar/i3cpu
new file mode 100755
index 0000000..c5eeb68
--- /dev/null
+++ b/.local/bin/statusbar/i3cpu
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+case "$BLOCK_BUTTON" in
+ 1) $TERMINAL -e gotop ;;
+ 2) $TERMINAL -e nvim "$(which i3cpu)" ;;
+ 3) echo "top,$TERMINAL -e top
+ htop,$TERMINAL -e htop
+ gotop,$TERMINAL -e gotop
+ nvtop,$TERMINAL -e nvtop" | jgmenu --vsimple --at-pointer ;;
+esac;
+
+cpu_usage="$(cpu_usage)"
+cpu="${cpu_usage%.*}"
+printf "%s" "$cpu_usage"
+# printf " "
+# sb-cpubars
+
+echo
+echo
+# Print color, if needed
+if [ "$cpu" -ge 90 ]; then
+ echo "$BLOCK_COLOR_LEVEL5";
+ exit 33;
+elif [ "$cpu" -ge 70 ]; then
+ echo "$BLOCK_COLOR_LEVEL4"
+elif [ "$cpu" -ge 50 ]; then
+ echo "$BLOCK_COLOR_LEVEL3"
+elif [ "$cpu" -ge 20 ]; then
+ echo "$BLOCK_COLOR_LEVEL2"
+else
+ echo "$BLOCK_COLOR_LEVEL1"
+fi
+
+
diff --git a/.local/bin/statusbar/i3cpubars b/.local/bin/statusbar/i3cpubars
new file mode 100755
index 0000000..c4c18af
--- /dev/null
+++ b/.local/bin/statusbar/i3cpubars
@@ -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/.local/bin/statusbar/i3cpuload b/.local/bin/statusbar/i3cpuload
new file mode 100755
index 0000000..6c14ddd
--- /dev/null
+++ b/.local/bin/statusbar/i3cpuload
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+#
+# Copyright 2014 Pierre Mavro <deimos@deimos.fr>
+# Copyright 2014 Vivien Didelot <vivien@didelot.org>
+# Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com>
+#
+# Licensed under the terms of the GNU GPL v3, or any later version.
+
+use strict;
+use warnings;
+use utf8;
+use Getopt::Long;
+
+# default values
+my $t_warn = $ENV{T_WARN} // 70; # default 50
+my $t_crit = $ENV{T_CRIT} // 90; # default 80
+my $cpu_usage = -1;
+my $decimals = $ENV{DECIMALS} // 2;
+my $label = $ENV{LABEL} // "";
+
+sub help {
+ print "Usage: cpu_usage [-w <warning>] [-c <critical>] [-d <decimals>]\n";
+ print "-w <percent>: warning threshold to become yellow\n";
+ print "-c <percent>: critical threshold to become red\n";
+ print "-d <decimals>: Use <decimals> decimals for percentage (default is $decimals) \n";
+ exit 0;
+}
+
+GetOptions("help|h" => \&help,
+ "w=i" => \$t_warn,
+ "c=i" => \$t_crit,
+ "d=i" => \$decimals,
+);
+
+# Get CPU usage
+$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it is
+open (MPSTAT, 'mpstat |') or die;
+while (<MPSTAT>) {
+ if (/^.*\s+(\d+\.\d+)[\s\x00]?$/) {
+ $cpu_usage = 100 - $1; # 100% - %idle
+ last;
+ }
+}
+close(MPSTAT);
+
+$cpu_usage eq -1 and die 'Can\'t find CPU information';
+
+# Print short_text, full_text
+print "${label}";
+printf "%.${decimals}f%%\n", $cpu_usage;
+
+
+# print "\n";
+# # Print color, if needed
+# if ($cpu_usage >= $t_crit) {
+# print "$ENV{BLOCK_COLOR_LEVEL5}\n";
+# exit 33;
+# } elsif ($cpu_usage >= $t_warn) {
+# print "$ENV{BLOCK_COLOR_LEVEL4}\n";
+# } elsif ($cpu_usage >= 50) {
+# print "$ENV{BLOCK_COLOR_LEVEL3}\n";
+# } elsif ($cpu_usage >= 20) {
+# print "$ENV{BLOCK_COLOR_LEVEL2}\n";
+# } else {
+# print "$ENV{BLOCK_COLOR_LEVEL1}\n";
+# }
+
+exit 0;
diff --git a/.local/bin/statusbar/i3memory b/.local/bin/statusbar/i3memory
new file mode 100755
index 0000000..edf9a73
--- /dev/null
+++ b/.local/bin/statusbar/i3memory
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+case "$BLOCK_BUTTON" in
+ 1) $TERMINAL -e gotop ;;
+ 2) $TERMINAL -e nvim "$(which i3cpu)" ;;
+ 3) echo "top,$TERMINAL -e top
+ htop,$TERMINAL -e htop
+ gotop,$TERMINAL -e gotop
+ nvtop,$TERMINAL -e nvtop" | jgmenu --vsimple --at-pointer ;;
+esac;
+
+memory="$(memory_percent)"
+printf "%s" "$(memory_usage)"
+# printf " "
+# sb-cpubars
+
+echo
+echo
+# Print color, if needed
+if [ "$memory" -ge 90 ]; then
+ echo "$BLOCK_COLOR_LEVEL5";
+ exit 33;
+elif [ "$memory" -ge 70 ]; then
+ echo "$BLOCK_COLOR_LEVEL4"
+elif [ "$memory" -ge 50 ]; then
+ echo "$BLOCK_COLOR_LEVEL3"
+elif [ "$memory" -ge 20 ]; then
+ echo "$BLOCK_COLOR_LEVEL2"
+else
+ echo "$BLOCK_COLOR_LEVEL1"
+fi
+
+
diff --git a/.local/bin/statusbar/i3weather b/.local/bin/statusbar/i3weather
new file mode 100755
index 0000000..2d34149
--- /dev/null
+++ b/.local/bin/statusbar/i3weather
@@ -0,0 +1,26 @@
+#!/bin/sh
+# i3block for displaying the current temperature, humidity and precipitation, if wttr.in i unavailable then WEATHER UNAVAILABLE will be displayed
+
+case "$BLOCK_BUTTON" in
+ '') ;;
+ 1)
+ $TERMINAL -e less -r ~/.cache/weather.txt & sleep 0.3
+ i3-msg 'move to workspace "12: Weather"; workspace "12: Weather"' >/dev/null 2>&1
+ ;;
+ 2) $TERMINAL -e nvim "$0" ;;
+ *) notify-send "⛅ Refreshing weather info..." ;;
+esac
+
+HTTP_WEATHER="https://wttr.in/Vasai"
+# weather="$(curl -s "$HTTP_WEATHER?format=%c%C++❄️+%t++☀️+%f++🌬️+%w")"
+weather="$(curl -Ss "$HTTP_WEATHER?0&T&Q" | cut -c 16- | head -2 |
+ xargs echo "$(curl -s "$HTTP_WEATHER?format=%c")")"
+
+if [ "$(echo "$weather" | grep -Ec "(Unknown|curl|HTML)")" -gt 0 ]; then
+ echo "WEATHER UNAVAILABLE"
+else
+ echo "${weather:-⛅ -- }"
+fi
+
+curl -s "$HTTP_WEATHER" > ~/.cache/weather.txt
+
diff --git a/.local/bin/statusbar/i3wifi b/.local/bin/statusbar/i3wifi
new file mode 100755
index 0000000..689e3a2
--- /dev/null
+++ b/.local/bin/statusbar/i3wifi
@@ -0,0 +1,37 @@
+#!/bin/sh
+# i3block for the displaying the wifi connectivity level
+# If the wifi interface exists but no connection is active, "down" shall be displayed.
+
+case "$BLOCK_BUTTON" in
+ 1) $TERMINAL -e nmtui ;;
+ 2) $TERMINAL -e nvim "$0" ;;
+ 3) $TERMINAL -e nethogs ;;
+ # 3) echo "nethogs,$TERMINAL -e nethogs
+ # bmon,$TERMINAL -e bmon
+ # nmtui, $TERMINAL -e nmtui" | jgmenu --vsimple --at-pointer ;;
+esac
+
+iface="$(find /sys/class/net/ -maxdepth 1 -name "w*" -printf "%f\n")"
+if [ "$(cat "/sys/class/net/$iface/operstate")" = 'down' ]; then
+ icon="󰤭"; quality="down"; color="$BLOCK_COLOR_LEVEL5"
+else
+ quality=$(grep "$iface" /proc/net/wireless | awk '{ print int($3 * 100 / 70) }')
+ if [ "$quality" = 100 ]; then
+ icon="󰤨"; color="$BLOCK_COLOR_LEVEL1"
+ elif [ "$quality" -ge 80 ]; then
+ icon="󰤥"; color="$BLOCK_COLOR_LEVEL1"
+ elif [ "$quality" -ge 60 ]; then
+ icon="󰤢"; color="$BLOCK_COLOR_LEVEL2"
+ elif [ "$quality" -ge 40 ]; then
+ icon="󰤟"; color="$BLOCK_COLOR_LEVEL3"
+ elif [ "$quality" -ge 20 ]; then
+ icon="󰤟"; color="$BLOCK_COLOR_LEVEL4"
+ else
+ icon="󰤯"; color="$BLOCK_COLOR_LEVEL5"
+ fi
+ [ -n "$quality" ] && quality="$quality%"
+fi
+
+echo "$icon $quality"
+echo
+echo "$color"
diff --git a/.local/bin/statusbar/memory_percent b/.local/bin/statusbar/memory_percent
new file mode 100755
index 0000000..2b8da66
--- /dev/null
+++ b/.local/bin/statusbar/memory_percent
@@ -0,0 +1,57 @@
+#!/bin/sh
+# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+TYPE="${BLOCK_INSTANCE:-mem}"
+
+awk -v type=$TYPE '
+/^MemTotal:/ {
+ mem_total=$2
+}
+/^MemFree:/ {
+ mem_free=$2
+}
+/^Buffers:/ {
+ mem_free+=$2
+}
+/^Cached:/ {
+ mem_free+=$2
+}
+/^SwapTotal:/ {
+ swap_total=$2
+}
+/^SwapFree:/ {
+ swap_free=$2
+}
+END {
+ if (type == "swap") {
+ free=swap_free/1024/1024
+ used=(swap_total-swap_free)/1024/1024
+ total=swap_total/1024/1024
+ } else {
+ free=mem_free/1024/1024
+ used=(mem_total-mem_free)/1024/1024
+ total=mem_total/1024/1024
+ }
+ pct=0
+ if (total > 0) {
+ pct=used/total*100
+ }
+ # full text
+ # printf("%.1fG/%.1fG", used, total)
+ # printf("%.1fG", used)
+ printf("%d", pct)
+}
+' /proc/meminfo
diff --git a/.local/bin/statusbar/memory_usage b/.local/bin/statusbar/memory_usage
new file mode 100755
index 0000000..8f0fee4
--- /dev/null
+++ b/.local/bin/statusbar/memory_usage
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+TYPE="${BLOCK_INSTANCE:-mem}"
+
+awk -v type=$TYPE '
+/^MemTotal:/ {
+ mem_total=$2
+}
+/^MemFree:/ {
+ mem_free=$2
+}
+/^Buffers:/ {
+ mem_free+=$2
+}
+/^Cached:/ {
+ mem_free+=$2
+}
+/^SwapTotal:/ {
+ swap_total=$2
+}
+/^SwapFree:/ {
+ swap_free=$2
+}
+END {
+ if (type == "swap") {
+ free=swap_free/1024/1024
+ used=(swap_total-swap_free)/1024/1024
+ total=swap_total/1024/1024
+ } else {
+ free=mem_free/1024/1024
+ used=(mem_total-mem_free)/1024/1024
+ total=mem_total/1024/1024
+ }
+ pct=0
+ if (total > 0) {
+ pct=used/total*100
+ }
+ # full text
+ # printf("%.1fG/%.1fG", used, total)
+ printf("%.1fG", used)
+}
+' /proc/meminfo
diff --git a/.local/bin/ttyl b/.local/bin/ttyl
new file mode 100755
index 0000000..fd71280
--- /dev/null
+++ b/.local/bin/ttyl
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+help() {
+ echo "ttyl - tty lock
+
+USAGE:
+ ttyl [OPTION]... [COMMAND]
+
+OPTIONS:
+ -a lock all TTYs
+ (default when no command is passed and terminal is a tty)
+ -c lock current TTY
+ -h show this help message"
+}
+
+err() { printf 'ttyl: %s\n' "$@" >&2; exit 1; }
+
+while getopts 'ach' o; do case "$o" in
+ a) lockall=0 ;;
+ c) lockall=1 ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+case "$lockall" in
+ 1) lock="vlock" ;;
+ 0) lock="vlock -a" ;;
+ *)
+ case "$(tty)" in
+ /dev/tty[1-7]) lock="vlock -a" ;;
+ *) lock="vlock" ;;
+ esac
+ ;;
+esac
+
+sleep 1 && $@ & $lock
diff --git a/.local/bin/unix b/.local/bin/unix
new file mode 100755
index 0000000..a9fb96e
--- /dev/null
+++ b/.local/bin/unix
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+#original artwork by http://www.sanderfocus.nl/#/portfolio/tech-heroes
+#converted to shell by #nixers @ irc.unix.chat
+
+cat << 'eof'
+ ,_ ,_==▄▂
+ , ▂▃▄▄▅▅▅▂▅¾. / /
+ ▄▆<´ "»▓▓▓%\ / / / /
+ ,▅7" ´>▓▓▓% / / > / >/%
+ ▐¶▓ ,»▓▓¾´ /> %/%// / /
+ ▓▃▅▅▅▃,,▄▅▅▅Æ\// ///>// />/ /
+ V║«¼.;→ ║<«.,`=// />//%/% / /
+ //╠<´ -²,)(▓~"-╝/¾/ %/>/ />
+ / / / ▐% -./▄▃▄▅▐, /7//;//% / /
+ / ////`▌▐ %zWv xX▓▇▌//&;% / /
+ / / / %//%/¾½´▌▃▄▄▄▄▃▃▐¶\/& /
+ </ /</%//`▓!%▓%╣[38;5;255;╣WY<Y)y&/`\
+ / / %/%//</%//\i7; ╠N>)VY>7; \_ UNIX IS VERY SIMPLE IT JUST NEEDS A
+ / /</ //<///<_/%\▓ V%W%£)XY _/%‾\_, GENIUS TO UNDERSTAND ITS SIMPLICITY
+ / / //%/_,=--^/%/%%\¾%¶%%} /%%%%%%;\,
+ %/< /_/ %%%%%;X%%\%%;, _/%%%;, \
+ / / %%%%%%;, \%%l%%;// _/%;, dmr
+ / %%%;, <;\-=-/ /
+ ;, l
+eof
diff --git a/.local/bin/web/fpl b/.local/bin/web/fpl
new file mode 100755
index 0000000..0398770
--- /dev/null
+++ b/.local/bin/web/fpl
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# You can pass any text file containing a list of video titles.
+# An fzf prompt will shown to select a video title.
+# The script will then try to find a video file whose name fuzzy matches the
+# selected title.
+
+[ -z "$1" ] && { echo "fzf-playlist: browse a list of video titles
+USAGE: fpl <PLAYLIST_FILE>" >&2; exit 1; }
+
+if [ "$OPENFLAG" = 1 ]; then
+
+ if [ -z "$OPENWITH" ]; then
+ files="$(find "${PWD%/*}")"
+ else
+ files="$(find "${PWD%/*}" -name '*.webm' -or -name '*.mkv' -or -name '*.mp4' -or \
+ -name '*.mp3' -or -name '*.ogg')"
+ fi
+
+ if [ -z "$OPENWITH" ]; then
+ for title in "$@"; do echo "$files" |
+ fzf --filter "$(printf '%s\n' "$title" | sed 's/[^A-Za-z0-9]*//g')"
+ echo; done
+ else
+ for title in "$@"; do $OPENWITH "$(echo "$files" |
+ fzf --filter "$(printf '%s\n' "$title" | sed 's/[^A-Za-z0-9]*//g')" |
+ head -1)"; echo; done
+ fi
+
+ exit
+fi
+
+file="$(readlink -f "$1")"
+cd "${file%/*}" || exit
+fzf --multi --reverse \
+ --header="Playlist: ${file##*/}" --header-first \
+ --bind 'enter:become(OPENFLAG=1 fpl {+})' \
+ --bind 'ctrl-o:execute(OPENFLAG=1 OPENWITH=mpv fpl {})' < "$file"
+
diff --git a/.local/bin/web/savesite b/.local/bin/web/savesite
new file mode 100755
index 0000000..206a633
--- /dev/null
+++ b/.local/bin/web/savesite
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+[ "$#" -lt 1 ] && { echo "savesite - save local copy of a website
+USAGE: savesite <URL> [DEST_DIR]"; exit 1; }
+
+url="$1"
+site="${2:-"$(echo "$url" | sed 's|\(https\?://\)\?\([A-Za-z0-9.-]*\)/.*|\2|')"}"
+WGETLOGS="${3:-.logs/$site.log}"
+started="$(date)"
+
+touch "$WGETLOGS" || exit
+printf ":: Downloading site: %s\n" "$site"
+printf ":: Logging to: %s\n" "$WGETLOGS"
+
+{
+ setsid wget \
+ --continue \
+ --recursive \
+ --no-clobber \
+ --page-requisites \
+ --html-extension \
+ --convert-links \
+ --restrict-file-names=windows \
+ --domains "$site" \
+ --no-parent \
+ --output-file "$WGETLOGS" \
+ "$url"
+
+ [ -n "$DISPLAY" ] && notify-send "savesite: finished downloading" "$site"
+ printf "%s\n" ":: Finished downloading site: $site" \
+ ":: Started at: $started" \
+ ":: Finished at: $(date)" >> "$WGETLOGS"
+} &
+
+tail -f "$WGETLOGS"
diff --git a/.local/bin/web/w3mman b/.local/bin/web/w3mman
new file mode 100755
index 0000000..5013fbd
--- /dev/null
+++ b/.local/bin/web/w3mman
@@ -0,0 +1,335 @@
+#!/bin/bash
+
+# w3m-man
+#
+# Use wget, w3m and less to download and view man pages.
+#
+# Homepage: https://github.com/sc0ttj/w3m-man
+#
+# Supports using $MANPAGER, $HTMLPAGER, $TERM_BROWSER, and
+# falls back to w3m and less if these are not set.
+#
+# How it works:
+#
+# - saves manpage from online sources to $HOME/.w3m-manpages/
+# - not proper man pages, just plain text output of websites
+# - prettifies them a bit (removes junk headers, links, messages)
+#
+# Usage:
+#
+# man <command> # view man page in plain text in $PAGER
+# man -H <command> # view man page as HTML in $BROWSER
+# man <command> --url # print the URL of the man page to STDOUT
+
+# TODO:
+#
+# - Display the path searched for manpages:
+#
+# man --path
+#
+# - Display the location of a manpage rather than the manpage itself:
+#
+# man -w command
+#
+# - Search for manpages containing a search string:
+#
+# man -k "search_string"
+#
+
+if [ "$1" = "--help" ];then
+
+ echo "# man (w3m-man)
+# Use wget, w3m and less to download and view man pages
+# See https://github.com/sc0ttj/w3m-man
+
+Usage:
+
+ man <command> # (download and) print the man page
+
+ man <command> --url # print the URL from which the man
+ # page was/would be downloaded
+
+ man --help # print this help info
+
+Where <command> is the command name you want to read about.
+
+Examples:
+
+ man diff # view 'diff' command (section 1)
+
+ man mount.8 # view 'mount' in section 8 (config stuff)
+
+ man 8 mount # same as above, but doesn't work with -H
+
+ man -H mount # view 'mount' man page as HTML using $BROWSER
+
+ man <command> --url # only print the URL from which the man page
+ # was/would be downloaded
+
+Man pages are divided into sections, as follows:
+
+ 1. User: most user commands and programs.
+
+ 2. System: calls by the Linux kernel.
+
+ 3. Library: documents provided by the standard C library.
+
+ 4. Devices: documents various devices, most of which reside in /dev.
+
+ 5. Files: describes various file formats and filesystems and proc(5).
+
+ 7. Overviews, conventions, and miscellaneous.
+
+ 8. Superuser and system administration commands.
+
+Checks the following URLs:
+
+the Ubuntu or Debian man pages, also:
+
+http://man.he.net/?topic=\${command}&section=\${section}
+http://manpages.org/\${command}/\${section}
+https://linux.die.net/man/\${section}/\${command}
+https://www.mankier.com/\${section}/\${command}
+https://man7.org/linux/man-pages/man\${section}/\${command}.\${section}.html
+http://manpages.org/\${command}
+http://man.he.net/?topic=\${command}&section=all
+https://ss64.com/bash/\${command}.html
+"
+ exit 0
+fi
+
+old_man="$(command -v man)"
+unset man
+
+command="$1"
+section="1"
+
+DISTRO_COMPAT_VERSION="latest"
+if [ -f /etc/DISTRO_SPECS ];then
+ source /etc/DISTRO_SPECS
+fi
+
+
+# support GNU man -H option (to view as HTML)
+if [ "$1" = "-H" ];then
+ command="$2"
+fi
+
+# support GNU man syntax `man 1 mount`
+re='^[1-8]+$'
+if [[ $1 =~ $re ]] ; then
+ command="${2}.$1"
+ section="$1"
+fi
+
+# support GNU man syntax `man mount.1`, `man mount.2`, etc
+section="${command//*\./}"
+command="${command//\.*/}"
+if [ "$command" = "$section" ];then
+ section=1
+fi
+
+manpage_file="$HOME/.w3m-manpages/$command.$section"
+
+# support env var $MANPAGER
+pager=${MANPAGER:-$PAGER}
+pager=${pager:-less -XR}
+w3m='w3m -o auto_image=false -o display_image=false'
+browser=${TERM_BROWSER:-$TERMBROWSER}
+browser=${browser:-$w3m}
+htmlpager=${HTMLPAGER:-w3m -dump}
+
+# Remove some junk from the plain text files generated by w3m,
+# such as headers, links to adverts, etc
+function prettifier {
+ url="$1"
+ case "$url" in
+
+ *'ubuntu.com'*|*'debian.org'*)
+ sed \
+ -e '1,5d' \
+ -e 's/ bug$//' \
+ -e 's/ / /g'
+ ;;
+
+ *'linux.die.net'*)
+ sed -e '1d' -e 's/\[INS::INS\]//g' -e 's/ \[ \]//g' \
+ -e 's/Site Search//g' 2>/dev/null | head -n -12
+ ;;
+
+ *mankier*)
+ grep -vEi ' • [A-Z]| □ [A-Z]' | sed -e '1,7d' -e 's/tldr.sh//g' \
+ -e "s/$command /$command($section) /g"
+ ;;
+
+ *ss64*com*)
+ sed '1,5d' 2>/dev/null
+ ;;
+
+ *'man7.org'*)
+ sed -e '1,4d' -e '8,13d' -e 's/ top/ /g' \
+ | grep -vE 'StatCounter' | head -n -15
+ ;;
+
+ *manpages*org*)
+ sed -e '1,3d' \
+ | head -n -14
+ ;;
+
+ *man*he*net*) cat - ;;
+
+ *) cat - ;;
+ esac
+}
+
+# create the config dir, if needed
+[ ! -d $HOME/.w3m-manpages ] && mkdir -p $HOME/.w3m-manpages
+
+# if we already have a proper man page, just print it and exit
+if [ ! -z "$MANPATH" ] && [ "$(which groff)" != "" ] && [ "$1" != "-H" ] && [ "$2" != "--url" ];then
+ usegroff=false
+ groff_file=''
+ zipped=false
+ paths=$(echo "${MANPATH}" | tr ':' '\n')
+ # for each path
+ for dir in ./ $paths
+ do
+ zipped=false
+ # let's find the man page file
+ groff_file=$dir/man${section}/${command}.${section}
+ # it might be gzipped
+ [ ! -f $groff_file ] && groff_file=$dir/man${section}/${command}.${section}.gz && zipped=true
+ # it might be in the current directory
+ [ -f ./${command}.${section} ] && groff_file="./${command}.${section}"
+ [ -f ./${command}.${section}.gz ] && groff_file="./${command}.${section}.gz" && zipped=true
+ # if we found the file
+ if [ -f $groff_file ];then
+ # unpack it, if needed
+ [ $zipped = true ] && zcat $groff_file > /tmp/unzipped && groff_file=/tmp/unzipped
+ # now lets read the man page and exit
+ groff -T utf8 -man $groff_file | $pager && exit 0
+ fi
+ done
+fi
+
+# if we already have the man page as plain text, just print it and exit
+[ "$1" != "-H" ] && [ "$2" != "--url" ] && [ -f "$manpage_file" ] && cat "$manpage_file" | $pager && exit 0
+
+# set a list of urls to check:
+
+# these man pages cover the correct versions of the program you have installed,
+# for the OS you're actually using (if using an Ubuntu or Debian based pup)
+if [ "$DISTRO_BINARY_COMPAT" = "ubuntu" ];then
+ URLS="https://manpages.ubuntu.com/manpages/${DISTRO_COMPAT_VERSION}/man${section}/${command}.${section}.html"
+elif [ "$DISTRO_BINARY_COMPAT" = "debian" ];then
+ URLS="https://manpages.debian.org/${DISTRO_COMPAT_VERSION}/${command}/${command}.${section}.en.html"
+fi
+
+# add the rest
+URLS="$URLS
+http://man.he.net/?topic=${command}&section=${section}
+http://manpages.org/${command}/${section}
+https://linux.die.net/man/${section}/${command}
+https://www.mankier.com/${section}/${command}
+https://man7.org/linux/man-pages/man${section}/${command}.${section}.html
+http://manpages.org/${command}
+http://man.he.net/?topic=${command}&section=all
+https://ss64.com/bash/${command}.html
+"
+# for each url in the list
+for url in ${URLS}
+do
+ # skip any empty urls
+ [ "$url" != "" ] || continue
+ [ "$url" != " " ] || continue
+
+ # crawl the url
+ wget --timeout=2 --spider -S -o /tmp/"$command".html "$url"
+
+ # get the status code
+ grep -m1 'HTTP/[1-3].[0-9] [0-9][0-9][0-9]' /tmp/"$command".html | grep -E '200 OK' > /tmp/response
+
+ # if HTTP status not 200, skip this url
+ grep -q -m1 "200" /tmp/response || continue
+
+ # print the URL if --url given
+ [ "$2" = "--url" ] && echo "$url" && exit 0
+
+ # grab the URL contents as plain text, put it into a file
+ timeout 2 $htmlpager "$url" | prettifier "$url" > "$manpage_file"
+
+ # if file is empty, remove it, skip this url
+ [ ! -s "$manpage_file" ] && rm "$manpage_file" && continue
+
+ # check if we if we got a "not found" page
+ notfound=false
+ grep -qiE "^Couldn|Hmmm|Invalid characters|No matches for \"|t found manual page under category" "$manpage_file" && notfound=true
+
+ # if we DID get a "not found" page, delete the man page, skip this url
+ [ "$notfound" = true ] && rm "$manpage_file" && continue
+
+ # if man page not a file, skip this url
+ [ ! -f "$manpage_file" ] && continue
+
+ # if -H was given, print it out as HTML (like GNU man)
+ if [ "$1" = "-H" ] ;then
+ $browser "$url"
+ fi
+
+ #
+ # add a footer to the man page
+ #
+ echo >> "$manpage_file"
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >> "$manpage_file"
+ echo >> "$manpage_file"
+ echo "Generated by https://github.com/sc0ttj/w3m-manpage" >> "$manpage_file"
+ echo >> "$manpage_file"
+ echo "Source URL $url" >> "$manpage_file"
+ echo >> "$manpage_file"
+
+ # man page created, dont need to do another url
+ break
+done
+
+# if we still did not _create_ a file, see if we have local
+# matching ones, in a different section
+if [ ! -f "$manpage_file" ];then
+ local_pages=$(ls $HOME/.w3m-manpages | grep "${command}.")
+ if [ "$local_pages" != "" ];then
+ if [ $(echo "$local_pages" | wc -l) = 1 ];then
+ echo
+ echo "Loading $local_pages" | tr -d '\n'
+ echo
+ sleep 2
+ manpage_file="$HOME/.w3m-manpages/$local_pages"
+ elif [ $(echo "$local_pages" | wc -l) -ge 2 ];then
+ echo
+ echo "Did you mean any of these?"
+ echo
+ echo "$local_pages"
+ exit 1
+ fi
+ fi
+fi
+
+# if we have a man page, and didnt already print the html, print it here
+[ "$1" != "-H" ] && [ -f "$manpage_file" ] \
+ && cat "$manpage_file" | $pager && exit 0
+
+# if _still_ nothing, try download it online from the next section
+if [ ! -f "$manpage_file" ];then
+ if [ -f /tmp/man_loopcount ] && [ $(wc -l /tmp/man_loopcount | cut -f1 -d' ') -ge 8 ];then
+ rm /tmp/man_loopcount
+ exit 1
+ fi
+ next_section=$(($section + 1))
+ [ $next_section -eq 9 ] && next_section=1
+ echo -n "."
+ echo "." >> /tmp/man_loopcount
+ exec $0 $next_section $command
+ retval=$?
+ [ $retval -eq 0 ] && rm /tmp/manprogress
+ echo
+fi
+
+man="$old_man"
diff --git a/.local/bin/web/ytf b/.local/bin/web/ytf
new file mode 100755
index 0000000..57b4af2
--- /dev/null
+++ b/.local/bin/web/ytf
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+case "$1" in
+ '') echo "ytf - download media using youtube config file\nUSAGE: ytf <FILE> [OPTION]..." >&2; exit 1 ;;
+ *.ytd) yt-dlp --config "$@" --config ~/.config/yt-dlp/videos.conf ;;
+ *.ytp) yt-dlp --config "$@" --config ~/.config/yt-dlp/playlist.conf ;;
+ *.ytps) yt-dlp --config "$@" --config ~/.config/yt-dlp/sequenced-playlist.conf ;;
+ *.ytc) yt-dlp --config "$@" --config ~/.config/yt-dlp/channel.conf ;;
+ *) echo "ytf: $1: config file not understood"; exit 1 ;;
+esac
diff --git a/.local/bin/web/ytplaylist b/.local/bin/web/ytplaylist
new file mode 100755
index 0000000..7bc9026
--- /dev/null
+++ b/.local/bin/web/ytplaylist
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Useful when creating a directory of videos sequenced as per a youtube
+# playlist.
+# Run this script from from the root of a directory that contains all the media
+# and metadata files.
+# The playlist file is expected to be in 'playlist' directory within the root
+# with .pl.txt extension. (playlist/PLAYLIST_NAME.pl.txt)
+# The new playlist directory will be created in the current directory i.e. the
+# root if no other destination is passed as the second argument.
+
+case "$1" in
+ '') echo "ytplaylist - build a directory of sequenced videos using a playlist file\n
+USAGE:\n\tytplaylist <PLAYLIST_FILE> [DESTINATION_DIR] " >&2; exit ;;
+ playlist/*.pl.txt) ;;
+ *)
+ printf "%s" "Unconventional file path, contniue? [y/N] "
+ read -r ans
+ case "$ans" in y) ;; *) exit 1 ;; esac
+ ;;
+esac
+
+playlist="$(readlink -f $1)"
+i=1
+fpl "$playlist" | while read -r file; do
+ if [ -z "$file" ]; then
+ i=$(( $i + 1 ))
+ continue
+ fi
+ dir="$(dirname "$file")"
+ base="$(basename "$file")"
+ rsync -Pru --mkpath "$file" \
+ "${2:-$(basename "${playlist%.pl.txt}")}/${dir#$(readlink -f "$PWD")}/$(printf "%02d" "$i") $base"
+done
diff --git a/.local/bin/web/ytv b/.local/bin/web/ytv
new file mode 100755
index 0000000..c6e9eec
--- /dev/null
+++ b/.local/bin/web/ytv
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+yt-dlp "$@" --config ~/.config/yt-dlp/videos.conf
diff --git a/.local/share/applications/browser.desktop b/.local/share/applications/browser.desktop
new file mode 100644
index 0000000..3435c13
--- /dev/null
+++ b/.local/share/applications/browser.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Application
+Name=Browser
+GenericName=Web Browser
+Icon=browser
+Exec=librewolf-open %u
+Actions=new-window;new-private-window;
+Categories=Network;WebBrowser;
+Keywords=Internet;WWW;Browser;Web;Explorer;
+StartupNotify=true
diff --git a/.local/share/applications/file.desktop b/.local/share/applications/file.desktop
new file mode 100644
index 0000000..369bdc0
--- /dev/null
+++ b/.local/share/applications/file.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=File Manager
+Exec=/usr/local/bin/st -e lf %u
diff --git a/.local/share/applications/img.desktop b/.local/share/applications/img.desktop
new file mode 100644
index 0000000..5783107
--- /dev/null
+++ b/.local/share/applications/img.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=Image viewer
+Exec=/usr/bin/nsxiv -a %f
diff --git a/.local/share/applications/mail.desktop b/.local/share/applications/mail.desktop
new file mode 100644
index 0000000..d24aea2
--- /dev/null
+++ b/.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/.local/share/applications/mimeapps.list b/.local/share/applications/mimeapps.list
new file mode 100644
index 0000000..5e5e662
--- /dev/null
+++ b/.local/share/applications/mimeapps.list
@@ -0,0 +1,25 @@
+[Default Applications]
+application/octet-stream=text.desktop
+application/pdf=pdf.desktop
+application/pdf=pdf.desktop
+application/x-gettext-translation=text.desktop
+application/xml=text.desktop
+application/x-wine-extension-ini=text.desktop
+image/gif=img.desktop
+image/gif=img.desktop
+image/jpeg=img.desktop
+image/png=img.desktop
+text/plain=text.desktop
+video/mp4=video.desktop
+video/ogg=video.desktop
+video/x-flv=video.desktop
+video/x-ms-wmv=video.desktop
+video/x-ogm+ogg=video.desktop
+video/x-theora+ogg=video.desktop
+inode/directory=file.desktop
+x-scheme-handler/http=browser.desktop
+x-scheme-handler/https=browser.desktop
+x-scheme-handler/etcher=balena-etcher-electron.desktop
+text/html=browser.desktop
+x-scheme-handler/about=browser.desktop
+x-scheme-handler/unknown=browser.desktop
diff --git a/.local/share/applications/mimeinfo.cache b/.local/share/applications/mimeinfo.cache
new file mode 100644
index 0000000..98f66ff
--- /dev/null
+++ b/.local/share/applications/mimeinfo.cache
@@ -0,0 +1,153 @@
+[MIME Cache]
+application/mxf=mpv.desktop;
+application/ogg=mpv.desktop;
+application/rdf+xml=offline-browser.desktop;torbrowser-open.desktop;
+application/rss+xml=offline-browser.desktop;torbrowser-open.desktop;
+application/sdp=mpv.desktop;
+application/smil=mpv.desktop;
+application/streamingmedia=mpv.desktop;
+application/vnd.apple.mpegurl=mpv.desktop;
+application/vnd.ms-asf=mpv.desktop;
+application/vnd.rn-realmedia=mpv.desktop;
+application/vnd.rn-realmedia-vbr=mpv.desktop;
+application/x-cue=mpv.desktop;
+application/x-extension-m4a=mpv.desktop;
+application/x-extension-mp4=mpv.desktop;
+application/x-matroska=mpv.desktop;
+application/x-mpegurl=mpv.desktop;
+application/x-ogg=mpv.desktop;
+application/x-ogm=mpv.desktop;
+application/x-ogm-audio=mpv.desktop;
+application/x-ogm-video=mpv.desktop;
+application/x-shellscript=nvim.desktop;
+application/x-shorten=mpv.desktop;
+application/x-smil=mpv.desktop;
+application/x-streamingmedia=mpv.desktop;
+application/x-xpinstall=offline-browser.desktop;torbrowser-open.desktop;
+application/xhtml+xml=offline-browser.desktop;torbrowser-open.desktop;
+application/xml=offline-browser.desktop;torbrowser-open.desktop;
+audio/3gpp=mpv.desktop;
+audio/3gpp2=mpv.desktop;
+audio/AMR=mpv.desktop;
+audio/aac=mpv.desktop;
+audio/ac3=mpv.desktop;
+audio/aiff=mpv.desktop;
+audio/amr-wb=mpv.desktop;
+audio/dv=mpv.desktop;
+audio/eac3=mpv.desktop;
+audio/flac=mpv.desktop;
+audio/m3u=mpv.desktop;
+audio/m4a=mpv.desktop;
+audio/mp1=mpv.desktop;
+audio/mp2=mpv.desktop;
+audio/mp3=mpv.desktop;
+audio/mp4=mpv.desktop;
+audio/mpeg=mpv.desktop;
+audio/mpeg2=mpv.desktop;
+audio/mpeg3=mpv.desktop;
+audio/mpegurl=mpv.desktop;
+audio/mpg=mpv.desktop;
+audio/musepack=mpv.desktop;
+audio/ogg=mpv.desktop;
+audio/opus=mpv.desktop;
+audio/rn-mpeg=mpv.desktop;
+audio/scpls=mpv.desktop;
+audio/vnd.dolby.heaac.1=mpv.desktop;
+audio/vnd.dolby.heaac.2=mpv.desktop;
+audio/vnd.dts=mpv.desktop;
+audio/vnd.dts.hd=mpv.desktop;
+audio/vnd.rn-realaudio=mpv.desktop;
+audio/vorbis=mpv.desktop;
+audio/wav=mpv.desktop;
+audio/webm=mpv.desktop;
+audio/x-aac=mpv.desktop;
+audio/x-adpcm=mpv.desktop;
+audio/x-aiff=mpv.desktop;
+audio/x-ape=mpv.desktop;
+audio/x-m4a=mpv.desktop;
+audio/x-matroska=mpv.desktop;
+audio/x-mp1=mpv.desktop;
+audio/x-mp2=mpv.desktop;
+audio/x-mp3=mpv.desktop;
+audio/x-mpegurl=mpv.desktop;
+audio/x-mpg=mpv.desktop;
+audio/x-ms-asf=mpv.desktop;
+audio/x-ms-wma=mpv.desktop;
+audio/x-musepack=mpv.desktop;
+audio/x-pls=mpv.desktop;
+audio/x-pn-au=mpv.desktop;
+audio/x-pn-realaudio=mpv.desktop;
+audio/x-pn-wav=mpv.desktop;
+audio/x-pn-windows-pcm=mpv.desktop;
+audio/x-realaudio=mpv.desktop;
+audio/x-scpls=mpv.desktop;
+audio/x-shorten=mpv.desktop;
+audio/x-tta=mpv.desktop;
+audio/x-vorbis=mpv.desktop;
+audio/x-vorbis+ogg=mpv.desktop;
+audio/x-wav=mpv.desktop;
+audio/x-wavpack=mpv.desktop;
+image/gif=offline-browser.desktop;torbrowser-open.desktop;
+image/jpeg=offline-browser.desktop;torbrowser-open.desktop;
+image/png=offline-browser.desktop;torbrowser-open.desktop;
+text/english=nvim.desktop;
+text/html=offline-browser.desktop;torbrowser-open.desktop;
+text/plain=nvim.desktop;
+text/x-c=nvim.desktop;
+text/x-c++=nvim.desktop;
+text/x-c++hdr=nvim.desktop;
+text/x-c++src=nvim.desktop;
+text/x-chdr=nvim.desktop;
+text/x-csrc=nvim.desktop;
+text/x-digital=digital-simulator.desktop;
+text/x-java=nvim.desktop;
+text/x-makefile=nvim.desktop;
+text/x-moc=nvim.desktop;
+text/x-pascal=nvim.desktop;
+text/x-tcl=nvim.desktop;
+text/x-tex=nvim.desktop;
+text/xml=offline-browser.desktop;torbrowser-open.desktop;
+video/3gp=mpv.desktop;
+video/3gpp=mpv.desktop;
+video/3gpp2=mpv.desktop;
+video/avi=mpv.desktop;
+video/divx=mpv.desktop;
+video/dv=mpv.desktop;
+video/fli=mpv.desktop;
+video/flv=mpv.desktop;
+video/mkv=mpv.desktop;
+video/mp2t=mpv.desktop;
+video/mp4=mpv.desktop;
+video/mp4v-es=mpv.desktop;
+video/mpeg=mpv.desktop;
+video/msvideo=mpv.desktop;
+video/ogg=mpv.desktop;
+video/quicktime=mpv.desktop;
+video/vnd.divx=mpv.desktop;
+video/vnd.mpegurl=mpv.desktop;
+video/vnd.rn-realvideo=mpv.desktop;
+video/webm=mpv.desktop;offline-browser.desktop;torbrowser-open.desktop;
+video/x-avi=mpv.desktop;
+video/x-flc=mpv.desktop;
+video/x-flic=mpv.desktop;
+video/x-flv=mpv.desktop;
+video/x-m4v=mpv.desktop;
+video/x-matroska=mpv.desktop;
+video/x-mpeg2=mpv.desktop;
+video/x-mpeg3=mpv.desktop;
+video/x-ms-afs=mpv.desktop;
+video/x-ms-asf=mpv.desktop;
+video/x-ms-wmv=mpv.desktop;
+video/x-ms-wmx=mpv.desktop;
+video/x-ms-wvxvideo=mpv.desktop;
+video/x-msvideo=mpv.desktop;
+video/x-ogm=mpv.desktop;
+video/x-ogm+ogg=mpv.desktop;
+video/x-theora=mpv.desktop;
+video/x-theora+ogg=mpv.desktop;
+x-scheme-handler/chrome=offline-browser.desktop;torbrowser-open.desktop;
+x-scheme-handler/etcher=appimagekit_1e61ab136866c084253c027d33a284e9-balenaEtcher.desktop;
+x-scheme-handler/ftp=offline-browser.desktop;torbrowser-open.desktop;
+x-scheme-handler/http=offline-browser.desktop;torbrowser-open.desktop;
+x-scheme-handler/https=offline-browser.desktop;torbrowser-open.desktop;
+x-scheme-handler/mailto=appimagekit_d9ccbe8820cf9667e998b3a64e89e45c-Tutanota_Desktop.desktop;
diff --git a/.local/share/applications/pdf.desktop b/.local/share/applications/pdf.desktop
new file mode 100644
index 0000000..8c38677
--- /dev/null
+++ b/.local/share/applications/pdf.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=PDF reader
+Exec=/usr/bin/zathura %u
diff --git a/.local/share/applications/rss.desktop b/.local/share/applications/rss.desktop
new file mode 100644
index 0000000..7180dcf
--- /dev/null
+++ b/.local/share/applications/rss.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Type=Application
+Name=RSS feed addition
+Exec=/usr/bin/env rssadd %U
+Icon=rssnow
diff --git a/.local/share/applications/text.desktop b/.local/share/applications/text.desktop
new file mode 100644
index 0000000..6ce6767
--- /dev/null
+++ b/.local/share/applications/text.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Type=Application
+Name=Text editor
+Exec=/usr/local/bin/st -e nvim %u
+Icon=text-editor
diff --git a/.local/share/applications/torrent.desktop b/.local/share/applications/torrent.desktop
new file mode 100644
index 0000000..313bca0
--- /dev/null
+++ b/.local/share/applications/torrent.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Type=Application
+Name=Torrent
+Exec=/usr/bin/env transadd %U
+Icon=torrents
diff --git a/.local/share/applications/video.desktop b/.local/share/applications/video.desktop
new file mode 100644
index 0000000..a29a0b1
--- /dev/null
+++ b/.local/share/applications/video.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Application
+Name=Video viewer
+Exec=/usr/bin/mpv -quiet %f
diff --git a/.local/share/chars/emoji b/.local/share/chars/emoji
new file mode 100644
index 0000000..40d7fc7
--- /dev/null
+++ b/.local/share/chars/emoji
@@ -0,0 +1,1630 @@
+😀 d83dde00; grinning face
+😃 d83dde03; grinning face with big eyes
+😄 d83dde04; grinning face with smiling eyes
+😁 d83dde01; beaming face with smiling eyes
+😆 d83dde06; grinning squinting face
+😅 d83dde05; grinning face with sweat
+🤣 d83edd23; rolling on the floor laughing
+😂 d83dde02; face with tears of joy
+🙂 d83dde42; slightly smiling face
+🙃 d83dde43; upside-down face
+🫠 d83edee0; melting face
+😉 d83dde09; winking face
+😊 d83dde0a; smiling face with smiling eyes
+😇 d83dde07; smiling face with halo
+🥰 d83edd70; smiling face with hearts
+😍 d83dde0d; smiling face with heart-eyes
+🤩 d83edd29; star-struck
+😘 d83dde18; face blowing a kiss
+😗 d83dde17; kissing face
+☺️ 263a fe0f; smiling face
+😚 d83dde1a; kissing face with closed eyes
+😙 d83dde19; kissing face with smiling eyes
+🥲 d83edd72; smiling face with tear
+😋 d83dde0b; face savoring food
+😛 d83dde1b; face with tongue
+😜 d83dde1c; winking face with tongue
+🤪 d83edd2a; zany face
+😝 d83dde1d; squinting face with tongue
+🤑 d83edd11; money-mouth face
+🤗 d83edd17; smiling face with open hands
+🤭 d83edd2d; face with hand over mouth
+🫢 d83edee2; face with open eyes and hand over mouth
+🫣 d83edee3; face with peeking eye
+🤫 d83edd2b; shushing face
+🤔 d83edd14; thinking face
+🫡 d83edee1; saluting face
+🤐 d83edd10; zipper-mouth face
+🤨 d83edd28; face with raised eyebrow
+😐 d83dde10; neutral face
+😑 d83dde11; expressionless face
+😶 d83dde36; face without mouth
+🫥 d83edee5; dotted line face
+😏 d83dde0f; smirking face
+😒 d83dde12; unamused face
+🙄 d83dde44; face with rolling eyes
+😬 d83dde2c; grimacing face
+🤥 d83edd25; lying face
+😌 d83dde0c; relieved face
+😔 d83dde14; pensive face
+😪 d83dde2a; sleepy face
+🤤 d83edd24; drooling face
+😴 d83dde34; sleeping face
+😷 d83dde37; face with medical mask
+🤒 d83edd12; face with thermometer
+🤕 d83edd15; face with head-bandage
+🤢 d83edd22; nauseated face
+🤮 d83edd2e; face vomiting
+🤧 d83edd27; sneezing face
+🥵 d83edd75; hot face
+🥶 d83edd76; cold face
+🥴 d83edd74; woozy face
+😵 d83dde35; face with crossed-out eyes
+🤯 d83edd2f; exploding head
+🤠 d83edd20; cowboy hat face
+🥳 d83edd73; partying face
+🥸 d83edd78; disguised face
+😎 d83dde0e; smiling face with sunglasses
+🤓 d83edd13; nerd face
+🧐 d83eddd0; face with monocle
+😕 d83dde15; confused face
+🫤 d83edee4; face with diagonal mouth
+😟 d83dde1f; worried face
+🙁 d83dde41; slightly frowning face
+☹️ 2639 fe0f; frowning face
+😮 d83dde2e; face with open mouth
+😯 d83dde2f; hushed face
+😲 d83dde32; astonished face
+😳 d83dde33; flushed face
+🥺 d83edd7a; pleading face
+🥹 d83edd79; face holding back tears
+😦 d83dde26; frowning face with open mouth
+😧 d83dde27; anguished face
+😨 d83dde28; fearful face
+😰 d83dde30; anxious face with sweat
+😥 d83dde25; sad but relieved face
+😢 d83dde22; crying face
+😭 d83dde2d; loudly crying face
+😱 d83dde31; face screaming in fear
+😖 d83dde16; confounded face
+😣 d83dde23; persevering face
+😞 d83dde1e; disappointed face
+😓 d83dde13; downcast face with sweat
+😩 d83dde29; weary face
+😫 d83dde2b; tired face
+🥱 d83edd71; yawning face
+😤 d83dde24; face with steam from nose
+😡 d83dde21; pouting face
+😠 d83dde20; angry face
+🤬 d83edd2c; face with symbols on mouth
+😈 d83dde08; smiling face with horns
+👿 d83ddc7f; angry face with horns
+💀 d83ddc80; skull
+☠️ 2620 fe0f; skull and crossbones
+💩 d83ddca9; pile of poo
+🤡 d83edd21; clown face
+👹 d83ddc79; ogre
+👺 d83ddc7a; goblin
+👻 d83ddc7b; ghost
+👽 d83ddc7d; alien
+👾 d83ddc7e; alien monster
+🤖 d83edd16; robot
+😺 d83dde3a; grinning cat
+😸 d83dde38; grinning cat with smiling eyes
+😹 d83dde39; cat with tears of joy
+😻 d83dde3b; smiling cat with heart-eyes
+😼 d83dde3c; cat with wry smile
+😽 d83dde3d; kissing cat
+🙀 d83dde40; weary cat
+😿 d83dde3f; crying cat
+😾 d83dde3e; pouting cat
+🙈 d83dde48; see-no-evil monkey
+🙉 d83dde49; hear-no-evil monkey
+🙊 d83dde4a; speak-no-evil monkey
+💋 d83ddc8b; kiss mark
+💌 d83ddc8c; love letter
+💘 d83ddc98; heart with arrow
+💝 d83ddc9d; heart with ribbon
+💖 d83ddc96; sparkling heart
+💗 d83ddc97; growing heart
+💓 d83ddc93; beating heart
+💞 d83ddc9e; revolving hearts
+💕 d83ddc95; two hearts
+💟 d83ddc9f; heart decoration
+❣️ 2763 fe0f; heart exclamation
+💔 d83ddc94; broken heart
+❤️ 2764 fe0f; red heart
+🧡 d83edde1; orange heart
+💛 d83ddc9b; yellow heart
+💚 d83ddc9a; green heart
+💙 d83ddc99; blue heart
+💜 d83ddc9c; purple heart
+🤎 d83edd0e; brown heart
+🖤 d83ddda4; black heart
+🤍 d83edd0d; white heart
+💯 d83ddcaf; hundred points
+💢 d83ddca2; anger symbol
+💥 d83ddca5; collision
+💫 d83ddcab; dizzy
+💦 d83ddca6; sweat droplets
+💨 d83ddca8; dashing away
+🕳️ d83ddd73 fe0f; hole
+💣 d83ddca3; bomb
+💬 d83ddcac; speech balloon
+🗨️ d83ddde8 fe0f; left speech bubble
+🗯️ d83dddef fe0f; right anger bubble
+💭 d83ddcad; thought balloon
+💤 d83ddca4; zzz
+👋 d83ddc4b; waving hand
+🤚 d83edd1a; raised back of hand
+🖐️ d83ddd90 fe0f; hand with fingers splayed
+✋ 270b; raised hand
+🖖 d83ddd96; vulcan salute
+🫱 d83edef1; rightwards hand
+🫲 d83edef2; leftwards hand
+🫳 d83edef3; palm down hand
+🫴 d83edef4; palm up hand
+👌 d83ddc4c; OK hand
+🤌 d83edd0c; pinched fingers
+🤏 d83edd0f; pinching hand
+✌️ 270c fe0f; victory hand
+🤞 d83edd1e; crossed fingers
+🫰 d83edef0; hand with index finger and thumb crossed
+🤟 d83edd1f; love-you gesture
+🤘 d83edd18; sign of the horns
+🤙 d83edd19; call me hand
+👈 d83ddc48; backhand index pointing left
+👉 d83ddc49; backhand index pointing right
+👆 d83ddc46; backhand index pointing up
+🖕 d83ddd95; middle finger
+👇 d83ddc47; backhand index pointing down
+☝️ 261d fe0f; index pointing up
+🫵 d83edef5; index pointing at the viewer
+👍 d83ddc4d; thumbs up
+👎 d83ddc4e; thumbs down
+✊ 270a; raised fist
+👊 d83ddc4a; oncoming fist
+🤛 d83edd1b; left-facing fist
+🤜 d83edd1c; right-facing fist
+👏 d83ddc4f; clapping hands
+🙌 d83dde4c; raising hands
+🫶 d83edef6; heart hands
+👐 d83ddc50; open hands
+🤲 d83edd32; palms up together
+🤝 d83edd1d; handshake
+🙏 d83dde4f; folded hands
+✍️ 270d fe0f; writing hand
+💅 d83ddc85; nail polish
+🤳 d83edd33; selfie
+💪 d83ddcaa; flexed biceps
+🦾 d83eddbe; mechanical arm
+🦿 d83eddbf; mechanical leg
+🦵 d83eddb5; leg
+🦶 d83eddb6; foot
+👂 d83ddc42; ear
+🦻 d83eddbb; ear with hearing aid
+👃 d83ddc43; nose
+🧠 d83edde0; brain
+🫀 d83edec0; anatomical heart
+🫁 d83edec1; lungs
+🦷 d83eddb7; tooth
+🦴 d83eddb4; bone
+👀 d83ddc40; eyes
+👁️ d83ddc41 fe0f; eye
+👅 d83ddc45; tongue
+👄 d83ddc44; mouth
+🫦 d83edee6; biting lip
+👶 d83ddc76; baby
+🧒 d83eddd2; child
+👦 d83ddc66; boy
+👧 d83ddc67; girl
+🧑 d83eddd1; person
+👱 d83ddc71; person: blond hair
+👨 d83ddc68; man
+🧔 d83eddd4; person: beard
+👩 d83ddc69; woman
+🧓 d83eddd3; older person
+👴 d83ddc74; old man
+👵 d83ddc75; old woman
+🙍 d83dde4d; person frowning
+🙎 d83dde4e; person pouting
+🙅 d83dde45; person gesturing NO
+🙆 d83dde46; person gesturing OK
+💁 d83ddc81; person tipping hand
+🙋 d83dde4b; person raising hand
+🧏 d83eddcf; deaf person
+🙇 d83dde47; person bowing
+🤦 d83edd26; person facepalming
+🤷 d83edd37; person shrugging
+👮 d83ddc6e; police officer
+🕵️ d83ddd75 fe0f; detective
+💂 d83ddc82; guard
+🥷 d83edd77; ninja
+👷 d83ddc77; construction worker
+🫅 d83edec5; person with crown
+🤴 d83edd34; prince
+👸 d83ddc78; princess
+👳 d83ddc73; person wearing turban
+👲 d83ddc72; person with skullcap
+🧕 d83eddd5; woman with headscarf
+🤵 d83edd35; person in tuxedo
+👰 d83ddc70; person with veil
+🤰 d83edd30; pregnant woman
+🫃 d83edec3; pregnant man
+🫄 d83edec4; pregnant person
+🤱 d83edd31; breast-feeding
+👼 d83ddc7c; baby angel
+🎅 d83cdf85; Santa Claus
+🤶 d83edd36; Mrs. Claus
+🦸 d83eddb8; superhero
+🦹 d83eddb9; supervillain
+🧙 d83eddd9; mage
+🧚 d83eddda; fairy
+🧛 d83edddb; vampire
+🧜 d83edddc; merperson
+🧝 d83edddd; elf
+🧞 d83eddde; genie
+🧟 d83edddf; zombie
+🧌 d83eddcc; troll
+💆 d83ddc86; person getting massage
+💇 d83ddc87; person getting haircut
+🚶 d83ddeb6; person walking
+🧍 d83eddcd; person standing
+🧎 d83eddce; person kneeling
+🏃 d83cdfc3; person running
+💃 d83ddc83; woman dancing
+🕺 d83ddd7a; man dancing
+🕴️ d83ddd74 fe0f; person in suit levitating
+👯 d83ddc6f; people with bunny ears
+🧖 d83eddd6; person in steamy room
+🧗 d83eddd7; person climbing
+🤺 d83edd3a; person fencing
+🏇 d83cdfc7; horse racing
+⛷️ 26f7 fe0f; skier
+🏂 d83cdfc2; snowboarder
+🏌️ d83cdfcc fe0f; person golfing
+🏄 d83cdfc4; person surfing
+🚣 d83ddea3; person rowing boat
+🏊 d83cdfca; person swimming
+⛹️ 26f9 fe0f; person bouncing ball
+🏋️ d83cdfcb fe0f; person lifting weights
+🚴 d83ddeb4; person biking
+🚵 d83ddeb5; person mountain biking
+🤸 d83edd38; person cartwheeling
+🤼 d83edd3c; people wrestling
+🤽 d83edd3d; person playing water polo
+🤾 d83edd3e; person playing handball
+🤹 d83edd39; person juggling
+🧘 d83eddd8; person in lotus position
+🛀 d83ddec0; person taking bath
+🛌 d83ddecc; person in bed
+👭 d83ddc6d; women holding hands
+👫 d83ddc6b; woman and man holding hands
+👬 d83ddc6c; men holding hands
+💏 d83ddc8f; kiss
+💑 d83ddc91; couple with heart
+👪 d83ddc6a; family
+🗣️ d83ddde3 fe0f; speaking head
+👤 d83ddc64; bust in silhouette
+👥 d83ddc65; busts in silhouette
+🫂 d83edec2; people hugging
+👣 d83ddc63; footprints
+🐵 d83ddc35; monkey face
+🐒 d83ddc12; monkey
+🦍 d83edd8d; gorilla
+🦧 d83edda7; orangutan
+🐶 d83ddc36; dog face
+🐕 d83ddc15; dog
+🦮 d83eddae; guide dog
+🐩 d83ddc29; poodle
+🐺 d83ddc3a; wolf
+🦊 d83edd8a; fox
+🦝 d83edd9d; raccoon
+🐱 d83ddc31; cat face
+🐈 d83ddc08; cat
+🦁 d83edd81; lion
+🐯 d83ddc2f; tiger face
+🐅 d83ddc05; tiger
+🐆 d83ddc06; leopard
+🐴 d83ddc34; horse face
+🐎 d83ddc0e; horse
+🦄 d83edd84; unicorn
+🦓 d83edd93; zebra
+🦌 d83edd8c; deer
+🦬 d83eddac; bison
+🐮 d83ddc2e; cow face
+🐂 d83ddc02; ox
+🐃 d83ddc03; water buffalo
+🐄 d83ddc04; cow
+🐷 d83ddc37; pig face
+🐖 d83ddc16; pig
+🐗 d83ddc17; boar
+🐽 d83ddc3d; pig nose
+🐏 d83ddc0f; ram
+🐑 d83ddc11; ewe
+🐐 d83ddc10; goat
+🐪 d83ddc2a; camel
+🐫 d83ddc2b; two-hump camel
+🦙 d83edd99; llama
+🦒 d83edd92; giraffe
+🐘 d83ddc18; elephant
+🦣 d83edda3; mammoth
+🦏 d83edd8f; rhinoceros
+🦛 d83edd9b; hippopotamus
+🐭 d83ddc2d; mouse face
+🐁 d83ddc01; mouse
+🐀 d83ddc00; rat
+🐹 d83ddc39; hamster
+🐰 d83ddc30; rabbit face
+🐇 d83ddc07; rabbit
+🐿️ d83ddc3f fe0f; chipmunk
+🦫 d83eddab; beaver
+🦔 d83edd94; hedgehog
+🦇 d83edd87; bat
+🐻 d83ddc3b; bear
+🐨 d83ddc28; koala
+🐼 d83ddc3c; panda
+🦥 d83edda5; sloth
+🦦 d83edda6; otter
+🦨 d83edda8; skunk
+🦘 d83edd98; kangaroo
+🦡 d83edda1; badger
+🐾 d83ddc3e; paw prints
+🦃 d83edd83; turkey
+🐔 d83ddc14; chicken
+🐓 d83ddc13; rooster
+🐣 d83ddc23; hatching chick
+🐤 d83ddc24; baby chick
+🐥 d83ddc25; front-facing baby chick
+🐦 d83ddc26; bird
+🐧 d83ddc27; penguin
+🕊️ d83ddd4a fe0f; dove
+🦅 d83edd85; eagle
+🦆 d83edd86; duck
+🦢 d83edda2; swan
+🦉 d83edd89; owl
+🦤 d83edda4; dodo
+🪶 d83edeb6; feather
+🦩 d83edda9; flamingo
+🦚 d83edd9a; peacock
+🦜 d83edd9c; parrot
+🐸 d83ddc38; frog
+🐊 d83ddc0a; crocodile
+🐢 d83ddc22; turtle
+🦎 d83edd8e; lizard
+🐍 d83ddc0d; snake
+🐲 d83ddc32; dragon face
+🐉 d83ddc09; dragon
+🦕 d83edd95; sauropod
+🦖 d83edd96; T-Rex
+🐳 d83ddc33; spouting whale
+🐋 d83ddc0b; whale
+🐬 d83ddc2c; dolphin
+🦭 d83eddad; seal
+🐟 d83ddc1f; fish
+🐠 d83ddc20; tropical fish
+🐡 d83ddc21; blowfish
+🦈 d83edd88; shark
+🐙 d83ddc19; octopus
+🐚 d83ddc1a; spiral shell
+🪸 d83edeb8; coral
+🐌 d83ddc0c; snail
+🦋 d83edd8b; butterfly
+🐛 d83ddc1b; bug
+🐜 d83ddc1c; ant
+🐝 d83ddc1d; honeybee
+🪲 d83edeb2; beetle
+🐞 d83ddc1e; lady beetle
+🦗 d83edd97; cricket
+🪳 d83edeb3; cockroach
+🕷️ d83ddd77 fe0f; spider
+🕸️ d83ddd78 fe0f; spider web
+🦂 d83edd82; scorpion
+🦟 d83edd9f; mosquito
+🪰 d83edeb0; fly
+🪱 d83edeb1; worm
+🦠 d83edda0; microbe
+💐 d83ddc90; bouquet
+🌸 d83cdf38; cherry blossom
+💮 d83ddcae; white flower
+🪷 d83edeb7; lotus
+🏵️ d83cdff5 fe0f; rosette
+🌹 d83cdf39; rose
+🥀 d83edd40; wilted flower
+🌺 d83cdf3a; hibiscus
+🌻 d83cdf3b; sunflower
+🌼 d83cdf3c; blossom
+🌷 d83cdf37; tulip
+🌱 d83cdf31; seedling
+🪴 d83edeb4; potted plant
+🌲 d83cdf32; evergreen tree
+🌳 d83cdf33; deciduous tree
+🌴 d83cdf34; palm tree
+🌵 d83cdf35; cactus
+🌾 d83cdf3e; sheaf of rice
+🌿 d83cdf3f; herb
+☘️ 2618 fe0f; shamrock
+🍀 d83cdf40; four leaf clover
+🍁 d83cdf41; maple leaf
+🍂 d83cdf42; fallen leaf
+🍃 d83cdf43; leaf fluttering in wind
+🪹 d83edeb9; empty nest
+🪺 d83edeba; nest with eggs
+🍇 d83cdf47; grapes
+🍈 d83cdf48; melon
+🍉 d83cdf49; watermelon
+🍊 d83cdf4a; tangerine
+🍋 d83cdf4b; lemon
+🍌 d83cdf4c; banana
+🍍 d83cdf4d; pineapple
+🥭 d83edd6d; mango
+🍎 d83cdf4e; red apple
+🍏 d83cdf4f; green apple
+🍐 d83cdf50; pear
+🍑 d83cdf51; peach
+🍒 d83cdf52; cherries
+🍓 d83cdf53; strawberry
+🫐 d83eded0; blueberries
+🥝 d83edd5d; kiwi fruit
+🍅 d83cdf45; tomato
+🫒 d83eded2; olive
+🥥 d83edd65; coconut
+🥑 d83edd51; avocado
+🍆 d83cdf46; eggplant
+🥔 d83edd54; potato
+🥕 d83edd55; carrot
+🌽 d83cdf3d; ear of corn
+🌶️ d83cdf36 fe0f; hot pepper
+🫑 d83eded1; bell pepper
+🥒 d83edd52; cucumber
+🥬 d83edd6c; leafy green
+🥦 d83edd66; broccoli
+🧄 d83eddc4; garlic
+🧅 d83eddc5; onion
+🍄 d83cdf44; mushroom
+🥜 d83edd5c; peanuts
+🫘 d83eded8; beans
+🌰 d83cdf30; chestnut
+🍞 d83cdf5e; bread
+🥐 d83edd50; croissant
+🥖 d83edd56; baguette bread
+🫓 d83eded3; flatbread
+🥨 d83edd68; pretzel
+🥯 d83edd6f; bagel
+🥞 d83edd5e; pancakes
+🧇 d83eddc7; waffle
+🧀 d83eddc0; cheese wedge
+🍖 d83cdf56; meat on bone
+🍗 d83cdf57; poultry leg
+🥩 d83edd69; cut of meat
+🥓 d83edd53; bacon
+🍔 d83cdf54; hamburger
+🍟 d83cdf5f; french fries
+🍕 d83cdf55; pizza
+🌭 d83cdf2d; hot dog
+🥪 d83edd6a; sandwich
+🌮 d83cdf2e; taco
+🌯 d83cdf2f; burrito
+🫔 d83eded4; tamale
+🥙 d83edd59; stuffed flatbread
+🧆 d83eddc6; falafel
+🥚 d83edd5a; egg
+🍳 d83cdf73; cooking
+🥘 d83edd58; shallow pan of food
+🍲 d83cdf72; pot of food
+🫕 d83eded5; fondue
+🥣 d83edd63; bowl with spoon
+🥗 d83edd57; green salad
+🍿 d83cdf7f; popcorn
+🧈 d83eddc8; butter
+🧂 d83eddc2; salt
+🥫 d83edd6b; canned food
+🍱 d83cdf71; bento box
+🍘 d83cdf58; rice cracker
+🍙 d83cdf59; rice ball
+🍚 d83cdf5a; cooked rice
+🍛 d83cdf5b; curry rice
+🍜 d83cdf5c; steaming bowl
+🍝 d83cdf5d; spaghetti
+🍠 d83cdf60; roasted sweet potato
+🍢 d83cdf62; oden
+🍣 d83cdf63; sushi
+🍤 d83cdf64; fried shrimp
+🍥 d83cdf65; fish cake with swirl
+🥮 d83edd6e; moon cake
+🍡 d83cdf61; dango
+🥟 d83edd5f; dumpling
+🥠 d83edd60; fortune cookie
+🥡 d83edd61; takeout box
+🦀 d83edd80; crab
+🦞 d83edd9e; lobster
+🦐 d83edd90; shrimp
+🦑 d83edd91; squid
+🦪 d83eddaa; oyster
+🍦 d83cdf66; soft ice cream
+🍧 d83cdf67; shaved ice
+🍨 d83cdf68; ice cream
+🍩 d83cdf69; doughnut
+🍪 d83cdf6a; cookie
+🎂 d83cdf82; birthday cake
+🍰 d83cdf70; shortcake
+🧁 d83eddc1; cupcake
+🥧 d83edd67; pie
+🍫 d83cdf6b; chocolate bar
+🍬 d83cdf6c; candy
+🍭 d83cdf6d; lollipop
+🍮 d83cdf6e; custard
+🍯 d83cdf6f; honey pot
+🍼 d83cdf7c; baby bottle
+🥛 d83edd5b; glass of milk
+☕ 2615; hot beverage
+🫖 d83eded6; teapot
+🍵 d83cdf75; teacup without handle
+🍶 d83cdf76; sake
+🍾 d83cdf7e; bottle with popping cork
+🍷 d83cdf77; wine glass
+🍸 d83cdf78; cocktail glass
+🍹 d83cdf79; tropical drink
+🍺 d83cdf7a; beer mug
+🍻 d83cdf7b; clinking beer mugs
+🥂 d83edd42; clinking glasses
+🥃 d83edd43; tumbler glass
+🫗 d83eded7; pouring liquid
+🥤 d83edd64; cup with straw
+🧋 d83eddcb; bubble tea
+🧃 d83eddc3; beverage box
+🧉 d83eddc9; mate
+🧊 d83eddca; ice
+🥢 d83edd62; chopsticks
+🍽️ d83cdf7d fe0f; fork and knife with plate
+🍴 d83cdf74; fork and knife
+🥄 d83edd44; spoon
+🔪 d83ddd2a; kitchen knife
+🫙 d83eded9; jar
+🏺 d83cdffa; amphora
+🌍 d83cdf0d; globe showing Europe-Africa
+🌎 d83cdf0e; globe showing Americas
+🌏 d83cdf0f; globe showing Asia-Australia
+🌐 d83cdf10; globe with meridians
+🗺️ d83dddfa fe0f; world map
+🗾 d83dddfe; map of Japan
+🧭 d83edded; compass
+🏔️ d83cdfd4 fe0f; snow-capped mountain
+⛰️ 26f0 fe0f; mountain
+🌋 d83cdf0b; volcano
+🗻 d83dddfb; mount fuji
+🏕️ d83cdfd5 fe0f; camping
+🏖️ d83cdfd6 fe0f; beach with umbrella
+🏜️ d83cdfdc fe0f; desert
+🏝️ d83cdfdd fe0f; desert island
+🏞️ d83cdfde fe0f; national park
+🏟️ d83cdfdf fe0f; stadium
+🏛️ d83cdfdb fe0f; classical building
+🏗️ d83cdfd7 fe0f; building construction
+🧱 d83eddf1; brick
+🪨 d83edea8; rock
+🪵 d83edeb5; wood
+🛖 d83dded6; hut
+🏘️ d83cdfd8 fe0f; houses
+🏚️ d83cdfda fe0f; derelict house
+🏠 d83cdfe0; house
+🏡 d83cdfe1; house with garden
+🏢 d83cdfe2; office building
+🏣 d83cdfe3; Japanese post office
+🏤 d83cdfe4; post office
+🏥 d83cdfe5; hospital
+🏦 d83cdfe6; bank
+🏨 d83cdfe8; hotel
+🏩 d83cdfe9; love hotel
+🏪 d83cdfea; convenience store
+🏫 d83cdfeb; school
+🏬 d83cdfec; department store
+🏭 d83cdfed; factory
+🏯 d83cdfef; Japanese castle
+🏰 d83cdff0; castle
+💒 d83ddc92; wedding
+🗼 d83dddfc; Tokyo tower
+🗽 d83dddfd; Statue of Liberty
+⛪ 26ea; church
+🕌 d83ddd4c; mosque
+🛕 d83dded5; hindu temple
+🕍 d83ddd4d; synagogue
+⛩️ 26e9 fe0f; shinto shrine
+🕋 d83ddd4b; kaaba
+⛲ 26f2; fountain
+⛺ 26fa; tent
+🌁 d83cdf01; foggy
+🌃 d83cdf03; night with stars
+🏙️ d83cdfd9 fe0f; cityscape
+🌄 d83cdf04; sunrise over mountains
+🌅 d83cdf05; sunrise
+🌆 d83cdf06; cityscape at dusk
+🌇 d83cdf07; sunset
+🌉 d83cdf09; bridge at night
+♨️ 2668 fe0f; hot springs
+🎠 d83cdfa0; carousel horse
+🛝 d83ddedd; playground slide
+🎡 d83cdfa1; ferris wheel
+🎢 d83cdfa2; roller coaster
+💈 d83ddc88; barber pole
+🎪 d83cdfaa; circus tent
+🚂 d83dde82; locomotive
+🚃 d83dde83; railway car
+🚄 d83dde84; high-speed train
+🚅 d83dde85; bullet train
+🚆 d83dde86; train
+🚇 d83dde87; metro
+🚈 d83dde88; light rail
+🚉 d83dde89; station
+🚊 d83dde8a; tram
+🚝 d83dde9d; monorail
+🚞 d83dde9e; mountain railway
+🚋 d83dde8b; tram car
+🚌 d83dde8c; bus
+🚍 d83dde8d; oncoming bus
+🚎 d83dde8e; trolleybus
+🚐 d83dde90; minibus
+🚑 d83dde91; ambulance
+🚒 d83dde92; fire engine
+🚓 d83dde93; police car
+🚔 d83dde94; oncoming police car
+🚕 d83dde95; taxi
+🚖 d83dde96; oncoming taxi
+🚗 d83dde97; automobile
+🚘 d83dde98; oncoming automobile
+🚙 d83dde99; sport utility vehicle
+🛻 d83ddefb; pickup truck
+🚚 d83dde9a; delivery truck
+🚛 d83dde9b; articulated lorry
+🚜 d83dde9c; tractor
+🏎️ d83cdfce fe0f; racing car
+🏍️ d83cdfcd fe0f; motorcycle
+🛵 d83ddef5; motor scooter
+🦽 d83eddbd; manual wheelchair
+🦼 d83eddbc; motorized wheelchair
+🛺 d83ddefa; auto rickshaw
+🚲 d83ddeb2; bicycle
+🛴 d83ddef4; kick scooter
+🛹 d83ddef9; skateboard
+🛼 d83ddefc; roller skate
+🚏 d83dde8f; bus stop
+🛣️ d83ddee3 fe0f; motorway
+🛤️ d83ddee4 fe0f; railway track
+🛢️ d83ddee2 fe0f; oil drum
+⛽ 26fd; fuel pump
+🛞 d83ddede; wheel
+🚨 d83ddea8; police car light
+🚥 d83ddea5; horizontal traffic light
+🚦 d83ddea6; vertical traffic light
+🛑 d83dded1; stop sign
+🚧 d83ddea7; construction
+⚓ 2693; anchor
+🛟 d83ddedf; ring buoy
+⛵ 26f5; sailboat
+🛶 d83ddef6; canoe
+🚤 d83ddea4; speedboat
+🛳️ d83ddef3 fe0f; passenger ship
+⛴️ 26f4 fe0f; ferry
+🛥️ d83ddee5 fe0f; motor boat
+🚢 d83ddea2; ship
+✈️ 2708 fe0f; airplane
+🛩️ d83ddee9 fe0f; small airplane
+🛫 d83ddeeb; airplane departure
+🛬 d83ddeec; airplane arrival
+🪂 d83ede82; parachute
+💺 d83ddcba; seat
+🚁 d83dde81; helicopter
+🚟 d83dde9f; suspension railway
+🚠 d83ddea0; mountain cableway
+🚡 d83ddea1; aerial tramway
+🛰️ d83ddef0 fe0f; satellite
+🚀 d83dde80; rocket
+🛸 d83ddef8; flying saucer
+🛎️ d83ddece fe0f; bellhop bell
+🧳 d83eddf3; luggage
+⌛ 231b; hourglass done
+⏳ 23f3; hourglass not done
+⌚ 231a; watch
+⏰ 23f0; alarm clock
+⏱️ 23f1 fe0f; stopwatch
+⏲️ 23f2 fe0f; timer clock
+🕰️ d83ddd70 fe0f; mantelpiece clock
+🕛 d83ddd5b; twelve o’clock
+🕧 d83ddd67; twelve-thirty
+🕐 d83ddd50; one o’clock
+🕜 d83ddd5c; one-thirty
+🕑 d83ddd51; two o’clock
+🕝 d83ddd5d; two-thirty
+🕒 d83ddd52; three o’clock
+🕞 d83ddd5e; three-thirty
+🕓 d83ddd53; four o’clock
+🕟 d83ddd5f; four-thirty
+🕔 d83ddd54; five o’clock
+🕠 d83ddd60; five-thirty
+🕕 d83ddd55; six o’clock
+🕡 d83ddd61; six-thirty
+🕖 d83ddd56; seven o’clock
+🕢 d83ddd62; seven-thirty
+🕗 d83ddd57; eight o’clock
+🕣 d83ddd63; eight-thirty
+🕘 d83ddd58; nine o’clock
+🕤 d83ddd64; nine-thirty
+🕙 d83ddd59; ten o’clock
+🕥 d83ddd65; ten-thirty
+🕚 d83ddd5a; eleven o’clock
+🕦 d83ddd66; eleven-thirty
+🌑 d83cdf11; new moon
+🌒 d83cdf12; waxing crescent moon
+🌓 d83cdf13; first quarter moon
+🌔 d83cdf14; waxing gibbous moon
+🌕 d83cdf15; full moon
+🌖 d83cdf16; waning gibbous moon
+🌗 d83cdf17; last quarter moon
+🌘 d83cdf18; waning crescent moon
+🌙 d83cdf19; crescent moon
+🌚 d83cdf1a; new moon face
+🌛 d83cdf1b; first quarter moon face
+🌜 d83cdf1c; last quarter moon face
+🌡️ d83cdf21 fe0f; thermometer
+☀️ 2600 fe0f; sun
+🌝 d83cdf1d; full moon face
+🌞 d83cdf1e; sun with face
+🪐 d83ede90; ringed planet
+⭐ 2b50; star
+🌟 d83cdf1f; glowing star
+🌠 d83cdf20; shooting star
+🌌 d83cdf0c; milky way
+☁️ 2601 fe0f; cloud
+⛅ 26c5; sun behind cloud
+⛈️ 26c8 fe0f; cloud with lightning and rain
+🌤️ d83cdf24 fe0f; sun behind small cloud
+🌥️ d83cdf25 fe0f; sun behind large cloud
+🌦️ d83cdf26 fe0f; sun behind rain cloud
+🌧️ d83cdf27 fe0f; cloud with rain
+🌨️ d83cdf28 fe0f; cloud with snow
+🌩️ d83cdf29 fe0f; cloud with lightning
+🌪️ d83cdf2a fe0f; tornado
+🌫️ d83cdf2b fe0f; fog
+🌬️ d83cdf2c fe0f; wind face
+🌀 d83cdf00; cyclone
+🌈 d83cdf08; rainbow
+🌂 d83cdf02; closed umbrella
+☂️ 2602 fe0f; umbrella
+☔ 2614; umbrella with rain drops
+⛱️ 26f1 fe0f; umbrella on ground
+⚡ 26a1; high voltage
+❄️ 2744 fe0f; snowflake
+☃️ 2603 fe0f; snowman
+⛄ 26c4; snowman without snow
+☄️ 2604 fe0f; comet
+🔥 d83ddd25; fire
+💧 d83ddca7; droplet
+🌊 d83cdf0a; water wave
+🎃 d83cdf83; jack-o-lantern
+🎄 d83cdf84; Christmas tree
+🎆 d83cdf86; fireworks
+🎇 d83cdf87; sparkler
+🧨 d83edde8; firecracker
+✨ 2728; sparkles
+🎈 d83cdf88; balloon
+🎉 d83cdf89; party popper
+🎊 d83cdf8a; confetti ball
+🎋 d83cdf8b; tanabata tree
+🎍 d83cdf8d; pine decoration
+🎎 d83cdf8e; Japanese dolls
+🎏 d83cdf8f; carp streamer
+🎐 d83cdf90; wind chime
+🎑 d83cdf91; moon viewing ceremony
+🧧 d83edde7; red envelope
+🎀 d83cdf80; ribbon
+🎁 d83cdf81; wrapped gift
+🎗️ d83cdf97 fe0f; reminder ribbon
+🎟️ d83cdf9f fe0f; admission tickets
+🎫 d83cdfab; ticket
+🎖️ d83cdf96 fe0f; military medal
+🏆 d83cdfc6; trophy
+🏅 d83cdfc5; sports medal
+🥇 d83edd47; 1st place medal
+🥈 d83edd48; 2nd place medal
+🥉 d83edd49; 3rd place medal
+⚽ 26bd; soccer ball
+⚾ 26be; baseball
+🥎 d83edd4e; softball
+🏀 d83cdfc0; basketball
+🏐 d83cdfd0; volleyball
+🏈 d83cdfc8; american football
+🏉 d83cdfc9; rugby football
+🎾 d83cdfbe; tennis
+🥏 d83edd4f; flying disc
+🎳 d83cdfb3; bowling
+🏏 d83cdfcf; cricket game
+🏑 d83cdfd1; field hockey
+🏒 d83cdfd2; ice hockey
+🥍 d83edd4d; lacrosse
+🏓 d83cdfd3; ping pong
+🏸 d83cdff8; badminton
+🥊 d83edd4a; boxing glove
+🥋 d83edd4b; martial arts uniform
+🥅 d83edd45; goal net
+⛳ 26f3; flag in hole
+⛸️ 26f8 fe0f; ice skate
+🎣 d83cdfa3; fishing pole
+🤿 d83edd3f; diving mask
+🎽 d83cdfbd; running shirt
+🎿 d83cdfbf; skis
+🛷 d83ddef7; sled
+🥌 d83edd4c; curling stone
+🎯 d83cdfaf; bullseye
+🪀 d83ede80; yo-yo
+🪁 d83ede81; kite
+🎱 d83cdfb1; pool 8 ball
+🔮 d83ddd2e; crystal ball
+🪄 d83ede84; magic wand
+🧿 d83eddff; nazar amulet
+🪬 d83edeac; hamsa
+🎮 d83cdfae; video game
+🕹️ d83ddd79 fe0f; joystick
+🎰 d83cdfb0; slot machine
+🎲 d83cdfb2; game die
+🧩 d83edde9; puzzle piece
+🧸 d83eddf8; teddy bear
+🪅 d83ede85; piñata
+🪩 d83edea9; mirror ball
+🪆 d83ede86; nesting dolls
+♠️ 2660 fe0f; spade suit
+♥️ 2665 fe0f; heart suit
+♦️ 2666 fe0f; diamond suit
+♣️ 2663 fe0f; club suit
+♟️ 265f fe0f; chess pawn
+🃏 d83cdccf; joker
+🀄 d83cdc04; mahjong red dragon
+🎴 d83cdfb4; flower playing cards
+🎭 d83cdfad; performing arts
+🖼️ d83dddbc fe0f; framed picture
+🎨 d83cdfa8; artist palette
+🧵 d83eddf5; thread
+🪡 d83edea1; sewing needle
+🧶 d83eddf6; yarn
+🪢 d83edea2; knot
+👓 d83ddc53; glasses
+🕶️ d83ddd76 fe0f; sunglasses
+🥽 d83edd7d; goggles
+🥼 d83edd7c; lab coat
+🦺 d83eddba; safety vest
+👔 d83ddc54; necktie
+👕 d83ddc55; t-shirt
+👖 d83ddc56; jeans
+🧣 d83edde3; scarf
+🧤 d83edde4; gloves
+🧥 d83edde5; coat
+🧦 d83edde6; socks
+👗 d83ddc57; dress
+👘 d83ddc58; kimono
+🥻 d83edd7b; sari
+🩱 d83ede71; one-piece swimsuit
+🩲 d83ede72; briefs
+🩳 d83ede73; shorts
+👙 d83ddc59; bikini
+👚 d83ddc5a; woman’s clothes
+👛 d83ddc5b; purse
+👜 d83ddc5c; handbag
+👝 d83ddc5d; clutch bag
+🛍️ d83ddecd fe0f; shopping bags
+🎒 d83cdf92; backpack
+🩴 d83ede74; thong sandal
+👞 d83ddc5e; man’s shoe
+👟 d83ddc5f; running shoe
+🥾 d83edd7e; hiking boot
+🥿 d83edd7f; flat shoe
+👠 d83ddc60; high-heeled shoe
+👡 d83ddc61; woman’s sandal
+🩰 d83ede70; ballet shoes
+👢 d83ddc62; woman’s boot
+👑 d83ddc51; crown
+👒 d83ddc52; woman’s hat
+🎩 d83cdfa9; top hat
+🎓 d83cdf93; graduation cap
+🧢 d83edde2; billed cap
+🪖 d83ede96; military helmet
+⛑️ 26d1 fe0f; rescue worker’s helmet
+📿 d83ddcff; prayer beads
+💄 d83ddc84; lipstick
+💍 d83ddc8d; ring
+💎 d83ddc8e; gem stone
+🔇 d83ddd07; muted speaker
+🔈 d83ddd08; speaker low volume
+🔉 d83ddd09; speaker medium volume
+🔊 d83ddd0a; speaker high volume
+📢 d83ddce2; loudspeaker
+📣 d83ddce3; megaphone
+📯 d83ddcef; postal horn
+🔔 d83ddd14; bell
+🔕 d83ddd15; bell with slash
+🎼 d83cdfbc; musical score
+🎵 d83cdfb5; musical note
+🎶 d83cdfb6; musical notes
+🎙️ d83cdf99 fe0f; studio microphone
+🎚️ d83cdf9a fe0f; level slider
+🎛️ d83cdf9b fe0f; control knobs
+🎤 d83cdfa4; microphone
+🎧 d83cdfa7; headphone
+📻 d83ddcfb; radio
+🎷 d83cdfb7; saxophone
+🪗 d83ede97; accordion
+🎸 d83cdfb8; guitar
+🎹 d83cdfb9; musical keyboard
+🎺 d83cdfba; trumpet
+🎻 d83cdfbb; violin
+🪕 d83ede95; banjo
+🥁 d83edd41; drum
+🪘 d83ede98; long drum
+📱 d83ddcf1; mobile phone
+📲 d83ddcf2; mobile phone with arrow
+☎️ 260e fe0f; telephone
+📞 d83ddcde; telephone receiver
+📟 d83ddcdf; pager
+📠 d83ddce0; fax machine
+🔋 d83ddd0b; battery
+🪫 d83edeab; low battery
+🔌 d83ddd0c; electric plug
+💻 d83ddcbb; laptop
+🖥️ d83ddda5 fe0f; desktop computer
+🖨️ d83ddda8 fe0f; printer
+⌨️ 2328 fe0f; keyboard
+🖱️ d83dddb1 fe0f; computer mouse
+🖲️ d83dddb2 fe0f; trackball
+💽 d83ddcbd; computer disk
+💾 d83ddcbe; floppy disk
+💿 d83ddcbf; optical disk
+📀 d83ddcc0; dvd
+🧮 d83eddee; abacus
+🎥 d83cdfa5; movie camera
+🎞️ d83cdf9e fe0f; film frames
+📽️ d83ddcfd fe0f; film projector
+🎬 d83cdfac; clapper board
+📺 d83ddcfa; television
+📷 d83ddcf7; camera
+📸 d83ddcf8; camera with flash
+📹 d83ddcf9; video camera
+📼 d83ddcfc; videocassette
+🔍 d83ddd0d; magnifying glass tilted left
+🔎 d83ddd0e; magnifying glass tilted right
+🕯️ d83ddd6f fe0f; candle
+💡 d83ddca1; light bulb
+🔦 d83ddd26; flashlight
+🏮 d83cdfee; red paper lantern
+🪔 d83ede94; diya lamp
+📔 d83ddcd4; notebook with decorative cover
+📕 d83ddcd5; closed book
+📖 d83ddcd6; open book
+📗 d83ddcd7; green book
+📘 d83ddcd8; blue book
+📙 d83ddcd9; orange book
+📚 d83ddcda; books
+📓 d83ddcd3; notebook
+📒 d83ddcd2; ledger
+📃 d83ddcc3; page with curl
+📜 d83ddcdc; scroll
+📄 d83ddcc4; page facing up
+📰 d83ddcf0; newspaper
+🗞️ d83dddde fe0f; rolled-up newspaper
+📑 d83ddcd1; bookmark tabs
+🔖 d83ddd16; bookmark
+🏷️ d83cdff7 fe0f; label
+💰 d83ddcb0; money bag
+🪙 d83ede99; coin
+💴 d83ddcb4; yen banknote
+💵 d83ddcb5; dollar banknote
+💶 d83ddcb6; euro banknote
+💷 d83ddcb7; pound banknote
+💸 d83ddcb8; money with wings
+💳 d83ddcb3; credit card
+🧾 d83eddfe; receipt
+💹 d83ddcb9; chart increasing with yen
+✉️ 2709 fe0f; envelope
+📧 d83ddce7; e-mail
+📨 d83ddce8; incoming envelope
+📩 d83ddce9; envelope with arrow
+📤 d83ddce4; outbox tray
+📥 d83ddce5; inbox tray
+📦 d83ddce6; package
+📫 d83ddceb; closed mailbox with raised flag
+📪 d83ddcea; closed mailbox with lowered flag
+📬 d83ddcec; open mailbox with raised flag
+📭 d83ddced; open mailbox with lowered flag
+📮 d83ddcee; postbox
+🗳️ d83dddf3 fe0f; ballot box with ballot
+✏️ 270f fe0f; pencil
+✒️ 2712 fe0f; black nib
+🖋️ d83ddd8b fe0f; fountain pen
+🖊️ d83ddd8a fe0f; pen
+🖌️ d83ddd8c fe0f; paintbrush
+🖍️ d83ddd8d fe0f; crayon
+📝 d83ddcdd; memo
+💼 d83ddcbc; briefcase
+📁 d83ddcc1; file folder
+📂 d83ddcc2; open file folder
+🗂️ d83dddc2 fe0f; card index dividers
+📅 d83ddcc5; calendar
+📆 d83ddcc6; tear-off calendar
+🗒️ d83dddd2 fe0f; spiral notepad
+🗓️ d83dddd3 fe0f; spiral calendar
+📇 d83ddcc7; card index
+📈 d83ddcc8; chart increasing
+📉 d83ddcc9; chart decreasing
+📊 d83ddcca; bar chart
+📋 d83ddccb; clipboard
+📌 d83ddccc; pushpin
+📍 d83ddccd; round pushpin
+📎 d83ddcce; paperclip
+🖇️ d83ddd87 fe0f; linked paperclips
+📏 d83ddccf; straight ruler
+📐 d83ddcd0; triangular ruler
+✂️ 2702 fe0f; scissors
+🗃️ d83dddc3 fe0f; card file box
+🗄️ d83dddc4 fe0f; file cabinet
+🗑️ d83dddd1 fe0f; wastebasket
+🔒 d83ddd12; locked
+🔓 d83ddd13; unlocked
+🔏 d83ddd0f; locked with pen
+🔐 d83ddd10; locked with key
+🔑 d83ddd11; key
+🗝️ d83ddddd fe0f; old key
+🔨 d83ddd28; hammer
+🪓 d83ede93; axe
+⛏️ 26cf fe0f; pick
+⚒️ 2692 fe0f; hammer and pick
+🛠️ d83ddee0 fe0f; hammer and wrench
+🗡️ d83ddde1 fe0f; dagger
+⚔️ 2694 fe0f; crossed swords
+🔫 d83ddd2b; water pistol
+🪃 d83ede83; boomerang
+🏹 d83cdff9; bow and arrow
+🛡️ d83ddee1 fe0f; shield
+🪚 d83ede9a; carpentry saw
+🔧 d83ddd27; wrench
+🪛 d83ede9b; screwdriver
+🔩 d83ddd29; nut and bolt
+⚙️ 2699 fe0f; gear
+🗜️ d83ddddc fe0f; clamp
+⚖️ 2696 fe0f; balance scale
+🦯 d83eddaf; white cane
+🔗 d83ddd17; link
+⛓️ 26d3 fe0f; chains
+🪝 d83ede9d; hook
+🧰 d83eddf0; toolbox
+🧲 d83eddf2; magnet
+🪜 d83ede9c; ladder
+⚗️ 2697 fe0f; alembic
+🧪 d83eddea; test tube
+🧫 d83eddeb; petri dish
+🧬 d83eddec; dna
+🔬 d83ddd2c; microscope
+🔭 d83ddd2d; telescope
+📡 d83ddce1; satellite antenna
+💉 d83ddc89; syringe
+🩸 d83ede78; drop of blood
+💊 d83ddc8a; pill
+🩹 d83ede79; adhesive bandage
+🩼 d83ede7c; crutch
+🩺 d83ede7a; stethoscope
+🩻 d83ede7b; x-ray
+🚪 d83ddeaa; door
+🛗 d83dded7; elevator
+🪞 d83ede9e; mirror
+🪟 d83ede9f; window
+🛏️ d83ddecf fe0f; bed
+🛋️ d83ddecb fe0f; couch and lamp
+🪑 d83ede91; chair
+🚽 d83ddebd; toilet
+🪠 d83edea0; plunger
+🚿 d83ddebf; shower
+🛁 d83ddec1; bathtub
+🪤 d83edea4; mouse trap
+🪒 d83ede92; razor
+🧴 d83eddf4; lotion bottle
+🧷 d83eddf7; safety pin
+🧹 d83eddf9; broom
+🧺 d83eddfa; basket
+🧻 d83eddfb; roll of paper
+🪣 d83edea3; bucket
+🧼 d83eddfc; soap
+🫧 d83edee7; bubbles
+🪥 d83edea5; toothbrush
+🧽 d83eddfd; sponge
+🧯 d83eddef; fire extinguisher
+🛒 d83dded2; shopping cart
+🚬 d83ddeac; cigarette
+⚰️ 26b0 fe0f; coffin
+🪦 d83edea6; headstone
+⚱️ 26b1 fe0f; funeral urn
+🗿 d83dddff; moai
+🪧 d83edea7; placard
+🪪 d83edeaa; identification card
+🏧 d83cdfe7; ATM sign
+🚮 d83ddeae; litter in bin sign
+🚰 d83ddeb0; potable water
+♿ 267f; wheelchair symbol
+🚹 d83ddeb9; men’s room
+🚺 d83ddeba; women’s room
+🚻 d83ddebb; restroom
+🚼 d83ddebc; baby symbol
+🚾 d83ddebe; water closet
+🛂 d83ddec2; passport control
+🛃 d83ddec3; customs
+🛄 d83ddec4; baggage claim
+🛅 d83ddec5; left luggage
+⚠️ 26a0 fe0f; warning
+🚸 d83ddeb8; children crossing
+⛔ 26d4; no entry
+🚫 d83ddeab; prohibited
+🚳 d83ddeb3; no bicycles
+🚭 d83ddead; no smoking
+🚯 d83ddeaf; no littering
+🚱 d83ddeb1; non-potable water
+🚷 d83ddeb7; no pedestrians
+📵 d83ddcf5; no mobile phones
+🔞 d83ddd1e; no one under eighteen
+☢️ 2622 fe0f; radioactive
+☣️ 2623 fe0f; biohazard
+⬆️ 2b06 fe0f; up arrow
+↗️ 2197 fe0f; up-right arrow
+➡️ 27a1 fe0f; right arrow
+↘️ 2198 fe0f; down-right arrow
+⬇️ 2b07 fe0f; down arrow
+↙️ 2199 fe0f; down-left arrow
+⬅️ 2b05 fe0f; left arrow
+↖️ 2196 fe0f; up-left arrow
+↕️ 2195 fe0f; up-down arrow
+↔️ 2194 fe0f; left-right arrow
+↩️ 21a9 fe0f; right arrow curving left
+↪️ 21aa fe0f; left arrow curving right
+⤴️ 2934 fe0f; right arrow curving up
+⤵️ 2935 fe0f; right arrow curving down
+🔃 d83ddd03; clockwise vertical arrows
+🔄 d83ddd04; counterclockwise arrows button
+🔙 d83ddd19; BACK arrow
+🔚 d83ddd1a; END arrow
+🔛 d83ddd1b; ON! arrow
+🔜 d83ddd1c; SOON arrow
+🔝 d83ddd1d; TOP arrow
+🛐 d83dded0; place of worship
+⚛️ 269b fe0f; atom symbol
+🕉️ d83ddd49 fe0f; om
+✡️ 2721 fe0f; star of David
+☸️ 2638 fe0f; wheel of dharma
+☯️ 262f fe0f; yin yang
+✝️ 271d fe0f; latin cross
+☦️ 2626 fe0f; orthodox cross
+☪️ 262a fe0f; star and crescent
+☮️ 262e fe0f; peace symbol
+🕎 d83ddd4e; menorah
+🔯 d83ddd2f; dotted six-pointed star
+♈ 2648; Aries
+♉ 2649; Taurus
+♊ 264a; Gemini
+♋ 264b; Cancer
+♌ 264c; Leo
+♍ 264d; Virgo
+♎ 264e; Libra
+♏ 264f; Scorpio
+♐ 2650; Sagittarius
+♑ 2651; Capricorn
+♒ 2652; Aquarius
+♓ 2653; Pisces
+⛎ 26ce; Ophiuchus
+🔀 d83ddd00; shuffle tracks button
+🔁 d83ddd01; repeat button
+🔂 d83ddd02; repeat single button
+▶️ 25b6 fe0f; play button
+⏩ 23e9; fast-forward button
+⏭️ 23ed fe0f; next track button
+⏯️ 23ef fe0f; play or pause button
+◀️ 25c0 fe0f; reverse button
+⏪ 23ea; fast reverse button
+⏮️ 23ee fe0f; last track button
+🔼 d83ddd3c; upwards button
+⏫ 23eb; fast up button
+🔽 d83ddd3d; downwards button
+⏬ 23ec; fast down button
+⏸️ 23f8 fe0f; pause button
+⏹️ 23f9 fe0f; stop button
+⏺️ 23fa fe0f; record button
+⏏️ 23cf fe0f; eject button
+🎦 d83cdfa6; cinema
+🔅 d83ddd05; dim button
+🔆 d83ddd06; bright button
+📶 d83ddcf6; antenna bars
+📳 d83ddcf3; vibration mode
+📴 d83ddcf4; mobile phone off
+♀️ 2640 fe0f; female sign
+♂️ 2642 fe0f; male sign
+⚧️ 26a7 fe0f; transgender symbol
+✖️ 2716 fe0f; multiply
+➕ 2795; plus
+➖ 2796; minus
+➗ 2797; divide
+🟰 d83ddff0; heavy equals sign
+♾️ 267e fe0f; infinity
+‼️ 203c fe0f; double exclamation mark
+⁉️ 2049 fe0f; exclamation question mark
+❓ 2753; red question mark
+❔ 2754; white question mark
+❕ 2755; white exclamation mark
+❗ 2757; red exclamation mark
+〰️ 3030 fe0f; wavy dash
+💱 d83ddcb1; currency exchange
+💲 d83ddcb2; heavy dollar sign
+⚕️ 2695 fe0f; medical symbol
+♻️ 267b fe0f; recycling symbol
+⚜️ 269c fe0f; fleur-de-lis
+🔱 d83ddd31; trident emblem
+📛 d83ddcdb; name badge
+🔰 d83ddd30; Japanese symbol for beginner
+⭕ 2b55; hollow red circle
+✅ 2705; check mark button
+☑️ 2611 fe0f; check box with check
+✔️ 2714 fe0f; check mark
+❌ 274c; cross mark
+❎ 274e; cross mark button
+➰ 27b0; curly loop
+➿ 27bf; double curly loop
+〽️ 303d fe0f; part alternation mark
+✳️ 2733 fe0f; eight-spoked asterisk
+✴️ 2734 fe0f; eight-pointed star
+❇️ 2747 fe0f; sparkle
+©️ 00a9 fe0f; copyright
+®️ 00ae fe0f; registered
+™️ 2122 fe0f; trade mark
+#️⃣ 0023 fe0f 20e3; keycap: #
+*️⃣ 002a fe0f 20e3; keycap: *
+0️⃣ 0030 fe0f 20e3; keycap: 0
+1️⃣ 0031 fe0f 20e3; keycap: 1
+2️⃣ 0032 fe0f 20e3; keycap: 2
+3️⃣ 0033 fe0f 20e3; keycap: 3
+4️⃣ 0034 fe0f 20e3; keycap: 4
+5️⃣ 0035 fe0f 20e3; keycap: 5
+6️⃣ 0036 fe0f 20e3; keycap: 6
+7️⃣ 0037 fe0f 20e3; keycap: 7
+8️⃣ 0038 fe0f 20e3; keycap: 8
+9️⃣ 0039 fe0f 20e3; keycap: 9
+🔟 d83ddd1f; keycap: 10
+🔠 d83ddd20; input latin uppercase
+🔡 d83ddd21; input latin lowercase
+🔢 d83ddd22; input numbers
+🔣 d83ddd23; input symbols
+🔤 d83ddd24; input latin letters
+🅰️ d83cdd70 fe0f; A button (blood type)
+🆎 d83cdd8e; AB button (blood type)
+🅱️ d83cdd71 fe0f; B button (blood type)
+🆑 d83cdd91; CL button
+🆒 d83cdd92; COOL button
+🆓 d83cdd93; FREE button
+ℹ️ 2139 fe0f; information
+🆔 d83cdd94; ID button
+Ⓜ️ 24c2 fe0f; circled M
+🆕 d83cdd95; NEW button
+🆖 d83cdd96; NG button
+🅾️ d83cdd7e fe0f; O button (blood type)
+🆗 d83cdd97; OK button
+🅿️ d83cdd7f fe0f; P button
+🆘 d83cdd98; SOS button
+🆙 d83cdd99; UP! button
+🆚 d83cdd9a; VS button
+🈁 d83cde01; Japanese “here” button
+🈂️ d83cde02 fe0f; Japanese “service charge” button
+🈷️ d83cde37 fe0f; Japanese “monthly amount” button
+🈶 d83cde36; Japanese “not free of charge” button
+🈯 d83cde2f; Japanese “reserved” button
+🉐 d83cde50; Japanese “bargain” button
+🈹 d83cde39; Japanese “discount” button
+🈚 d83cde1a; Japanese “free of charge” button
+🈲 d83cde32; Japanese “prohibited” button
+🉑 d83cde51; Japanese “acceptable” button
+🈸 d83cde38; Japanese “application” button
+🈴 d83cde34; Japanese “passing grade” button
+🈳 d83cde33; Japanese “vacancy” button
+㊗️ 3297 fe0f; Japanese “congratulations” button
+㊙️ 3299 fe0f; Japanese “secret” button
+🈺 d83cde3a; Japanese “open for business” button
+🈵 d83cde35; Japanese “no vacancy” button
+🔴 d83ddd34; red circle
+🟠 d83ddfe0; orange circle
+🟡 d83ddfe1; yellow circle
+🟢 d83ddfe2; green circle
+🔵 d83ddd35; blue circle
+🟣 d83ddfe3; purple circle
+🟤 d83ddfe4; brown circle
+⚫ 26ab; black circle
+⚪ 26aa; white circle
+🟥 d83ddfe5; red square
+🟧 d83ddfe7; orange square
+🟨 d83ddfe8; yellow square
+🟩 d83ddfe9; green square
+🟦 d83ddfe6; blue square
+🟪 d83ddfea; purple square
+🟫 d83ddfeb; brown square
+⬛ 2b1b; black large square
+⬜ 2b1c; white large square
+◼️ 25fc fe0f; black medium square
+◻️ 25fb fe0f; white medium square
+◾ 25fe; black medium-small square
+◽ 25fd; white medium-small square
+▪️ 25aa fe0f; black small square
+▫️ 25ab fe0f; white small square
+🔶 d83ddd36; large orange diamond
+🔷 d83ddd37; large blue diamond
+🔸 d83ddd38; small orange diamond
+🔹 d83ddd39; small blue diamond
+🔺 d83ddd3a; red triangle pointed up
+🔻 d83ddd3b; red triangle pointed down
+💠 d83ddca0; diamond with a dot
+🔘 d83ddd18; radio button
+🔳 d83ddd33; white square button
+🔲 d83ddd32; black square button
+🏁 d83cdfc1; chequered flag
+🚩 d83ddea9; triangular flag
+🎌 d83cdf8c; crossed flags
+🏴 d83cdff4; black flag
+🏳️ d83cdff3 fe0f; white flag
+🇦🇨 d83cdde6 d83cdde8; flag: Ascension Island
+🇦🇩 d83cdde6 d83cdde9; flag: Andorra
+🇦🇪 d83cdde6 d83cddea; flag: United Arab Emirates
+🇦🇫 d83cdde6 d83cddeb; flag: Afghanistan
+🇦🇬 d83cdde6 d83cddec; flag: Antigua & Barbuda
+🇦🇮 d83cdde6 d83cddee; flag: Anguilla
+🇦🇱 d83cdde6 d83cddf1; flag: Albania
+🇦🇲 d83cdde6 d83cddf2; flag: Armenia
+🇦🇴 d83cdde6 d83cddf4; flag: Angola
+🇦🇶 d83cdde6 d83cddf6; flag: Antarctica
+🇦🇷 d83cdde6 d83cddf7; flag: Argentina
+🇦🇸 d83cdde6 d83cddf8; flag: American Samoa
+🇦🇹 d83cdde6 d83cddf9; flag: Austria
+🇦🇺 d83cdde6 d83cddfa; flag: Australia
+🇦🇼 d83cdde6 d83cddfc; flag: Aruba
+🇦🇽 d83cdde6 d83cddfd; flag: Åland Islands
+🇦🇿 d83cdde6 d83cddff; flag: Azerbaijan
+🇧🇦 d83cdde7 d83cdde6; flag: Bosnia & Herzegovina
+🇧🇧 d83cdde7 d83cdde7; flag: Barbados
+🇧🇩 d83cdde7 d83cdde9; flag: Bangladesh
+🇧🇪 d83cdde7 d83cddea; flag: Belgium
+🇧🇫 d83cdde7 d83cddeb; flag: Burkina Faso
+🇧🇬 d83cdde7 d83cddec; flag: Bulgaria
+🇧🇭 d83cdde7 d83cdded; flag: Bahrain
+🇧🇮 d83cdde7 d83cddee; flag: Burundi
+🇧🇯 d83cdde7 d83cddef; flag: Benin
+🇧🇱 d83cdde7 d83cddf1; flag: St. Barthélemy
+🇧🇲 d83cdde7 d83cddf2; flag: Bermuda
+🇧🇳 d83cdde7 d83cddf3; flag: Brunei
+🇧🇴 d83cdde7 d83cddf4; flag: Bolivia
+🇧🇶 d83cdde7 d83cddf6; flag: Caribbean Netherlands
+🇧🇷 d83cdde7 d83cddf7; flag: Brazil
+🇧🇸 d83cdde7 d83cddf8; flag: Bahamas
+🇧🇹 d83cdde7 d83cddf9; flag: Bhutan
+🇧🇻 d83cdde7 d83cddfb; flag: Bouvet Island
+🇧🇼 d83cdde7 d83cddfc; flag: Botswana
+🇧🇾 d83cdde7 d83cddfe; flag: Belarus
+🇧🇿 d83cdde7 d83cddff; flag: Belize
+🇨🇦 d83cdde8 d83cdde6; flag: Canada
+🇨🇨 d83cdde8 d83cdde8; flag: Cocos (Keeling) Islands
+🇨🇩 d83cdde8 d83cdde9; flag: Congo - Kinshasa
+🇨🇫 d83cdde8 d83cddeb; flag: Central African Republic
+🇨🇬 d83cdde8 d83cddec; flag: Congo - Brazzaville
+🇨🇭 d83cdde8 d83cdded; flag: Switzerland
+🇨🇮 d83cdde8 d83cddee; flag: Côte d’Ivoire
+🇨🇰 d83cdde8 d83cddf0; flag: Cook Islands
+🇨🇱 d83cdde8 d83cddf1; flag: Chile
+🇨🇲 d83cdde8 d83cddf2; flag: Cameroon
+🇨🇳 d83cdde8 d83cddf3; flag: China
+🇨🇴 d83cdde8 d83cddf4; flag: Colombia
+🇨🇵 d83cdde8 d83cddf5; flag: Clipperton Island
+🇨🇷 d83cdde8 d83cddf7; flag: Costa Rica
+🇨🇺 d83cdde8 d83cddfa; flag: Cuba
+🇨🇻 d83cdde8 d83cddfb; flag: Cape Verde
+🇨🇼 d83cdde8 d83cddfc; flag: Curaçao
+🇨🇽 d83cdde8 d83cddfd; flag: Christmas Island
+🇨🇾 d83cdde8 d83cddfe; flag: Cyprus
+🇨🇿 d83cdde8 d83cddff; flag: Czechia
+🇩🇪 d83cdde9 d83cddea; flag: Germany
+🇩🇬 d83cdde9 d83cddec; flag: Diego Garcia
+🇩🇯 d83cdde9 d83cddef; flag: Djibouti
+🇩🇰 d83cdde9 d83cddf0; flag: Denmark
+🇩🇲 d83cdde9 d83cddf2; flag: Dominica
+🇩🇴 d83cdde9 d83cddf4; flag: Dominican Republic
+🇩🇿 d83cdde9 d83cddff; flag: Algeria
+🇪🇦 d83cddea d83cdde6; flag: Ceuta & Melilla
+🇪🇨 d83cddea d83cdde8; flag: Ecuador
+🇪🇪 d83cddea d83cddea; flag: Estonia
+🇪🇬 d83cddea d83cddec; flag: Egypt
+🇪🇭 d83cddea d83cdded; flag: Western Sahara
+🇪🇷 d83cddea d83cddf7; flag: Eritrea
+🇪🇸 d83cddea d83cddf8; flag: Spain
+🇪🇹 d83cddea d83cddf9; flag: Ethiopia
+🇪🇺 d83cddea d83cddfa; flag: European Union
+🇫🇮 d83cddeb d83cddee; flag: Finland
+🇫🇯 d83cddeb d83cddef; flag: Fiji
+🇫🇰 d83cddeb d83cddf0; flag: Falkland Islands
+🇫🇲 d83cddeb d83cddf2; flag: Micronesia
+🇫🇴 d83cddeb d83cddf4; flag: Faroe Islands
+🇫🇷 d83cddeb d83cddf7; flag: France
+🇬🇦 d83cddec d83cdde6; flag: Gabon
+🇬🇧 d83cddec d83cdde7; flag: United Kingdom
+🇬🇩 d83cddec d83cdde9; flag: Grenada
+🇬🇪 d83cddec d83cddea; flag: Georgia
+🇬🇫 d83cddec d83cddeb; flag: French Guiana
+🇬🇬 d83cddec d83cddec; flag: Guernsey
+🇬🇭 d83cddec d83cdded; flag: Ghana
+🇬🇮 d83cddec d83cddee; flag: Gibraltar
+🇬🇱 d83cddec d83cddf1; flag: Greenland
+🇬🇲 d83cddec d83cddf2; flag: Gambia
+🇬🇳 d83cddec d83cddf3; flag: Guinea
+🇬🇵 d83cddec d83cddf5; flag: Guadeloupe
+🇬🇶 d83cddec d83cddf6; flag: Equatorial Guinea
+🇬🇷 d83cddec d83cddf7; flag: Greece
+🇬🇸 d83cddec d83cddf8; flag: South Georgia & South Sandwich Islands
+🇬🇹 d83cddec d83cddf9; flag: Guatemala
+🇬🇺 d83cddec d83cddfa; flag: Guam
+🇬🇼 d83cddec d83cddfc; flag: Guinea-Bissau
+🇬🇾 d83cddec d83cddfe; flag: Guyana
+🇭🇰 d83cdded d83cddf0; flag: Hong Kong SAR China
+🇭🇲 d83cdded d83cddf2; flag: Heard & McDonald Islands
+🇭🇳 d83cdded d83cddf3; flag: Honduras
+🇭🇷 d83cdded d83cddf7; flag: Croatia
+🇭🇹 d83cdded d83cddf9; flag: Haiti
+🇭🇺 d83cdded d83cddfa; flag: Hungary
+🇮🇨 d83cddee d83cdde8; flag: Canary Islands
+🇮🇩 d83cddee d83cdde9; flag: Indonesia
+🇮🇪 d83cddee d83cddea; flag: Ireland
+🇮🇱 d83cddee d83cddf1; flag: Israel
+🇮🇲 d83cddee d83cddf2; flag: Isle of Man
+🇮🇳 d83cddee d83cddf3; flag: India
+🇮🇴 d83cddee d83cddf4; flag: British Indian Ocean Territory
+🇮🇶 d83cddee d83cddf6; flag: Iraq
+🇮🇷 d83cddee d83cddf7; flag: Iran
+🇮🇸 d83cddee d83cddf8; flag: Iceland
+🇮🇹 d83cddee d83cddf9; flag: Italy
+🇯🇪 d83cddef d83cddea; flag: Jersey
+🇯🇲 d83cddef d83cddf2; flag: Jamaica
+🇯🇴 d83cddef d83cddf4; flag: Jordan
+🇯🇵 d83cddef d83cddf5; flag: Japan
+🇰🇪 d83cddf0 d83cddea; flag: Kenya
+🇰🇬 d83cddf0 d83cddec; flag: Kyrgyzstan
+🇰🇭 d83cddf0 d83cdded; flag: Cambodia
+🇰🇮 d83cddf0 d83cddee; flag: Kiribati
+🇰🇲 d83cddf0 d83cddf2; flag: Comoros
+🇰🇳 d83cddf0 d83cddf3; flag: St. Kitts & Nevis
+🇰🇵 d83cddf0 d83cddf5; flag: North Korea
+🇰🇷 d83cddf0 d83cddf7; flag: South Korea
+🇰🇼 d83cddf0 d83cddfc; flag: Kuwait
+🇰🇾 d83cddf0 d83cddfe; flag: Cayman Islands
+🇰🇿 d83cddf0 d83cddff; flag: Kazakhstan
+🇱🇦 d83cddf1 d83cdde6; flag: Laos
+🇱🇧 d83cddf1 d83cdde7; flag: Lebanon
+🇱🇨 d83cddf1 d83cdde8; flag: St. Lucia
+🇱🇮 d83cddf1 d83cddee; flag: Liechtenstein
+🇱🇰 d83cddf1 d83cddf0; flag: Sri Lanka
+🇱🇷 d83cddf1 d83cddf7; flag: Liberia
+🇱🇸 d83cddf1 d83cddf8; flag: Lesotho
+🇱🇹 d83cddf1 d83cddf9; flag: Lithuania
+🇱🇺 d83cddf1 d83cddfa; flag: Luxembourg
+🇱🇻 d83cddf1 d83cddfb; flag: Latvia
+🇱🇾 d83cddf1 d83cddfe; flag: Libya
+🇲🇦 d83cddf2 d83cdde6; flag: Morocco
+🇲🇨 d83cddf2 d83cdde8; flag: Monaco
+🇲🇩 d83cddf2 d83cdde9; flag: Moldova
+🇲🇪 d83cddf2 d83cddea; flag: Montenegro
+🇲🇫 d83cddf2 d83cddeb; flag: St. Martin
+🇲🇬 d83cddf2 d83cddec; flag: Madagascar
+🇲🇭 d83cddf2 d83cdded; flag: Marshall Islands
+🇲🇰 d83cddf2 d83cddf0; flag: North Macedonia
+🇲🇱 d83cddf2 d83cddf1; flag: Mali
+🇲🇲 d83cddf2 d83cddf2; flag: Myanmar (Burma)
+🇲🇳 d83cddf2 d83cddf3; flag: Mongolia
+🇲🇴 d83cddf2 d83cddf4; flag: Macao SAR China
+🇲🇵 d83cddf2 d83cddf5; flag: Northern Mariana Islands
+🇲🇶 d83cddf2 d83cddf6; flag: Martinique
+🇲🇷 d83cddf2 d83cddf7; flag: Mauritania
+🇲🇸 d83cddf2 d83cddf8; flag: Montserrat
+🇲🇹 d83cddf2 d83cddf9; flag: Malta
+🇲🇺 d83cddf2 d83cddfa; flag: Mauritius
+🇲🇻 d83cddf2 d83cddfb; flag: Maldives
+🇲🇼 d83cddf2 d83cddfc; flag: Malawi
+🇲🇽 d83cddf2 d83cddfd; flag: Mexico
+🇲🇾 d83cddf2 d83cddfe; flag: Malaysia
+🇲🇿 d83cddf2 d83cddff; flag: Mozambique
+🇳🇦 d83cddf3 d83cdde6; flag: Namibia
+🇳🇨 d83cddf3 d83cdde8; flag: New Caledonia
+🇳🇪 d83cddf3 d83cddea; flag: Niger
+🇳🇫 d83cddf3 d83cddeb; flag: Norfolk Island
+🇳🇬 d83cddf3 d83cddec; flag: Nigeria
+🇳🇮 d83cddf3 d83cddee; flag: Nicaragua
+🇳🇱 d83cddf3 d83cddf1; flag: Netherlands
+🇳🇴 d83cddf3 d83cddf4; flag: Norway
+🇳🇵 d83cddf3 d83cddf5; flag: Nepal
+🇳🇷 d83cddf3 d83cddf7; flag: Nauru
+🇳🇺 d83cddf3 d83cddfa; flag: Niue
+🇳🇿 d83cddf3 d83cddff; flag: New Zealand
+🇴🇲 d83cddf4 d83cddf2; flag: Oman
+🇵🇦 d83cddf5 d83cdde6; flag: Panama
+🇵🇪 d83cddf5 d83cddea; flag: Peru
+🇵🇫 d83cddf5 d83cddeb; flag: French Polynesia
+🇵🇬 d83cddf5 d83cddec; flag: Papua New Guinea
+🇵🇭 d83cddf5 d83cdded; flag: Philippines
+🇵🇰 d83cddf5 d83cddf0; flag: Pakistan
+🇵🇱 d83cddf5 d83cddf1; flag: Poland
+🇵🇲 d83cddf5 d83cddf2; flag: St. Pierre & Miquelon
+🇵🇳 d83cddf5 d83cddf3; flag: Pitcairn Islands
+🇵🇷 d83cddf5 d83cddf7; flag: Puerto Rico
+🇵🇸 d83cddf5 d83cddf8; flag: Palestinian Territories
+🇵🇹 d83cddf5 d83cddf9; flag: Portugal
+🇵🇼 d83cddf5 d83cddfc; flag: Palau
+🇵🇾 d83cddf5 d83cddfe; flag: Paraguay
+🇶🇦 d83cddf6 d83cdde6; flag: Qatar
+🇷🇪 d83cddf7 d83cddea; flag: Réunion
+🇷🇴 d83cddf7 d83cddf4; flag: Romania
+🇷🇸 d83cddf7 d83cddf8; flag: Serbia
+🇷🇺 d83cddf7 d83cddfa; flag: Russia
+🇷🇼 d83cddf7 d83cddfc; flag: Rwanda
+🇸🇦 d83cddf8 d83cdde6; flag: Saudi Arabia
+🇸🇧 d83cddf8 d83cdde7; flag: Solomon Islands
+🇸🇨 d83cddf8 d83cdde8; flag: Seychelles
+🇸🇩 d83cddf8 d83cdde9; flag: Sudan
+🇸🇪 d83cddf8 d83cddea; flag: Sweden
+🇸🇬 d83cddf8 d83cddec; flag: Singapore
+🇸🇭 d83cddf8 d83cdded; flag: St. Helena
+🇸🇮 d83cddf8 d83cddee; flag: Slovenia
+🇸🇯 d83cddf8 d83cddef; flag: Svalbard & Jan Mayen
+🇸🇰 d83cddf8 d83cddf0; flag: Slovakia
+🇸🇱 d83cddf8 d83cddf1; flag: Sierra Leone
+🇸🇲 d83cddf8 d83cddf2; flag: San Marino
+🇸🇳 d83cddf8 d83cddf3; flag: Senegal
+🇸🇴 d83cddf8 d83cddf4; flag: Somalia
+🇸🇷 d83cddf8 d83cddf7; flag: Suriname
+🇸🇸 d83cddf8 d83cddf8; flag: South Sudan
+🇸🇹 d83cddf8 d83cddf9; flag: São Tomé & Príncipe
+🇸🇻 d83cddf8 d83cddfb; flag: El Salvador
+🇸🇽 d83cddf8 d83cddfd; flag: Sint Maarten
+🇸🇾 d83cddf8 d83cddfe; flag: Syria
+🇸🇿 d83cddf8 d83cddff; flag: Eswatini
+🇹🇦 d83cddf9 d83cdde6; flag: Tristan da Cunha
+🇹🇨 d83cddf9 d83cdde8; flag: Turks & Caicos Islands
+🇹🇩 d83cddf9 d83cdde9; flag: Chad
+🇹🇫 d83cddf9 d83cddeb; flag: French Southern Territories
+🇹🇬 d83cddf9 d83cddec; flag: Togo
+🇹🇭 d83cddf9 d83cdded; flag: Thailand
+🇹🇯 d83cddf9 d83cddef; flag: Tajikistan
+🇹🇰 d83cddf9 d83cddf0; flag: Tokelau
+🇹🇱 d83cddf9 d83cddf1; flag: Timor-Leste
+🇹🇲 d83cddf9 d83cddf2; flag: Turkmenistan
+🇹🇳 d83cddf9 d83cddf3; flag: Tunisia
+🇹🇴 d83cddf9 d83cddf4; flag: Tonga
+🇹🇷 d83cddf9 d83cddf7; flag: Turkey
+🇹🇹 d83cddf9 d83cddf9; flag: Trinidad & Tobago
+🇹🇻 d83cddf9 d83cddfb; flag: Tuvalu
+🇹🇼 d83cddf9 d83cddfc; flag: Taiwan
+🇹🇿 d83cddf9 d83cddff; flag: Tanzania
+🇺🇦 d83cddfa d83cdde6; flag: Ukraine
+🇺🇬 d83cddfa d83cddec; flag: Uganda
+🇺🇲 d83cddfa d83cddf2; flag: U.S. Outlying Islands
+🇺🇳 d83cddfa d83cddf3; flag: United Nations
+🇺🇸 d83cddfa d83cddf8; flag: United States
+🇺🇾 d83cddfa d83cddfe; flag: Uruguay
+🇺🇿 d83cddfa d83cddff; flag: Uzbekistan
+🇻🇦 d83cddfb d83cdde6; flag: Vatican City
+🇻🇨 d83cddfb d83cdde8; flag: St. Vincent & Grenadines
+🇻🇪 d83cddfb d83cddea; flag: Venezuela
+🇻🇬 d83cddfb d83cddec; flag: British Virgin Islands
+🇻🇮 d83cddfb d83cddee; flag: U.S. Virgin Islands
+🇻🇳 d83cddfb d83cddf3; flag: Vietnam
+🇻🇺 d83cddfb d83cddfa; flag: Vanuatu
+🇼🇫 d83cddfc d83cddeb; flag: Wallis & Futuna
+🇼🇸 d83cddfc d83cddf8; flag: Samoa
+🇽🇰 d83cddfd d83cddf0; flag: Kosovo
+🇾🇪 d83cddfe d83cddea; flag: Yemen
+🇾🇹 d83cddfe d83cddf9; flag: Mayotte
+🇿🇦 d83cddff d83cdde6; flag: South Africa
+🇿🇲 d83cddff d83cddf2; flag: Zambia
+🇿🇼 d83cddff d83cddfc; flag: Zimbabwe
+🏴󠁧󠁢󠁥󠁮󠁧󠁿 d83cdff4 db40dc67 db40dc62 db40dc65 db40dc6e db40dc67 db40dc7f; flag: England
+🏴󠁧󠁢󠁳󠁣󠁴󠁿 d83cdff4 db40dc67 db40dc62 db40dc73 db40dc63 db40dc74 db40dc7f; flag: Scotland
+🏴󠁧󠁢󠁷󠁬󠁳󠁿 d83cdff4 db40dc67 db40dc62 db40dc77 db40dc6c db40dc73 db40dc7f; flag: Wales
diff --git a/.local/share/chars/font-awesome b/.local/share/chars/font-awesome
new file mode 100644
index 0000000..882068e
--- /dev/null
+++ b/.local/share/chars/font-awesome
@@ -0,0 +1,1456 @@
+ f26e; 500px
+ f368; accessible-icon
+ f369; accusoft
+ f6af; acquisitions-incorporated
+ f641; ad
+ f2b9; address-book
+ f2bb; address-card
+ f042; adjust
+ f170; adn
+ f36a; adversal
+ f36b; affiliatetheme
+ f5d0; air-freshener
+ f834; airbnb
+ f36c; algolia
+ f037; align-center
+ f039; align-justify
+ f036; align-left
+ f038; align-right
+ f642; alipay
+ f461; allergies
+ f270; amazon
+ f42c; amazon-pay
+ f0f9; ambulance
+ f2a3; american-sign-language-interpreting
+ f36d; amilia
+ f13d; anchor
+ f17b; android
+ f209; angellist
+ f103; angle-double-down
+ f100; angle-double-left
+ f101; angle-double-right
+ f102; angle-double-up
+ f107; angle-down
+ f104; angle-left
+ f105; angle-right
+ f106; angle-up
+ f556; angry
+ f36e; angrycreative
+ f420; angular
+ f644; ankh
+ f36f; app-store
+ f370; app-store-ios
+ f371; apper
+ f179; apple
+ f5d1; apple-alt
+ f415; apple-pay
+ f187; archive
+ f557; archway
+ f358; arrow-alt-circle-down
+ f359; arrow-alt-circle-left
+ f35a; arrow-alt-circle-right
+ f35b; arrow-alt-circle-up
+ f0ab; arrow-circle-down
+ f0a8; arrow-circle-left
+ f0a9; arrow-circle-right
+ f0aa; arrow-circle-up
+ f063; arrow-down
+ f060; arrow-left
+ f061; arrow-right
+ f062; arrow-up
+ f0b2; arrows-alt
+ f337; arrows-alt-h
+ f338; arrows-alt-v
+ f77a; artstation
+ f2a2; assistive-listening-systems
+ f069; asterisk
+ f372; asymmetrik
+ f1fa; at
+ f558; atlas
+ f77b; atlassian
+ f5d2; atom
+ f373; audible
+ f29e; audio-description
+ f41c; autoprefixer
+ f374; avianex
+ f421; aviato
+ f559; award
+ f375; aws
+ f77c; baby
+ f77d; baby-carriage
+ f55a; backspace
+ f04a; backward
+ f7e5; bacon
+ e059; bacteri
+ e05a; bacteriu
+ f666; bahai
+ f24e; balance-scale
+ f515; balance-scale-left
+ f516; balance-scale-right
+ f05e; ban
+ f462; band-aid
+ f2d5; bandcamp
+ f02a; barcode
+ f0c9; bars
+ f433; baseball-ball
+ f434; basketball-ball
+ f2cd; bath
+ f244; battery-empty
+ f240; battery-full
+ f242; battery-half
+ f243; battery-quarter
+ f241; battery-three-quarters
+ f835; battle-net
+ f236; bed
+ f0fc; beer
+ f1b4; behance
+ f1b5; behance-square
+ f0f3; bell
+ f1f6; bell-slash
+ f55b; bezier-curve
+ f647; bible
+ f206; bicycle
+ f84a; biking
+ f378; bimobject
+ f1e5; binoculars
+ f780; biohazard
+ f1fd; birthday-cake
+ f171; bitbucket
+ f379; bitcoin
+ f37a; bity
+ f27e; black-tie
+ f37b; blackberry
+ f517; blender
+ f6b6; blender-phone
+ f29d; blind
+ f781; blog
+ f37c; blogger
+ f37d; blogger-b
+ f293; bluetooth
+ f294; bluetooth-b
+ f032; bold
+ f0e7; bolt
+ f1e2; bomb
+ f5d7; bone
+ f55c; bong
+ f02d; book
+ f6b7; book-dead
+ f7e6; book-medical
+ f518; book-open
+ f5da; book-reader
+ f02e; bookmark
+ f836; bootstrap
+ f84c; border-all
+ f850; border-none
+ f853; border-style
+ f436; bowling-ball
+ f466; box
+ f49e; box-open
+ e05b; box-tissu
+ f468; boxes
+ f2a1; braille
+ f5dc; brain
+ f7ec; bread-slice
+ f0b1; briefcase
+ f469; briefcase-medical
+ f519; broadcast-tower
+ f51a; broom
+ f55d; brush
+ f15a; btc
+ f837; buffer
+ f188; bug
+ f1ad; building
+ f0a1; bullhorn
+ f140; bullseye
+ f46a; burn
+ f37f; buromobelexperte
+ f207; bus
+ f55e; bus-alt
+ f64a; business-time
+ f8a6; buy-n-large
+ f1ec; calculator
+ f133; calendar
+ f073; calendar-alt
+ f274; calendar-check
+ f783; calendar-day
+ f272; calendar-minus
+ f271; calendar-plus
+ f273; calendar-times
+ f784; calendar-week
+ f030; camera
+ f083; camera-retro
+ f6bb; campground
+ f785; canadian-maple-leaf
+ f786; candy-cane
+ f55f; cannabis
+ f46b; capsules
+ f1b9; car
+ f5de; car-alt
+ f5df; car-battery
+ f5e1; car-crash
+ f5e4; car-side
+ f8ff; caravan
+ f0d7; caret-down
+ f0d9; caret-left
+ f0da; caret-right
+ f150; caret-square-down
+ f191; caret-square-left
+ f152; caret-square-right
+ f151; caret-square-up
+ f0d8; caret-up
+ f787; carrot
+ f218; cart-arrow-down
+ f217; cart-plus
+ f788; cash-register
+ f6be; cat
+ f42d; cc-amazon-pay
+ f1f3; cc-amex
+ f416; cc-apple-pay
+ f24c; cc-diners-club
+ f1f2; cc-discover
+ f24b; cc-jcb
+ f1f1; cc-mastercard
+ f1f4; cc-paypal
+ f1f5; cc-stripe
+ f1f0; cc-visa
+ f380; centercode
+ f789; centos
+ f0a3; certificate
+ f6c0; chair
+ f51b; chalkboard
+ f51c; chalkboard-teacher
+ f5e7; charging-station
+ f1fe; chart-area
+ f080; chart-bar
+ f201; chart-line
+ f200; chart-pie
+ f00c; check
+ f058; check-circle
+ f560; check-double
+ f14a; check-square
+ f7ef; cheese
+ f439; chess
+ f43a; chess-bishop
+ f43c; chess-board
+ f43f; chess-king
+ f441; chess-knight
+ f443; chess-pawn
+ f445; chess-queen
+ f447; chess-rook
+ f13a; chevron-circle-down
+ f137; chevron-circle-left
+ f138; chevron-circle-right
+ f139; chevron-circle-up
+ f078; chevron-down
+ f053; chevron-left
+ f054; chevron-right
+ f077; chevron-up
+ f1ae; child
+ f268; chrome
+ f838; chromecast
+ f51d; church
+ f111; circle
+ f1ce; circle-notch
+ f64f; city
+ f7f2; clinic-medical
+ f328; clipboard
+ f46c; clipboard-check
+ f46d; clipboard-list
+ f017; clock
+ f24d; clone
+ f20a; closed-captioning
+ f0c2; cloud
+ f381; cloud-download-alt
+ f73b; cloud-meatball
+ f6c3; cloud-moon
+ f73c; cloud-moon-rain
+ f73d; cloud-rain
+ f740; cloud-showers-heavy
+ f6c4; cloud-sun
+ f743; cloud-sun-rain
+ f382; cloud-upload-alt
+ e07d; cloudflar
+ f383; cloudscale
+ f384; cloudsmith
+ f385; cloudversify
+ f561; cocktail
+ f121; code
+ f126; code-branch
+ f1cb; codepen
+ f284; codiepie
+ f0f4; coffee
+ f013; cog
+ f085; cogs
+ f51e; coins
+ f0db; columns
+ f075; comment
+ f27a; comment-alt
+ f651; comment-dollar
+ f4ad; comment-dots
+ f7f5; comment-medical
+ f4b3; comment-slash
+ f086; comments
+ f653; comments-dollar
+ f51f; compact-disc
+ f14e; compass
+ f066; compress
+ f422; compress-alt
+ f78c; compress-arrows-alt
+ f562; concierge-bell
+ f78d; confluence
+ f20e; connectdevelop
+ f26d; contao
+ f563; cookie
+ f564; cookie-bite
+ f0c5; copy
+ f1f9; copyright
+ f89e; cotton-bureau
+ f4b8; couch
+ f388; cpanel
+ f25e; creative-commons
+ f4e7; creative-commons-by
+ f4e8; creative-commons-nc
+ f4e9; creative-commons-nc-eu
+ f4ea; creative-commons-nc-jp
+ f4eb; creative-commons-nd
+ f4ec; creative-commons-pd
+ f4ed; creative-commons-pd-alt
+ f4ee; creative-commons-remix
+ f4ef; creative-commons-sa
+ f4f0; creative-commons-sampling
+ f4f1; creative-commons-sampling-plus
+ f4f2; creative-commons-share
+ f4f3; creative-commons-zero
+ f09d; credit-card
+ f6c9; critical-role
+ f125; crop
+ f565; crop-alt
+ f654; cross
+ f05b; crosshairs
+ f520; crow
+ f521; crown
+ f7f7; crutch
+ f13c; css3
+ f38b; css3-alt
+ f1b2; cube
+ f1b3; cubes
+ f0c4; cut
+ f38c; cuttlefish
+ f38d; d-and-d
+ f6ca; d-and-d-beyond
+ e052; dailymotio
+ f210; dashcube
+ f1c0; database
+ f2a4; deaf
+ e077; deeze
+ f1a5; delicious
+ f747; democrat
+ f38e; deploydog
+ f38f; deskpro
+ f108; desktop
+ f6cc; dev
+ f1bd; deviantart
+ f655; dharmachakra
+ f790; dhl
+ f470; diagnoses
+ f791; diaspora
+ f522; dice
+ f6cf; dice-d20
+ f6d1; dice-d6
+ f523; dice-five
+ f524; dice-four
+ f525; dice-one
+ f526; dice-six
+ f527; dice-three
+ f528; dice-two
+ f1a6; digg
+ f391; digital-ocean
+ f566; digital-tachograph
+ f5eb; directions
+ f392; discord
+ f393; discourse
+ f7fa; disease
+ f529; divide
+ f567; dizzy
+ f471; dna
+ f394; dochub
+ f395; docker
+ f6d3; dog
+ f155; dollar-sign
+ f472; dolly
+ f474; dolly-flatbed
+ f4b9; donate
+ f52a; door-closed
+ f52b; door-open
+ f192; dot-circle
+ f4ba; dove
+ f019; download
+ f396; draft2digital
+ f568; drafting-compass
+ f6d5; dragon
+ f5ee; draw-polygon
+ f17d; dribbble
+ f397; dribbble-square
+ f16b; dropbox
+ f569; drum
+ f56a; drum-steelpan
+ f6d7; drumstick-bite
+ f1a9; drupal
+ f44b; dumbbell
+ f793; dumpster
+ f794; dumpster-fire
+ f6d9; dungeon
+ f399; dyalog
+ f39a; earlybirds
+ f4f4; ebay
+ f282; edge
+ e078; edge-legac
+ f044; edit
+ f7fb; egg
+ f052; eject
+ f430; elementor
+ f141; ellipsis-h
+ f142; ellipsis-v
+ f5f1; ello
+ f423; ember
+ f1d1; empire
+ f0e0; envelope
+ f2b6; envelope-open
+ f658; envelope-open-text
+ f199; envelope-square
+ f299; envira
+ f52c; equals
+ f12d; eraser
+ f39d; erlang
+ f42e; ethereum
+ f796; ethernet
+ f2d7; etsy
+ f153; euro-sign
+ f839; evernote
+ f362; exchange-alt
+ f12a; exclamation
+ f06a; exclamation-circle
+ f071; exclamation-triangle
+ f065; expand
+ f424; expand-alt
+ f31e; expand-arrows-alt
+ f23e; expeditedssl
+ f35d; external-link-alt
+ f360; external-link-square-alt
+ f06e; eye
+ f1fb; eye-dropper
+ f070; eye-slash
+ f09a;; facebook
+ f39e;; facebook-f
+ f39f;; facebook-messenger
+ f082;; facebook-square
+ f863;; fan
+ f6dc;; fantasy-flight-games
+ f049;; fast-backward
+ f050;; fast-forward
+ e005;; fauce
+ f1ac;; fax
+ f52d;; feather
+ f56b;; feather-alt
+ f797;; fedex
+ f798;; fedora
+ f182;; female
+ f0fb;; fighter-jet
+ f799;; figma
+ f15b;; file
+ f15c;; file-alt
+ f1c6;; file-archive
+ f1c7;; file-audio
+ f1c9;; file-code
+ f56c;; file-contract
+ f6dd;; file-csv
+ f56d;; file-download
+ f1c3;; file-excel
+ f56e;; file-export
+ f1c5;; file-image
+ f56f;; file-import
+ f570;; file-invoice
+ f571;; file-invoice-dollar
+ f477;; file-medical
+ f478;; file-medical-alt
+ f1c1;; file-pdf
+ f1c4;; file-powerpoint
+ f572;; file-prescription
+ f573;; file-signature
+ f574;; file-upload
+ f1c8;; file-video
+ f1c2;; file-word
+ f575;; fill
+ f576;; fill-drip
+ f008;; film
+ f0b0;; filter
+ f577;; fingerprint
+ f06d;; fire
+ f7e4;; fire-alt
+ f134;; fire-extinguisher
+ f269;; firefox
+ e007;; firefox-browse
+ f479;; first-aid
+ f2b0;; first-order
+ f50a;; first-order-alt
+ f3a1;; firstdraft
+ f578;; fish
+ f6de;; fist-raised
+ f024;; flag
+ f11e;; flag-checkered
+ f74d;; flag-usa
+ f0c3;; flask
+ f16e;; flickr
+ f44d;; flipboard
+ f579;; flushed
+ f417;; fly
+ f07b;; folder
+ f65d;; folder-minus
+ f07c;; folder-open
+ f65e;; folder-plus
+ f031;; font
+ f2b4;; font-awesome
+ f35c;; font-awesome-alt
+ f425;; font-awesome-flag
+ f280;; fonticons
+ f3a2;; fonticons-fi
+ f44e;; football-ball
+ f286;; fort-awesome
+ f3a3;; fort-awesome-alt
+ f211;; forumbee
+ f04e;; forward
+ f180;; foursquare
+ f2c5;; free-code-camp
+ f3a4;; freebsd
+ f52e;; frog
+ f119;; frown
+ f57a;; frown-open
+ f50b;; fulcrum
+ f662;; funnel-dollar
+ f1e3;; futbol
+ f50c; galactic-republic
+ f50d; galactic-senate
+ f11b; gamepad
+ f52f; gas-pump
+ f0e3; gavel
+ f3a5; gem
+ f22d; genderless
+ f265; get-pocket
+ f260; gg
+ f261; gg-circle
+ f6e2; ghost
+ f06b; gift
+ f79c; gifts
+ f1d3; git
+ f841; git-alt
+ f1d2; git-square
+ f09b; github
+ f113; github-alt
+ f092; github-square
+ f3a6; gitkraken
+ f296; gitlab
+ f426; gitter
+ f79f; glass-cheers
+ f000; glass-martini
+ f57b; glass-martini-alt
+ f7a0; glass-whiskey
+ f530; glasses
+ f2a5; glide
+ f2a6; glide-g
+ f0ac; globe
+ f57c; globe-africa
+ f57d; globe-americas
+ f57e; globe-asia
+ f7a2; globe-europe
+ f3a7; gofore
+ f450; golf-ball
+ f3a8; goodreads
+ f3a9; goodreads-g
+ f1a0; google
+ f3aa; google-drive
+ e079; google-pa
+ f3ab; google-play
+ f2b3; google-plus
+ f0d5; google-plus-g
+ f0d4; google-plus-square
+ f1ee; google-wallet
+ f664; gopuram
+ f19d; graduation-cap
+ f184; gratipay
+ f2d6; grav
+ f531; greater-than
+ f532; greater-than-equal
+ f57f; grimace
+ f580; grin
+ f581; grin-alt
+ f582; grin-beam
+ f583; grin-beam-sweat
+ f584; grin-hearts
+ f585; grin-squint
+ f586; grin-squint-tears
+ f587; grin-stars
+ f588; grin-tears
+ f589; grin-tongue
+ f58a; grin-tongue-squint
+ f58b; grin-tongue-wink
+ f58c; grin-wink
+ f58d; grip-horizontal
+ f7a4; grip-lines
+ f7a5; grip-lines-vertical
+ f58e; grip-vertical
+ f3ac; gripfire
+ f3ad; grunt
+ e07e; guilde
+ f7a6; guitar
+ f3ae; gulp
+ f0fd; h-square
+ f1d4; hacker-news
+ f3af; hacker-news-square
+ f5f7; hackerrank
+ f805; hamburger
+ f6e3; hammer
+ f665; hamsa
+ f4bd; hand-holding
+ f4be; hand-holding-heart
+ e05c; hand-holding-medica
+ f4c0; hand-holding-usd
+ f4c1; hand-holding-water
+ f258; hand-lizard
+ f806; hand-middle-finger
+ f256; hand-paper
+ f25b; hand-peace
+ f0a7; hand-point-down
+ f0a5; hand-point-left
+ f0a4; hand-point-right
+ f0a6; hand-point-up
+ f25a; hand-pointer
+ f255; hand-rock
+ f257; hand-scissors
+ e05d; hand-sparkle
+ f259; hand-spock
+ f4c2; hands
+ f4c4; hands-helping
+ e05e; hands-was
+ f2b5; handshake
+ e05f; handshake-alt-slas
+ e060; handshake-slas
+ f6e6; hanukiah
+ f807; hard-hat
+ f292; hashtag
+ f8c0; hat-cowboy
+ f8c1; hat-cowboy-side
+ f6e8; hat-wizard
+ f0a0; hdd
+ e061; head-side-coug
+ e062; head-side-cough-slas
+ e063; head-side-mas
+ e064; head-side-viru
+ f1dc; heading
+ f025; headphones
+ f58f; headphones-alt
+ f590; headset
+ f004; heart
+ f7a9; heart-broken
+ f21e; heartbeat
+ f533; helicopter
+ f591; highlighter
+ f6ec; hiking
+ f6ed; hippo
+ f452; hips
+ f3b0; hire-a-helper
+ f1da; history
+ e07f; hiv
+ f453; hockey-puck
+ f7aa; holly-berry
+ f015; home
+ f427; hooli
+ f592; hornbill
+ f6f0; horse
+ f7ab; horse-head
+ f0f8; hospital
+ f47d; hospital-alt
+ f47e; hospital-symbol
+ f80d; hospital-user
+ f593; hot-tub
+ f80f; hotdog
+ f594; hotel
+ f3b1; hotjar
+ f254; hourglass
+ f253; hourglass-end
+ f252; hourglass-half
+ f251; hourglass-start
+ f6f1; house-damage
+ e065; house-use
+ f27c; houzz
+ f6f2; hryvnia
+ f13b; html5
+ f3b2; hubspot
+ f246; i-cursor
+ f810; ice-cream
+ f7ad; icicles
+ f86d; icons
+ f2c1; id-badge
+ f2c2; id-card
+ f47f; id-card-alt
+ e013; idea
+ f7ae; igloo
+ f03e; image
+ f302; images
+ f2d8; imdb
+ f01c; inbox
+ f03c; indent
+ f275; industry
+ f534; infinity
+ f129; info
+ f05a; info-circle
+ e080; innosof
+ f16d; instagram
+ e055; instagram-squar
+ e081; instalo
+ f7af; intercom
+ f26b; internet-explorer
+ f7b0; invision
+ f208; ioxhost
+ f033; italic
+ f83a; itch-io
+ f3b4; itunes
+ f3b5; itunes-note
+ f4e4; java
+ f669; jedi
+ f50e; jedi-order
+ f3b6; jenkins
+ f7b1; jira
+ f3b7; joget
+ f595; joint
+ f1aa; joomla
+ f66a; journal-whills
+ f3b8; js
+ f3b9; js-square
+ f1cc; jsfiddle
+ f66b; kaaba
+ f5fa; kaggle
+ f084; key
+ f4f5; keybase
+ f11c; keyboard
+ f3ba; keycdn
+ f66d; khanda
+ f3bb; kickstarter
+ f3bc; kickstarter-k
+ f596; kiss
+ f597; kiss-beam
+ f598; kiss-wink-heart
+ f535; kiwi-bird
+ f42f; korvue
+ f66f; landmark
+ f1ab; language
+ f109; laptop
+ f5fc; laptop-code
+ e066; laptop-hous
+ f812; laptop-medical
+ f3bd; laravel
+ f202; lastfm
+ f203; lastfm-square
+ f599; laugh
+ f59a; laugh-beam
+ f59b; laugh-squint
+ f59c; laugh-wink
+ f5fd; layer-group
+ f06c; leaf
+ f212; leanpub
+ f094; lemon
+ f41d; less
+ f536; less-than
+ f537; less-than-equal
+ f3be; level-down-alt
+ f3bf; level-up-alt
+ f1cd; life-ring
+ f0eb; lightbulb
+ f3c0; line
+ f0c1; link
+ f08c; linkedin
+ f0e1; linkedin-in
+ f2b8; linode
+ f17c; linux
+ f195; lira-sign
+ f03a; list
+ f022; list-alt
+ f0cb; list-ol
+ f0ca; list-ul
+ f124; location-arrow
+ f023; lock
+ f3c1; lock-open
+ f309; long-arrow-alt-down
+ f30a; long-arrow-alt-left
+ f30b; long-arrow-alt-right
+ f30c; long-arrow-alt-up
+ f2a8; low-vision
+ f59d; luggage-cart
+ f604; lungs
+ e067; lungs-viru
+ f3c3; lyft
+ f3c4; magento
+ f0d0; magic
+ f076; magnet
+ f674; mail-bulk
+ f59e; mailchimp
+ f183; male
+ f50f; mandalorian
+ f279; map
+ f59f; map-marked
+ f5a0; map-marked-alt
+ f041; map-marker
+ f3c5; map-marker-alt
+ f276; map-pin
+ f277; map-signs
+ f60f; markdown
+ f5a1; marker
+ f222; mars
+ f227; mars-double
+ f229; mars-stroke
+ f22b; mars-stroke-h
+ f22a; mars-stroke-v
+ f6fa; mask
+ f4f6; mastodon
+ f136; maxcdn
+ f8ca; mdb
+ f5a2; medal
+ f3c6; medapps
+ f23a; medium
+ f3c7; medium-m
+ f0fa; medkit
+ f3c8; medrt
+ f2e0; meetup
+ f5a3; megaport
+ f11a; meh
+ f5a4; meh-blank
+ f5a5; meh-rolling-eyes
+ f538; memory
+ f7b3; mendeley
+ f676; menorah
+ f223; mercury
+ f753; meteor
+ e01a; microblo
+ f2db; microchip
+ f130; microphone
+ f3c9; microphone-alt
+ f539; microphone-alt-slash
+ f131; microphone-slash
+ f610; microscope
+ f3ca; microsoft
+ f068; minus
+ f056; minus-circle
+ f146; minus-square
+ f7b5; mitten
+ f3cb; mix
+ f289; mixcloud
+ e056; mixe
+ f3cc; mizuni
+ f10b; mobile
+ f3cd; mobile-alt
+ f285; modx
+ f3d0; monero
+ f0d6; money-bill
+ f3d1; money-bill-alt
+ f53a; money-bill-wave
+ f53b; money-bill-wave-alt
+ f53c; money-check
+ f53d; money-check-alt
+ f5a6; monument
+ f186; moon
+ f5a7; mortar-pestle
+ f678; mosque
+ f21c; motorcycle
+ f6fc; mountain
+ f8cc; mouse
+ f245; mouse-pointer
+ f7b6; mug-hot
+ f001; music
+ f3d2; napster
+ f612; neos
+ f6ff; network-wired
+ f22c; neuter
+ f1ea; newspaper
+ f5a8; nimblr
+ f419; node
+ f3d3; node-js
+ f53e; not-equal
+ f481; notes-medical
+ f3d4; npm
+ f3d5; ns8
+ f3d6; nutritionix
+ f247; object-group
+ f248; object-ungroup
+ e082; octopus-deplo
+ f263; odnoklassniki
+ f264; odnoklassniki-square
+ f613; oil-can
+ f510; old-republic
+ f679; om
+ f23d; opencart
+ f19b; openid
+ f26a; opera
+ f23c; optin-monster
+ f8d2; orcid
+ f41a; osi
+ f700; otter
+ f03b; outdent
+ f3d7; page4
+ f18c; pagelines
+ f815; pager
+ f1fc; paint-brush
+ f5aa; paint-roller
+ f53f; palette
+ f3d8; palfed
+ f482; pallet
+ f1d8; paper-plane
+ f0c6; paperclip
+ f4cd; parachute-box
+ f1dd; paragraph
+ f540; parking
+ f5ab; passport
+ f67b; pastafarianism
+ f0ea; paste
+ f3d9; patreon
+ f04c; pause
+ f28b; pause-circle
+ f1b0; paw
+ f1ed; paypal
+ f67c; peace
+ f304; pen
+ f305; pen-alt
+ f5ac; pen-fancy
+ f5ad; pen-nib
+ f14b; pen-square
+ f303; pencil-alt
+ f5ae; pencil-ruler
+ f704; penny-arcade
+ e068; people-arrow
+ f4ce; people-carry
+ f816; pepper-hot
+ e083; perbyt
+ f295; percent
+ f541; percentage
+ f3da; periscope
+ f756; person-booth
+ f3db; phabricator
+ f3dc; phoenix-framework
+ f511; phoenix-squadron
+ f095; phone
+ f879; phone-alt
+ f3dd; phone-slash
+ f098; phone-square
+ f87b; phone-square-alt
+ f2a0; phone-volume
+ f87c; photo-video
+ f457; php
+ f2ae; pied-piper
+ f1a8; pied-piper-alt
+ f4e5; pied-piper-hat
+ f1a7; pied-piper-pp
+ e01e; pied-piper-squar
+ f4d3; piggy-bank
+ f484; pills
+ f0d2; pinterest
+ f231; pinterest-p
+ f0d3; pinterest-square
+ f818; pizza-slice
+ f67f; place-of-worship
+ f072; plane
+ f5af; plane-arrival
+ f5b0; plane-departure
+ e069; plane-slas
+ f04b; play
+ f144; play-circle
+ f3df; playstation
+ f1e6; plug
+ f067; plus
+ f055; plus-circle
+ f0fe; plus-square
+ f2ce; podcast
+ f681; poll
+ f682; poll-h
+ f2fe; poo
+ f75a; poo-storm
+ f619; poop
+ f3e0; portrait
+ f154; pound-sign
+ f011; power-off
+ f683; pray
+ f684; praying-hands
+ f5b1; prescription
+ f485; prescription-bottle
+ f486; prescription-bottle-alt
+ f02f; print
+ f487; procedures
+ f288; product-hunt
+ f542; project-diagram
+ e06a; pump-medica
+ e06b; pump-soa
+ f3e1; pushed
+ f12e; puzzle-piece
+ f3e2; python
+ f1d6; qq
+ f029; qrcode
+ f128; question
+ f059; question-circle
+ f458; quidditch
+ f459; quinscape
+ f2c4; quora
+ f10d; quote-left
+ f10e; quote-right
+ f687; quran
+ f4f7; r-project
+ f7b9; radiation
+ f7ba; radiation-alt
+ f75b; rainbow
+ f074; random
+ f7bb; raspberry-pi
+ f2d9; ravelry
+ f41b; react
+ f75d; reacteurope
+ f4d5; readme
+ f1d0; rebel
+ f543; receipt
+ f8d9; record-vinyl
+ f1b8; recycle
+ f3e3; red-river
+ f1a1; reddit
+ f281; reddit-alien
+ f1a2; reddit-square
+ f7bc; redhat
+ f01e; redo
+ f2f9; redo-alt
+ f25d; registered
+ f87d; remove-format
+ f18b; renren
+ f3e5; reply
+ f122; reply-all
+ f3e6; replyd
+ f75e; republican
+ f4f8; researchgate
+ f3e7; resolving
+ f7bd; restroom
+ f079; retweet
+ f5b2; rev
+ f4d6; ribbon
+ f70b; ring
+ f018; road
+ f544; robot
+ f135; rocket
+ f3e8; rocketchat
+ f3e9; rockrms
+ f4d7; route
+ f09e; rss
+ f143; rss-square
+ f158; ruble-sign
+ f545; ruler
+ f546; ruler-combined
+ f547; ruler-horizontal
+ f548; ruler-vertical
+ f70c; running
+ f156; rupee-sign
+ e07a; rus
+ f5b3; sad-cry
+ f5b4; sad-tear
+ f267; safari
+ f83b; salesforce
+ f41e; sass
+ f7bf; satellite
+ f7c0; satellite-dish
+ f0c7; save
+ f3ea; schlix
+ f549; school
+ f54a; screwdriver
+ f28a; scribd
+ f70e; scroll
+ f7c2; sd-card
+ f002; search
+ f688; search-dollar
+ f689; search-location
+ f010; search-minus
+ f00e; search-plus
+ f3eb; searchengin
+ f4d8; seedling
+ f2da; sellcast
+ f213; sellsy
+ f233; server
+ f3ec; servicestack
+ f61f; shapes
+ f064; share
+ f1e0; share-alt
+ f1e1; share-alt-square
+ f14d; share-square
+ f20b; shekel-sign
+ f3ed; shield-alt
+ e06c; shield-viru
+ f21a; ship
+ f48b; shipping-fast
+ f214; shirtsinbulk
+ f54b; shoe-prints
+ e057; shopif
+ f290; shopping-bag
+ f291; shopping-basket
+ f07a; shopping-cart
+ f5b5; shopware
+ f2cc; shower
+ f5b6; shuttle-van
+ f4d9; sign
+ f2f6; sign-in-alt
+ f2a7; sign-language
+ f2f5; sign-out-alt
+ f012; signal
+ f5b7; signature
+ f7c4; sim-card
+ f215; simplybuilt
+ e06d; sin
+ f3ee; sistrix
+ f0e8; sitemap
+ f512; sith
+ f7c5; skating
+ f7c6; sketch
+ f7c9; skiing
+ f7ca; skiing-nordic
+ f54c; skull
+ f714; skull-crossbones
+ f216; skyatlas
+ f17e; skype
+ f198; slack
+ f3ef; slack-hash
+ f715; slash
+ f7cc; sleigh
+ f1de; sliders-h
+ f1e7; slideshare
+ f118; smile
+ f5b8; smile-beam
+ f4da; smile-wink
+ f75f; smog
+ f48d; smoking
+ f54d; smoking-ban
+ f7cd; sms
+ f2ab; snapchat
+ f2ac; snapchat-ghost
+ f2ad; snapchat-square
+ f7ce; snowboarding
+ f2dc; snowflake
+ f7d0; snowman
+ f7d2; snowplow
+ e06e; soa
+ f696; socks
+ f5ba; solar-panel
+ f0dc; sort
+ f15d; sort-alpha-down
+ f881; sort-alpha-down-alt
+ f15e; sort-alpha-up
+ f882; sort-alpha-up-alt
+ f160; sort-amount-down
+ f884; sort-amount-down-alt
+ f161; sort-amount-up
+ f885; sort-amount-up-alt
+ f0dd; sort-down
+ f162; sort-numeric-down
+ f886; sort-numeric-down-alt
+ f163; sort-numeric-up
+ f887; sort-numeric-up-alt
+ f0de; sort-up
+ f1be; soundcloud
+ f7d3; sourcetree
+ f5bb; spa
+ f197; space-shuttle
+ f3f3; speakap
+ f83c; speaker-deck
+ f891; spell-check
+ f717; spider
+ f110; spinner
+ f5bc; splotch
+ f1bc; spotify
+ f5bd; spray-can
+ f0c8; square
+ f45c; square-full
+ f698; square-root-alt
+ f5be; squarespace
+ f18d; stack-exchange
+ f16c; stack-overflow
+ f842; stackpath
+ f5bf; stamp
+ f005; star
+ f699; star-and-crescent
+ f089; star-half
+ f5c0; star-half-alt
+ f69a; star-of-david
+ f621; star-of-life
+ f3f5; staylinked
+ f1b6; steam
+ f1b7; steam-square
+ f3f6; steam-symbol
+ f048; step-backward
+ f051; step-forward
+ f0f1; stethoscope
+ f3f7; sticker-mule
+ f249; sticky-note
+ f04d; stop
+ f28d; stop-circle
+ f2f2; stopwatch
+ e06f; stopwatch-2
+ f54e; store
+ f54f; store-alt
+ e070; store-alt-slas
+ e071; store-slas
+ f428; strava
+ f550; stream
+ f21d; street-view
+ f0cc; strikethrough
+ f429; stripe
+ f42a; stripe-s
+ f551; stroopwafel
+ f3f8; studiovinari
+ f1a4; stumbleupon
+ f1a3; stumbleupon-circle
+ f12c; subscript
+ f239; subway
+ f0f2; suitcase
+ f5c1; suitcase-rolling
+ f185; sun
+ f2dd; superpowers
+ f12b; superscript
+ f3f9; supple
+ f5c2; surprise
+ f7d6; suse
+ f5c3; swatchbook
+ f8e1; swift
+ f5c4; swimmer
+ f5c5; swimming-pool
+ f83d; symfony
+ f69b; synagogue
+ f021; sync
+ f2f1; sync-alt
+ f48e; syringe
+ f0ce; table
+ f45d; table-tennis
+ f10a; tablet
+ f3fa; tablet-alt
+ f490; tablets
+ f3fd; tachometer-alt
+ f02b; tag
+ f02c; tags
+ f4db; tape
+ f0ae; tasks
+ f1ba; taxi
+ f4f9; teamspeak
+ f62e; teeth
+ f62f; teeth-open
+ f2c6; telegram
+ f3fe; telegram-plane
+ f769; temperature-high
+ f76b; temperature-low
+ f1d5; tencent-weibo
+ f7d7; tenge
+ f120; terminal
+ f034; text-height
+ f035; text-width
+ f00a; th
+ f009; th-large
+ f00b; th-list
+ f69d; the-red-yeti
+ f630; theater-masks
+ f5c6; themeco
+ f2b2; themeisle
+ f491; thermometer
+ f2cb; thermometer-empty
+ f2c7; thermometer-full
+ f2c9; thermometer-half
+ f2ca; thermometer-quarter
+ f2c8; thermometer-three-quarters
+ f731; think-peaks
+ f165; thumbs-down
+ f164; thumbs-up
+ f08d; thumbtack
+ f3ff; ticket-alt
+ e07b; tikto
+ f00d; times
+ f057; times-circle
+ f043; tint
+ f5c7; tint-slash
+ f5c8; tired
+ f204; toggle-off
+ f205; toggle-on
+ f7d8; toilet
+ f71e; toilet-paper
+ e072; toilet-paper-slas
+ f552; toolbox
+ f7d9; tools
+ f5c9; tooth
+ f6a0; torah
+ f6a1; torii-gate
+ f722; tractor
+ f513; trade-federation
+ f25c; trademark
+ f637; traffic-light
+ e041; traile
+ f238; train
+ f7da; tram
+ f224; transgender
+ f225; transgender-alt
+ f1f8; trash
+ f2ed; trash-alt
+ f829; trash-restore
+ f82a; trash-restore-alt
+ f1bb; tree
+ f181; trello
+ f091; trophy
+ f0d1; truck
+ f4de; truck-loading
+ f63b; truck-monster
+ f4df; truck-moving
+ f63c; truck-pickup
+ f553; tshirt
+ f1e4; tty
+ f173; tumblr
+ f174; tumblr-square
+ f26c; tv
+ f1e8; twitch
+ f099; twitter
+ f081; twitter-square
+ f42b; typo3
+ f402; uber
+ f7df; ubuntu
+ f403; uikit
+ f8e8; umbraco
+ f0e9; umbrella
+ f5ca; umbrella-beach
+ e084; uncharte
+ f0cd; underline
+ f0e2; undo
+ f2ea; undo-alt
+ f404; uniregistry
+ e049; unit
+ f29a; universal-access
+ f19c; university
+ f127; unlink
+ f09c; unlock
+ f13e; unlock-alt
+ e07c; unsplas
+ f405; untappd
+ f093; upload
+ f7e0; ups
+ f287; usb
+ f007; user
+ f406; user-alt
+ f4fa; user-alt-slash
+ f4fb; user-astronaut
+ f4fc; user-check
+ f2bd; user-circle
+ f4fd; user-clock
+ f4fe; user-cog
+ f4ff; user-edit
+ f500; user-friends
+ f501; user-graduate
+ f728; user-injured
+ f502; user-lock
+ f0f0; user-md
+ f503; user-minus
+ f504; user-ninja
+ f82f; user-nurse
+ f234; user-plus
+ f21b; user-secret
+ f505; user-shield
+ f506; user-slash
+ f507; user-tag
+ f508; user-tie
+ f235; user-times
+ f0c0; users
+ f509; users-cog
+ e073; users-slas
+ f7e1; usps
+ f407; ussunnah
+ f2e5; utensil-spoon
+ f2e7; utensils
+ f408; vaadin
+ f5cb; vector-square
+ f221; venus
+ f226; venus-double
+ f228; venus-mars
+ e085; ves
+ e086; vest-patche
+ f237; viacoin
+ f2a9; viadeo
+ f2aa; viadeo-square
+ f492; vial
+ f493; vials
+ f409; viber
+ f03d; video
+ f4e2; video-slash
+ f6a7; vihara
+ f40a; vimeo
+ f194; vimeo-square
+ f27d; vimeo-v
+ f1ca; vine
+ e074; viru
+ e075; virus-slas
+ e076; viruse
+ f189; vk
+ f40b; vnv
+ f897; voicemail
+ f45f; volleyball-ball
+ f027; volume-down
+ f6a9; volume-mute
+ f026; volume-off
+ f028; volume-up
+ f772; vote-yea
+ f729; vr-cardboard
+ f41f; vuejs
+ f554; walking
+ f555; wallet
+ f494; warehouse
+ e087; watchman-monitorin
+ f773; water
+ f83e; wave-square
+ f83f; waze
+ f5cc; weebly
+ f18a; weibo
+ f496; weight
+ f5cd; weight-hanging
+ f1d7; weixin
+ f232; whatsapp
+ f40c; whatsapp-square
+ f193; wheelchair
+ f40d; whmcs
+ f1eb; wifi
+ f266; wikipedia-w
+ f72e; wind
+ f410; window-close
+ f2d0; window-maximize
+ f2d1; window-minimize
+ f2d2; window-restore
+ f17a; windows
+ f72f; wine-bottle
+ f4e3; wine-glass
+ f5ce; wine-glass-alt
+ f5cf; wix
+ f730; wizards-of-the-coast
+ e088; wod
+ f514; wolf-pack-battalion
+ f159; won-sign
+ f19a; wordpress
+ f411; wordpress-simple
+ f297; wpbeginner
+ f2de; wpexplorer
+ f298; wpforms
+ f3e4; wpressr
+ f0ad; wrench
+ f497; x-ray
+ f412; xbox
+ f168; xing
+ f169; xing-square
+ f23b; y-combinator
+ f19e; yahoo
+ f840; yammer
+ f413; yandex
+ f414; yandex-international
+ f7e3; yarn
+ f1e9; yelp
+ f157; yen-sign
+ f6ad; yin-yang
+ f2b1; yoast
+ f167; youtube
+ f431; youtube-square
+ f63f; zhihu
diff --git a/.local/share/chars/unicode b/.local/share/chars/unicode
new file mode 100644
index 0000000..dfbc814
--- /dev/null
+++ b/.local/share/chars/unicode
Binary files differ
diff --git a/.profile b/.profile
new file mode 120000
index 0000000..5eae43a
--- /dev/null
+++ b/.profile
@@ -0,0 +1 @@
+/home/master/.config/shell/profile \ No newline at end of file
diff --git a/.xprofile b/.xprofile
new file mode 120000
index 0000000..8fb625c
--- /dev/null
+++ b/.xprofile
@@ -0,0 +1 @@
+/home/master/.config/X11/xprofile \ No newline at end of file
diff --git a/.zprofile b/.zprofile
new file mode 120000
index 0000000..17a69c2
--- /dev/null
+++ b/.zprofile
@@ -0,0 +1 @@
+/home/master/.config/zsh/zprofile \ No newline at end of file
diff --git a/gtkrc-2.0 b/gtkrc-2.0
new file mode 100644
index 0000000..73dbc57
--- /dev/null
+++ b/gtkrc-2.0
@@ -0,0 +1,19 @@
+# DO NOT EDIT! This file will be overwritten by LXAppearance.
+# Any customization should be done in ~/.gtkrc-2.0.mine instead.
+
+include "/home/master/.gtkrc-2.0.mine"
+gtk-theme-name="Arc-Dark"
+gtk-icon-theme-name="Gruvbox-Plus-Dark"
+gtk-font-name="Fira Sans 14"
+gtk-cursor-theme-size=24
+gtk-toolbar-style=GTK_TOOLBAR_ICONS
+gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
+gtk-button-images=1
+gtk-menu-images=1
+gtk-enable-event-sounds=1
+gtk-enable-input-feedback-sounds=1
+gtk-xft-antialias=1
+gtk-xft-hinting=1
+gtk-xft-hintstyle="hintmedium"
+gtk-xft-rgba="none"
+gtk-modules="canberra-gtk-module:gail:atk-bridge"